Compare commits
No commits in common. 'main' and 'master' have entirely different histories.
@ -1,132 +1,17 @@
|
|||||||
# ---> Node
|
# npm 构建产物
|
||||||
# Logs
|
miniprogram_npm/
|
||||||
logs
|
dist/
|
||||||
*.log
|
build/
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
# node_modules
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
node_modules/
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# Snowpack dependency directory (https://snowpack.dev/)
|
|
||||||
web_modules/
|
|
||||||
|
|
||||||
# TypeScript cache
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Optional stylelint cache
|
|
||||||
.stylelintcache
|
|
||||||
|
|
||||||
# Microbundle cache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
# 缓存文件
|
||||||
*.tgz
|
npm-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
# Yarn Integrity file
|
*.lock
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variable files
|
|
||||||
.env
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
.env.local
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
.parcel-cache
|
|
||||||
|
|
||||||
# Next.js build output
|
|
||||||
.next
|
|
||||||
out
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
|
||||||
.nuxt
|
|
||||||
dist
|
|
||||||
|
|
||||||
# Gatsby files
|
|
||||||
.cache/
|
|
||||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
||||||
# public
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# vuepress v2.x temp and cache directory
|
|
||||||
.temp
|
|
||||||
.cache
|
|
||||||
|
|
||||||
# Docusaurus cache and generated files
|
|
||||||
.docusaurus
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# TernJS port file
|
|
||||||
.tern-port
|
|
||||||
|
|
||||||
# Stores VSCode versions used for testing VSCode extensions
|
|
||||||
.vscode-test
|
|
||||||
|
|
||||||
# yarn v2
|
|
||||||
.yarn/cache
|
|
||||||
.yarn/unplugged
|
|
||||||
.yarn/build-state.yml
|
|
||||||
.yarn/install-state.gz
|
|
||||||
.pnp.*
|
|
||||||
|
|
||||||
|
# 开发工具临时文件
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
// app.js
|
||||||
|
const { isAuthenticated } = require('./utils/token');
|
||||||
|
|
||||||
|
App({
|
||||||
|
onLaunch() {
|
||||||
|
// 展示本地存储能力
|
||||||
|
const logs = wx.getStorageSync('logs') || []
|
||||||
|
logs.unshift(Date.now())
|
||||||
|
wx.setStorageSync('logs', logs)
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
wx.login({
|
||||||
|
success: res => {
|
||||||
|
// 发送 res.code 到后台换取 openId, sessionKey, unionId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 检查token有效性并自动跳转
|
||||||
|
this.checkTokenAndRedirect();
|
||||||
|
},
|
||||||
|
|
||||||
|
globalData: {
|
||||||
|
userInfo: null
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查token有效性并自动跳转到相应页面
|
||||||
|
*/
|
||||||
|
checkTokenAndRedirect() {
|
||||||
|
if (isAuthenticated()) {
|
||||||
|
console.log('用户已认证,跳转到首页');
|
||||||
|
// 如果用户已经登录,跳转到首页
|
||||||
|
wx.switchTab({
|
||||||
|
url: '/pages/index/index',
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('跳转到首页失败:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('用户未认证,跳转到登录页');
|
||||||
|
// 如果用户未登录,跳转到登录页
|
||||||
|
wx.redirectTo({
|
||||||
|
url: '/pages/login/login',
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('跳转到登录页失败:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"pages": [
|
||||||
|
"pages/login/login",
|
||||||
|
"pages/index/index",
|
||||||
|
"pages/category/category",
|
||||||
|
"pages/mine/mine"
|
||||||
|
],
|
||||||
|
"window": {
|
||||||
|
"backgroundTextStyle": "light",
|
||||||
|
"navigationBarBackgroundColor": "#fff",
|
||||||
|
"navigationBarTitleText": "底部TabBar示例",
|
||||||
|
"navigationBarTextStyle": "black"
|
||||||
|
},
|
||||||
|
"tabBar": {
|
||||||
|
"color": "#dbdbdb",
|
||||||
|
"selectedColor": "#fff",
|
||||||
|
"backgroundColor": "#FF9966",
|
||||||
|
"borderStyle": "black",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"pagePath": "pages/index/index",
|
||||||
|
"text": "首页",
|
||||||
|
"iconPath": "img/tab/home_active.png",
|
||||||
|
"selectedIconPath": "img/tab/home.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/category/category",
|
||||||
|
"text": "分类",
|
||||||
|
"iconPath": "img/tab/category_active.png",
|
||||||
|
"selectedIconPath": "img/tab/category.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/mine/mine",
|
||||||
|
"text": "我的",
|
||||||
|
"iconPath": "img/tab/mine_active.png",
|
||||||
|
"selectedIconPath": "img/tab/mine.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"requiredPrivateInfos": ["getLocation"],
|
||||||
|
"permission": {
|
||||||
|
"scope.userLocation": {
|
||||||
|
"desc": "你的位置信息将用于获取当前位置并在地图上显示"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"componentFramework": "glass-easel",
|
||||||
|
"sitemapLocation": "sitemap.json",
|
||||||
|
"lazyCodeLoading": "requiredComponents"
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
/**app.wxss**/
|
||||||
|
.container {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 200rpx 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "wxapp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"node_modules/@vant/weapp": {
|
||||||
|
"version": "1.11.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vant/weapp/-/weapp-1.11.7.tgz",
|
||||||
|
"integrity": "sha512-Rwn9BBnb4kHSV4XmvBicwtd42J+amEUfnFDcXJsGNPNX4a9c/DoT6YLsm4X1wB2+sQbdiQsbFBLAvGRBxCkD8g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/ant-design-mini": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ant-design-mini/-/ant-design-mini-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-pMtB6VUth5FVaSKho/rl7oDTrYl3cuuckDrEkDeTwqdiylfe2nm5OOomWg+oujpl8XV/SCpUOqmRybfBDOjXDg==",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "ant-design-mini",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "ant-design-mini",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "liumin",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
console.log('hello world')
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "wxapp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "wxapp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@vant/weapp": "^1.11.7",
|
||||||
|
"ant-design-mini": "^0.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {}
|
||||||
|
},
|
||||||
|
"node_modules/@vant/weapp": {
|
||||||
|
"version": "1.11.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vant/weapp/-/weapp-1.11.7.tgz",
|
||||||
|
"integrity": "sha512-Rwn9BBnb4kHSV4XmvBicwtd42J+amEUfnFDcXJsGNPNX4a9c/DoT6YLsm4X1wB2+sQbdiQsbFBLAvGRBxCkD8g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/ant-design-mini": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ant-design-mini/-/ant-design-mini-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-pMtB6VUth5FVaSKho/rl7oDTrYl3cuuckDrEkDeTwqdiylfe2nm5OOomWg+oujpl8XV/SCpUOqmRybfBDOjXDg==",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "wxapp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "app.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "YuLeYuan",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@vant/weapp": "^1.11.7",
|
||||||
|
"ant-design-mini": "^0.0.1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://bdgit.educoder.net/pq54ntls9/nodejs-wxapp-learning.git"
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
// pages/category/category.js
|
||||||
|
Page({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面的初始数据
|
||||||
|
*/
|
||||||
|
data: {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面加载
|
||||||
|
*/
|
||||||
|
onLoad(options) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面初次渲染完成
|
||||||
|
*/
|
||||||
|
onReady() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面显示
|
||||||
|
*/
|
||||||
|
onShow() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面隐藏
|
||||||
|
*/
|
||||||
|
onHide() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面卸载
|
||||||
|
*/
|
||||||
|
onUnload() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面相关事件处理函数--监听用户下拉动作
|
||||||
|
*/
|
||||||
|
onPullDownRefresh() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面上拉触底事件的处理函数
|
||||||
|
*/
|
||||||
|
onReachBottom() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户点击右上角分享
|
||||||
|
*/
|
||||||
|
onShareAppMessage() {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
<!--pages/category/category.wxml-->
|
||||||
|
<text>pages/category/category.wxml</text>
|
||||||
@ -0,0 +1 @@
|
|||||||
|
/* pages/category/category.wxss */
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
// pages/home/home.js
|
||||||
|
Page({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面的初始数据
|
||||||
|
*/
|
||||||
|
data: {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面加载
|
||||||
|
*/
|
||||||
|
onLoad(options) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面初次渲染完成
|
||||||
|
*/
|
||||||
|
onReady() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面显示
|
||||||
|
*/
|
||||||
|
onShow() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面隐藏
|
||||||
|
*/
|
||||||
|
onHide() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生命周期函数--监听页面卸载
|
||||||
|
*/
|
||||||
|
onUnload() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面相关事件处理函数--监听用户下拉动作
|
||||||
|
*/
|
||||||
|
onPullDownRefresh() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面上拉触底事件的处理函数
|
||||||
|
*/
|
||||||
|
onReachBottom() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户点击右上角分享
|
||||||
|
*/
|
||||||
|
onShareAppMessage() {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<!--pages/home/home.wxml-->
|
||||||
|
<text>pages/home/home.wxml</text>
|
||||||
|
<view>
|
||||||
|
|
||||||
|
</view>
|
||||||
@ -0,0 +1 @@
|
|||||||
|
/* pages/home/home.wxss */
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {},
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
"backgroundTextStyle": "dark"
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
<!--pages/index/index.wxml-->
|
||||||
|
<view class="container">
|
||||||
|
<!-- 页面标题 -->
|
||||||
|
<view class="header">
|
||||||
|
<text class="title">商品列表</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<view wx:if="{{loading}}" class="loading-container">
|
||||||
|
<text>加载中...</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 错误状态 -->
|
||||||
|
<view wx:elif="{{hasError}}" class="error-container">
|
||||||
|
<text class="error-msg">{{errorMsg}}</text>
|
||||||
|
<button bindtap="getProductList" class="retry-btn">重新加载</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 商品列表 -->
|
||||||
|
<view wx:else class="product-list">
|
||||||
|
<view
|
||||||
|
wx:for="{{productList}}"
|
||||||
|
wx:key="id"
|
||||||
|
class="product-item"
|
||||||
|
bindtap="onProductTap"
|
||||||
|
data-product="{{item}}"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
src="{{item.imageUrl || 'https://via.placeholder.com/200x200'}}"
|
||||||
|
class="product-image"
|
||||||
|
mode="aspectFill"
|
||||||
|
lazy-load="{{true}}"
|
||||||
|
/>
|
||||||
|
<view class="product-info">
|
||||||
|
<text class="product-name">{{item.name}}</text>
|
||||||
|
<text class="product-price">¥{{item.price}}</text>
|
||||||
|
<text class="product-description">{{item.description}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view wx:if="{{productList.length === 0}}" class="empty-state">
|
||||||
|
<text>暂无商品</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
@ -0,0 +1,110 @@
|
|||||||
|
/* pages/index/index.wxss */
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 20rpx;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 20rpx 0;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-container,
|
||||||
|
.error-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 200rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-container {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-msg {
|
||||||
|
color: #ff4d4f;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-btn {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: white;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 10rpx 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-item {
|
||||||
|
display: flex;
|
||||||
|
background: white;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-image {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-info {
|
||||||
|
flex: 1;
|
||||||
|
padding: 20rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-name {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
display: block;
|
||||||
|
/* 限制一行显示,超出省略 */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-price {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #ff6b35;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-description {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
display: block;
|
||||||
|
/* 限制两行显示,超出省略 */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 100rpx 0;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"navigationBarTitleText": "登录",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"usingComponents": {
|
||||||
|
"van-field": "@vant/weapp/field/index",
|
||||||
|
"van-button": "@vant/weapp/button/index"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
<view class="login-container">
|
||||||
|
<!-- Vant 输入框:账号/手机号 -->
|
||||||
|
<van-field
|
||||||
|
v-model="{{account}}"
|
||||||
|
label="账号"
|
||||||
|
placeholder="请输入账号/手机号"
|
||||||
|
border="{{true}}"
|
||||||
|
bind:change="handleAccountInput"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Vant 输入框:密码(加密显示) -->
|
||||||
|
<van-field
|
||||||
|
v-model="{{password}}"
|
||||||
|
label="密码"
|
||||||
|
type="password"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
border="{{true}}"
|
||||||
|
bind:change="handlePasswordInput"
|
||||||
|
clearable="{{true}}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Vant 按钮组 -->
|
||||||
|
<view class="btn-group">
|
||||||
|
<van-button
|
||||||
|
type="primary"
|
||||||
|
size="large"
|
||||||
|
bind:click="handleLogin"
|
||||||
|
style="flex:1;margin-right:10rpx;"
|
||||||
|
>登录</van-button>
|
||||||
|
<van-button
|
||||||
|
type="default"
|
||||||
|
size="large"
|
||||||
|
bind:click="handleReset"
|
||||||
|
style="flex:1;"
|
||||||
|
>重置</van-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
.login-container {
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"navigationBarTitleText": "地图定位",
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<view class="container">
|
||||||
|
<!-- 地图组件 - 占满全屏 -->
|
||||||
|
<map
|
||||||
|
id="myMap"
|
||||||
|
longitude="{{longitude}}"
|
||||||
|
latitude="{{latitude}}"
|
||||||
|
scale="{{scale}}"
|
||||||
|
markers="{{markers}}"
|
||||||
|
style="width: 100%; height: 100%;">
|
||||||
|
</map>
|
||||||
|
|
||||||
|
<!-- 悬浮定位按钮 -->
|
||||||
|
<button class="locate-btn" bindtap="getCurrentLocation">定位当前位置</button>
|
||||||
|
</view>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
.container{
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.locate-btn {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 40rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
z-index: 999;
|
||||||
|
padding: 20rpx 40rpx;
|
||||||
|
background-color: #007aff;
|
||||||
|
color: white;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
border: none;
|
||||||
|
font-size: 32rpx;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2);
|
||||||
|
min-width: 200rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"compileType": "miniprogram",
|
||||||
|
"libVersion": "3.14.2",
|
||||||
|
"packOptions": {
|
||||||
|
"ignore": [],
|
||||||
|
"include": []
|
||||||
|
},
|
||||||
|
"setting": {
|
||||||
|
"coverView": true,
|
||||||
|
"es6": true,
|
||||||
|
"postcss": true,
|
||||||
|
"minified": true,
|
||||||
|
"enhance": true,
|
||||||
|
"showShadowRootInWxmlPanel": true,
|
||||||
|
"babelSetting": {
|
||||||
|
"ignore": [],
|
||||||
|
"disablePlugins": [],
|
||||||
|
"outputPath": ""
|
||||||
|
},
|
||||||
|
"compileWorklet": false,
|
||||||
|
"uglifyFileName": false,
|
||||||
|
"uploadWithSourceMap": true,
|
||||||
|
"packNpmManually": true,
|
||||||
|
"packNpmRelationList": [
|
||||||
|
{
|
||||||
|
"packageJsonPath": "./package.json",
|
||||||
|
"miniprogramNpmDistDir": "./"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"useCompilerPlugins": [],
|
||||||
|
"minifyWXSS": true,
|
||||||
|
"minifyWXML": true,
|
||||||
|
"localPlugins": false,
|
||||||
|
"condition": false,
|
||||||
|
"swc": false,
|
||||||
|
"disableSWC": true,
|
||||||
|
"disableUseStrict": false
|
||||||
|
},
|
||||||
|
"condition": {},
|
||||||
|
"editorSetting": {
|
||||||
|
"tabIndent": "auto",
|
||||||
|
"tabSize": 2
|
||||||
|
},
|
||||||
|
"appid": "wx9bfeebe2956c4c5b",
|
||||||
|
"simulatorPluginLibVersion": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
|
||||||
|
"rules": [{
|
||||||
|
"action": "allow",
|
||||||
|
"page": "*"
|
||||||
|
}]
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
const formatTime = date => {
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = date.getMonth() + 1
|
||||||
|
const day = date.getDate()
|
||||||
|
const hour = date.getHours()
|
||||||
|
const minute = date.getMinutes()
|
||||||
|
const second = date.getSeconds()
|
||||||
|
|
||||||
|
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatNumber = n => {
|
||||||
|
n = n.toString()
|
||||||
|
return n[1] ? n : `0${n}`
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
formatTime
|
||||||
|
}
|
||||||