diff --git a/front-end/mall4uni/src/app.css b/front-end/mall4uni/src/app.css index 8ff70e1..af2239e 100644 --- a/front-end/mall4uni/src/app.css +++ b/front-end/mall4uni/src/app.css @@ -1,108 +1,176 @@ -/**app.wxss**/ +/** app.wxss **/ + +/* + * 容器样式 + * 设置容器的高度为100%,确保其占据整个屏幕高度。 + * 使用 border-box 模型,使得 padding 和 border 包含在元素的总宽度和高度内。 + * 设置文本颜色为 #333,并指定字体系列以确保跨平台一致性。 + */ .container { height: 100%; box-sizing: border-box; color: #333; - font-family: helvetica,'Heiti SC',PingFangSC-Light; + font-family: helvetica, 'Heiti SC', PingFangSC-Light; } -.price{ + +/* + * 价格样式 + * 设置价格的字体为 Arial,显示为行内块级元素,颜色为红色 (#eb2444)。 + * 添加底部和左侧的内边距,使价格与其他内容之间有适当的间距。 + */ +.price { font-family: Arial; display: inline-block; color: #eb2444; - padding-bottom:10rpx; - padding-left:10rpx; + padding-bottom: 10rpx; + padding-left: 10rpx; } -/* 价格数字显示不同大小 */ +/* + * 价格符号(如¥、$等)样式 + * 设置符号的字体大小为 24rpx。 + */ .symbol { font-size: 24rpx; } +/* + * 大号数字样式 + * 设置大号数字的字体大小为 32rpx。 + */ .big-num { font-size: 32rpx; } +/* + * 小号数字样式 + * 设置小号数字的字体大小为 24rpx。 + */ .small-num { font-size: 24rpx; } /* -*改变checkbox样式 -*自定义样式 -*/ -/* reg */ + * 改变checkbox样式 + * 自定义样式以适应应用设计 + */ + +/* + * checkbox 组样式 + * 设置 checkbox 组的宽度为 100%,确保其占满整个父容器。 + */ uni-checkbox-group { width: 100% !important; } -uni-checkbox-group uni-label{ - width: 33% !important; - display: inline-flex; - margin-bottom: 20rpx; -} -/*checkbox 选项框大小 */ -uni-checkbox .uni-checkbox-input{ + + /* + * checkbox 标签样式 + * 设置每个 checkbox 标签的宽度为 33%,并使用行内弹性布局,使其在一行中均匀分布。 + * 添加底部外边距,确保标签之间有足够的间距。 + */ + uni-checkbox-group uni-label { + width: 33% !important; + display: inline-flex; + margin-bottom: 20rpx; + } + +/* + * checkbox 选项框大小 + * 设置 checkbox 选项框的宽度和高度为 38rpx,并设置为圆形(border-radius: 50%)。 + */ +uni-checkbox .uni-checkbox-input { width: 38rpx !important; height: 38rpx !important; - border-radius: 50%!important; -} -/*checkbox选中后样式 */ -uni-checkbox .uni-checkbox-input.uni-checkbox-input-checked{ - background: #e43130; - border: 1px solid transparent !important; -} -/*checkbox选中后图标样式 */ -uni-checkbox .uni-checkbox-input.uni-checkbox-input-checked::before{ - display: inline-block; - width: 20rpx; - height: 20rpx; - line-height: 20rpx; - text-align: center; - font-size: 18rpx; - color: #fff; - background: transparent; - transform: translate(-60%, -50%) scale(1); - -webkit-transform: translate(-60%, -50%) scale(1); + border-radius: 50% !important; } + /* + * checkbox 选中后样式 + * 设置选中后的 checkbox 背景颜色为红色 (#e43130),并移除默认边框。 + */ + uni-checkbox .uni-checkbox-input.uni-checkbox-input-checked { + background: #e43130; + border: 1px solid transparent !important; + } + + /* + * checkbox 选中后图标样式 + * 设置选中后的 checkbox 图标的样式,包括尺寸、对齐方式、字体大小和颜色。 + * 使用 transform 属性调整图标的居中位置和缩放比例。 + */ + uni-checkbox .uni-checkbox-input.uni-checkbox-input-checked::before { + display: inline-block; + width: 20rpx; + height: 20rpx; + line-height: 20rpx; + text-align: center; + font-size: 18rpx; + color: #fff; + background: transparent; + transform: translate(-60%, -50%) scale(1); + -webkit-transform: translate(-60%, -50%) scale(1); + } + /* -*改变radio样式 -*自定义样式 -*/ -/* 未选中的 背景样式 */ -uni-radio .uni-radio-input{ + * 改变radio样式 + * 自定义样式以适应应用设计 + */ + +/* + * 未选中的 radio 背景样式 + * 设置未选中的 radio 选项框的高度和宽度为 36rpx,背景透明,并设置为圆形。 + */ +uni-radio .uni-radio-input { height: 36rpx; width: 36rpx; border-radius: 50%; background: transparent; box-sizing: border-box; } -/* 选中后的 背景样式 */ -uni-radio .uni-radio-input.uni-radio-input-checked{ - border: none !important; - background: #e43130 !important; -} -/* 选中后的 对勾样式 */ -uni-radio .uni-radio-input.uni-radio-input-checked::before{ - border-radius: 50%; - width: 32rpx; - height: 32rpx; - line-height: 32rpx; - text-align: center; - font-size: 20rpx; - color:#fff; - background: #e43130; - border-radius: 50%; - transform: translate(-50%, -50%) scale(1); - -webkit-transform: translate(-50%, -50%) scale(1); -} -/* 底部按钮兼容 iPhone X以上 */ -@media screen and (width: 375px) and (height: 812px){ + /* + * 选中后的 radio 背景样式 + * 设置选中后的 radio 选项框的背景颜色为红色 (#e43130),并移除默认边框。 + */ + uni-radio .uni-radio-input.uni-radio-input-checked { + border: none !important; + background: #e43130 !important; + } + + /* + * 选中后的 radio 对勾样式 + * 设置选中后的 radio 对勾的样式,包括尺寸、对齐方式、字体大小和颜色。 + * 使用 transform 属性调整对勾的居中位置和缩放比例。 + */ + uni-radio .uni-radio-input.uni-radio-input-checked::before { + border-radius: 50%; + width: 32rpx; + height: 32rpx; + line-height: 32rpx; + text-align: center; + font-size: 20rpx; + color: #fff; + background: #e43130; + border-radius: 50%; + transform: translate(-50%, -50%) scale(1); + -webkit-transform: translate(-50%, -50%) scale(1); + } + +/* + * 底部按钮兼容 iPhone X以上 + * 为特定屏幕尺寸的设备(如 iPhone X 及以上)添加额外的底部内边距,以避免底部按钮被虚拟键盘遮挡。 + */ +@media screen and (width: 375px) and (height: 812px) { .container { padding-bottom: 70px; } } -@media screen and (width: 414px) and (height: 736px){ + +/* + * 底部按钮兼容 iPhone 8 Plus + * 为特定屏幕尺寸的设备(如 iPhone 8 Plus)添加额外的底部内边距,以避免底部按钮被虚拟键盘遮挡。 + */ +@media screen and (width: 414px) and (height: 736px) { .container { padding-bottom: 70px; } diff --git a/front-end/mall4uni/src/main.js b/front-end/mall4uni/src/main.js index ebe9b26..055ca7e 100644 --- a/front-end/mall4uni/src/main.js +++ b/front-end/mall4uni/src/main.js @@ -1,9 +1,18 @@ import { - createSSRApp + createSSRApp // 从 Vue 库中导入 createSSRApp 函数,用于创建一个适用于服务器端渲染 (SSR) 的 Vue 应用实例 } from 'vue' -import App from './App.vue' -export function createApp () { +import App from './App.vue' // 导入应用的根组件 + +/** + * 创建并返回一个 Vue 应用实例 + * + * @returns {Object} - 包含应用实例的对象 + */ +export function createApp() { + // 使用 createSSRApp 函数创建一个新的 Vue 应用实例,并传入根组件 App const app = createSSRApp(App) + + // 返回一个对象,包含创建的应用实例 return { app } diff --git a/front-end/mall4uni/src/manifest.json b/front-end/mall4uni/src/manifest.json index 0d4e2ac..440924b 100644 --- a/front-end/mall4uni/src/manifest.json +++ b/front-end/mall4uni/src/manifest.json @@ -1,99 +1,106 @@ { - "name" : "", - "appid" : "__UNI__2CF44C6", - "description" : "", - "versionName" : "1.0.0", - "versionCode" : "100", - "transformPx" : false, - /* 5+App特有相关 */ - "app-plus" : { - "compatible" : { - "ignoreVersion" : true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持 - }, - "usingComponents" : true, - "nvueStyleCompiler" : "uni-app", - "compilerVersion" : 3, - "splashscreen" : { - "alwaysShowBeforeRender" : true, - "waiting" : true, - "autoclose" : true, - "delay" : 0 - }, - /* 模块配置 */ - "modules" : { - "Camera" : {}, - "LivePusher" : {} - }, - /* 应用发布信息 */ - "distribute" : { - /* android打包配置 */ - "android" : { - "permissions" : [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ], - "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ] - } - } + "name": "", // 应用名称,当前为空 + "appid": "__UNI__2CF44C6", // 应用的唯一标识符(AppID) + "description": "", // 应用描述,当前为空 + "versionName": "1.0.0", // 应用版本名称 + "versionCode": "100", // 应用版本号,用于内部版本控制 + "transformPx": false, // 是否将 px 单位转换为 rpx,false 表示不转换 + + /* 5+App特有相关 */ + "app-plus": { + "compatible": { + "ignoreVersion": true // true 表示忽略版本检查提示框,HBuilderX 1.9.0 及以上版本支持 }, - /* 小程序特有相关 */ - "mp-weixin" : { - "appid" : "wx6fa71e69231a4fa4", - "setting" : { - "urlCheck" : false - }, - "usingComponents" : true, - "permission" : { - "scope.userLocation" : { - "desc" : "你的位置信息将用于地址信息新增、修改以及获取附近门店" - } - }, - "requiredPrivateInfos" : [ "getLocation", "chooseLocation" ] + "usingComponents": true, // 是否启用自定义组件,true 表示启用 + "nvueStyleCompiler": "uni-app", // 指定 nvue 样式编译器,使用 uni-app 编译器 + "compilerVersion": 3, // 编译器版本号 + + "splashscreen": { + "alwaysShowBeforeRender": true, // 启动页是否总是在渲染前显示,true 表示是 + "waiting": true, // 启动页是否显示等待动画,true 表示是 + "autoclose": true, // 启动页是否自动关闭,true 表示是 + "delay": 0 // 启动页延迟关闭的时间(毫秒),0 表示无延迟 }, - "h5" : { - "title" : "", - "domain" : "https://mini-h5.mall4j.com", - "router" : { - "mode" : "history" - }, - "uniStatistics" : { - "enable" : false - }, - "optimization" : { - "treeShaking" : { - "enable" : false - } - }, - "template" : "index.html", - "devServer" : { - "disableHostCheck" : true, - "port" : 80 - }, - "sdkConfigs" : { - "maps" : { - "qqmap" : { - // 用于h5端ip定位 - "key" : "" - } - } - } + + /* 模块配置 */ + "modules": { + "Camera": {}, // 配置 Camera 模块 + "LivePusher": {} // 配置 LivePusher 模块 + }, + + /* 应用发布信息 */ + "distribute": { + /* android打包配置 */ + "android": { + "permissions": [ + "", // 使用相机功能 + "", // 使用自动对焦功能 + "", // 访问网络状态 + "", // 访问 Wi-Fi 状态 + "", // 使用相机权限 + "", // 更改网络状态 + "", // 更改 Wi-Fi 状态 + "", // 使用闪光灯 + "", // 获取账户信息 + "", // 挂载和卸载文件系统 + "", // 读取日志 + "", // 读取电话状态 + "", // 录音权限 + "", // 使用振动 + "", // 保持唤醒锁 + "" // 修改系统设置 + ], + "abiFilters": [ "armeabi-v7a", "arm64-v8a", "x86" ] // 支持的 ABI 架构 + } + } + }, + + /* 小程序特有相关 */ + "mp-weixin": { + "appid": "wx6fa71e69231a4fa4", // 微信小程序的 AppID + "setting": { + "urlCheck": false // 是否开启 URL 安全检查,false 表示不开启 + }, + "usingComponents": true, // 是否启用自定义组件,true 表示启用 + "permission": { + "scope.userLocation": { + "desc": "你的位置信息将用于地址信息新增、修改以及获取附近门店" // 位置权限说明 + } }, - "uniStatistics" : { - "enable" : false + "requiredPrivateInfos": [ "getLocation", "chooseLocation" ] // 必须申请的私有信息权限 + }, + + "h5": { + "title": "", // H5 页面标题,当前为空 + "domain": "https://mini-h5.mall4j.com", // H5 应用的域名 + "router": { + "mode": "history" // 路由模式,使用 history 模式 }, - "vueVersion" : "3" + "uniStatistics": { + "enable": false // 是否启用 Uni-App 统计,false 表示不启用 + }, + "optimization": { + "treeShaking": { + "enable": false // 是否启用 Tree Shaking 优化,false 表示不启用 + } + }, + "template": "index.html", // H5 应用的模板文件 + "devServer": { + "disableHostCheck": true, // 是否禁用主机检查,true 表示禁用 + "port": 80 // 开发服务器端口 + }, + "sdkConfigs": { + "maps": { + "qqmap": { + "key": "" // QQ 地图 API Key,用于 H5 端 IP 定位 + } + } + } + }, + + "uniStatistics": { + "enable": false // 是否启用 Uni-App 统计,false 表示不启用 + }, + + "vueVersion": "3" // 使用的 Vue 版本,当前为 Vue 3 } diff --git a/front-end/mall4uni/src/pages.json b/front-end/mall4uni/src/pages.json index 7a0fa2a..b8c99b9 100644 --- a/front-end/mall4uni/src/pages.json +++ b/front-end/mall4uni/src/pages.json @@ -1,196 +1,200 @@ { "pages": [ { - "path": "pages/index/index", + "path": "pages/index/index", // 首页路径 "style": { - "backgroundTextStyle": "dark", - "navigationBarBackgroundColor": "#fff", - "navigationBarTextStyle": "black", - "enablePullDownRefresh": true, - "navigationBarTitleText": "mall4j" + "backgroundTextStyle": "dark", // 下拉刷新时背景文本颜色,"dark" 表示深色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTextStyle": "black", // 导航栏文字颜色,黑色 + "enablePullDownRefresh": true, // 是否启用下拉刷新功能,true 表示启用 + "navigationBarTitleText": "mall4j" // 导航栏标题文本 } }, { - "path": "pages/user/user", + "path": "pages/user/user", // 个人中心页面路径 "style": { - "navigationBarTitleText": "个人中心" + "navigationBarTitleText": "个人中心" // 导航栏标题文本 } }, { - "path": "pages/basket/basket", + "path": "pages/basket/basket", // 购物车页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "购物车", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "购物车", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/category/category", + "path": "pages/category/category", // 分类商品页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "分类商品", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "分类商品", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/sub-category/sub-category" + "path": "pages/sub-category/sub-category" // 子分类页面路径 }, { - "path": "pages/search-page/search-page", + "path": "pages/search-page/search-page", // 搜索页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "搜索", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "搜索", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/delivery-address/delivery-address", + "path": "pages/delivery-address/delivery-address", // 收货地址页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "收货地址", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "收货地址", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/editAddress/editAddress", + "path": "pages/editAddress/editAddress", // 编辑收货地址页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "编辑收货地址", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "编辑收货地址", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/orderList/orderList", + "path": "pages/orderList/orderList", // 订单列表页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarTitleText": "订单列表", - "navigationBarTextStyle": "black", - "navigationBarBackgroundColor": "#fafafa" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarTitleText": "订单列表", // 导航栏标题文本 + "navigationBarTextStyle": "black", // 导航栏文字颜色,黑色 + "navigationBarBackgroundColor": "#fafafa" // 导航栏背景颜色,浅灰色 } }, { - "path": "pages/order-detail/order-detail", + "path": "pages/order-detail/order-detail", // 订单详情页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "订单详情", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "订单详情", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/submit-order/submit-order", + "path": "pages/submit-order/submit-order", // 提交订单页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "提交订单", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "提交订单", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/express-delivery/express-delivery", + "path": "pages/express-delivery/express-delivery", // 物流查询页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "物流查询", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "物流查询", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/pay-result/pay-result", + "path": "pages/pay-result/pay-result", // 支付结果页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "支付结果", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "支付结果", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/search-prod-show/search-prod-show", + "path": "pages/search-prod-show/search-prod-show", // 搜索结果页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "搜索结果", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 导航栏背景颜色,白色 + "navigationBarTitleText": "搜索结果", // 导航栏标题文本 + "navigationBarTextStyle": "black" // 导航栏文字颜色,黑色 } }, { - "path": "pages/prod/prod", + "path": "pages/prod/prod", // 商品详情页面路径 "style": { - "navigationBarTitleText": "商品详情" + "navigationBarTitleText": "商品详情" // 导航栏标题文本 } }, { - "path": "pages/prod-classify/prod-classify", + "path": "pages/prod-classify/prod-classify", // 商品分类页面路径 "style": { - "onReachBottomDistance": 0 + "onReachBottomDistance": 0 // 触底加载距离,0 表示触底即触发 } }, { - "path": "pages/recent-news/recent-news", + "path": "pages/recent-news/recent-news", // 最新公告页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarTitleText": "最新公告", - "navigationBarTextStyle": "black", - "navigationBarBackgroundColor": "#fafafa" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarTitleText": "最新公告", // 导航栏标题文本 + "navigationBarTextStyle": "black", // 导航栏文字颜色,黑色 + "navigationBarBackgroundColor": "#fafafa" // 导航栏背景颜色,浅灰色 } }, { - "path": "pages/news-detail/news-detail", + "path": "pages/news-detail/news-detail", // 公告详情页面路径 "style": { - "backgroundTextStyle": "light", - "navigationBarTitleText": "最新公告", - "navigationBarTextStyle": "black", - "navigationBarBackgroundColor": "#fafafa" + "backgroundTextStyle": "light", // 下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarTitleText": "最新公告", // 导航栏标题文本 + "navigationBarTextStyle": "black", // 导航栏文字颜色,黑色 + "navigationBarBackgroundColor": "#fafafa" // 导航栏背景颜色,浅灰色 } }, { - "path": "pages/accountLogin/accountLogin" + "path": "pages/accountLogin/accountLogin" // 账号登录页面路径 }, { - "path": "pages/register/register" + "path": "pages/register/register" // 注册页面路径 } ], + "tabBar": { - "selectedColor": "#3a86b9", - "color": "#b8b8b8", + "selectedColor": "#3a86b9", // 选中项的颜色 + "color": "#b8b8b8", // 未选中项的颜色 "list": [ { - "pagePath": "pages/index/index", - "text": "首页", - "iconPath": "/static/images/tabbar/homepage.png", - "selectedIconPath": "/static/images/tabbar/homepage-sel.png" + "pagePath": "pages/index/index", // 首页路径 + "text": "首页", // 标签文本 + "iconPath": "/static/images/tabbar/homepage.png", // 未选中图标路径 + "selectedIconPath": "/static/images/tabbar/homepage-sel.png" // 选中图标路径 }, { - "pagePath": "pages/category/category", - "text": "分类", - "iconPath": "/static/images/tabbar/category.png", - "selectedIconPath": "/static/images/tabbar/category-sel.png" + "pagePath": "pages/category/category", // 分类页面路径 + "text": "分类", // 标签文本 + "iconPath": "/static/images/tabbar/category.png", // 未选中图标路径 + "selectedIconPath": "/static/images/tabbar/category-sel.png" // 选中图标路径 }, { - "pagePath": "pages/basket/basket", - "text": "购物车", - "iconPath": "/static/images/tabbar/basket.png", - "selectedIconPath": "/static/images/tabbar/basket-sel.png" + "pagePath": "pages/basket/basket", // 购物车页面路径 + "text": "购物车", // 标签文本 + "iconPath": "/static/images/tabbar/basket.png", // 未选中图标路径 + "selectedIconPath": "/static/images/tabbar/basket-sel.png" // 选中图标路径 }, { - "pagePath": "pages/user/user", - "text": "我的", - "iconPath": "/static/images/tabbar/user.png", - "selectedIconPath": "/static/images/tabbar/user-sel.png" + "pagePath": "pages/user/user", // 个人中心页面路径 + "text": "我的", // 标签文本 + "iconPath": "/static/images/tabbar/user.png", // 未选中图标路径 + "selectedIconPath": "/static/images/tabbar/user-sel.png" // 选中图标路径 } ] }, - "sitemapLocation": "sitemap.json", + + "sitemapLocation": "sitemap.json", // 站点地图文件位置 + "globalStyle": { - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#fff", - "navigationBarTitleText": "WeChat", - "navigationBarTextStyle": "black" + "backgroundTextStyle": "light", // 全局下拉刷新时背景文本颜色,"light" 表示浅色 + "navigationBarBackgroundColor": "#fff", // 全局导航栏背景颜色,白色 + "navigationBarTitleText": "WeChat", // 全局导航栏标题文本(默认值) + "navigationBarTextStyle": "black" // 全局导航栏文字颜色,黑色 }, - "subPackages": [] + + "subPackages": [] // 子包配置,当前为空 } diff --git a/front-end/mall4uni/src/utils/http.js b/front-end/mall4uni/src/utils/http.js index f4dbb86..719c3ea 100644 --- a/front-end/mall4uni/src/utils/http.js +++ b/front-end/mall4uni/src/utils/http.js @@ -3,102 +3,108 @@ import loginMethods from './login' const http = { + /** + * 发起HTTP请求 + * @param {Object} params - 请求参数对象,包含url、data、method等 + * @returns {Promise} - 返回一个Promise对象,解析或拒绝根据请求结果 + */ request: async function (params) { - // 请求参数处理 + // 处理请求数据类型,确保数组和数字被正确序列化为字符串 if (Object.prototype.toString.call(params.data) === '[object Array]') { params.data = JSON.stringify(params.data) } else if (Object.prototype.toString.call(params.data) === '[object Number]') { params.data = params.data + '' } - // 刷新token + // 如果不是登录请求且应用未完全启动(即未完成首次加载),并且不是刷新token的请求,则尝试刷新token if (!params.login && !getApp()?.globalData.isLanding && !params.isRefreshing) { await loginMethods.refreshToken() } - // 发起请求 + + // 发起请求,并返回Promise对象处理异步操作 return new Promise((resolve, reject) => { uni.request({ dataType: 'json', responseType: params.responseType === undefined ? 'text' : params.responseType, header: { - Authorization: uni.getStorageSync('Token') + Authorization: uni.getStorageSync('Token') // 设置请求头中的Authorization字段 }, - url: (params.domain ? params.domain : import.meta.env.VITE_APP_BASE_API) + params.url, - data: params.data, - method: params.method === undefined ? 'POST' : params.method, + url: (params.domain ? params.domain : import.meta.env.VITE_APP_BASE_API) + params.url, // 拼接完整的请求URL + data: params.data, // 请求体数据 + method: params.method === undefined ? 'POST' : params.method, // 默认请求方法为POST success: (res) => { const responseData = res.data - // 请求小程序码 + // 特殊处理小程序码请求 if (params.responseType === 'arraybuffer' && res.statusCode === 200) { return resolve(responseData) } - // 00000 请求成功 - // A00002 用于直接显示提示系统的成功,内容由输入决定 - if (responseData.code === '00000' || responseData.code === 'A00002') { - resolve(responseData) - } - // A00004 未授权 - if (responseData.code === 'A00004') { - // 重设登录后跳转地址 - loginMethods.setRouteUrlAfterLogin() - uni.removeStorageSync('expiresTimeStamp') - uni.removeStorageSync('loginResult') - uni.removeStorageSync('Token') - if (!params.dontTrunLogin) { - uni.showModal({ - title: '提示', - content: uni.getStorageSync('hadLogin') ? '登录已过期,请重新登陆!' : '请先进行登录!', - cancelText: '取消', - confirmText: '确定', - success: res => { - if (res.confirm) { - uni.navigateTo({ - url: '/pages/accountLogin/accountLogin' - }) - } else { - const router = getCurrentPages() - if (router[0].route === 'pages/basket/basket') { - uni.switchTab({ - url: '/pages/index/index' + // 根据响应码处理不同情况 + switch (responseData.code) { + case '00000': // 请求成功 + case 'A00002': // 系统成功的提示信息 + resolve(responseData) + break; + case 'A00004': // 未授权 + // 重设登录后跳转地址,并清除相关存储 + loginMethods.setRouteUrlAfterLogin() + uni.removeStorageSync('expiresTimeStamp') + uni.removeStorageSync('loginResult') + uni.removeStorageSync('Token') + + // 如果允许转向登录页面,则显示模态框提示用户重新登录 + if (!params.dontTrunLogin) { + uni.showModal({ + title: '提示', + content: uni.getStorageSync('hadLogin') ? '登录已过期,请重新登陆!' : '请先进行登录!', + cancelText: '取消', + confirmText: '确定', + success: res => { + if (res.confirm) { + uni.navigateTo({ + url: '/pages/accountLogin/accountLogin' }) + } else { + const router = getCurrentPages() + if (router[0].route === 'pages/basket/basket') { + uni.switchTab({ + url: '/pages/index/index' + }) + } } } - } - }) - } - resolve(responseData) - } - - // A00005 服务器出了点小差 - if (responseData.code === 'A00005') { - this.onRequestFail(params, responseData) - uni.showToast({ - title: '服务器出了点小差~', - icon: 'none' - }) - } - - // 其他异常码 - // A00001 用于直接显示提示用户的错误,内容由输入内容决定 - // A04001 社交账号未绑定 - // A00012 tempUid错误 - // A00006 验证码错误 - if (responseData.code === 'A04001' || responseData.code === 'A00001' || responseData.code === 'A00012' || responseData.code === 'A00006') { - if (!params.hasCatch) { + }) + } + resolve(responseData) + break; + case 'A00005': // 服务器错误 + this.onRequestFail(params, responseData) uni.showToast({ - title: responseData.msg || responseData.data || 'Error', + title: '服务器出了点小差~', icon: 'none' }) - } - } - - if (responseData.code !== '00000') { - reject(responseData) + break; + case 'A04001': // 社交账号未绑定 + case 'A00001': // 直接显示提示用户的错误 + case 'A00012': // tempUid错误 + case 'A00006': // 验证码错误 + if (!params.hasCatch) { + uni.showToast({ + title: responseData.msg || responseData.data || 'Error', + icon: 'none' + }) + } + reject(responseData) + break; + default: + if (responseData.code !== '00000') { + reject(responseData) + } } }, fail: (err) => { + // 请求失败时显示提示并拒绝Promise uni.showToast({ title: '请求失败' }) @@ -107,56 +113,70 @@ const http = { }) }) }, + + /** + * 获取购物车商品数量,并更新tabBar徽章 + */ getCartCount: () => { if (!uni.getStorageSync('Token')) { - util.removeTabBadge() + util.removeTabBadge() // 如果没有token,移除购物车徽章 return } http.request({ url: '/p/shopCart/prodCount', method: 'GET', - dontTrunLogin: true, + dontTrunLogin: true, // 不需要转向登录 data: {} }) .then(({ data }) => { if (data > 0) { uni.setTabBarBadge({ - index: 2, - text: data + '' + index: 2, // 假设购物车位于第三个tab + text: data + '' // 显示商品数量 }) - getApp().globalData.totalCartCount = data + getApp().globalData.totalCartCount = data // 更新全局购物车数量 } else { uni.removeTabBarBadge({ - index: 2 + index: 2 // 移除购物车徽章 }) getApp().globalData.totalCartCount = 0 } }) }, + + /** + * 请求失败时的日志记录 + * @param {Object} params - 请求参数 + * @param {Object} responseData - 响应数据 + */ onRequestFail: (params, responseData) => { console.error('============== 请求异常 ==============') console.log('接口地址: ', params.url) console.log('异常信息: ', responseData) console.error('============== 请求异常 end ==========') }, + /** - * 登录成功后执行 - * @param {Object} result 登录成功返回的数据 - * @param {Object} fn 登录成功后的回调 + * 登录成功后的处理逻辑 + * @param {Object} result - 登录成功返回的数据 + * @param {Function} fn - 登录成功后的回调函数 */ loginSuccess: (result, fn) => { - // 保存登陆信息 + // 保存登录信息到本地存储 wx.setStorageSync('loginResult', result) - // 保存成功登录标识,token过期判断 + // 保存成功登录标识,用于判断token是否过期 wx.setStorageSync('hadLogin', true) - const expiresTimeStamp = result.expiresIn * 1000 / 2 + new Date().getTime() + const expiresTimeStamp = result.expiresIn * 1000 / 2 + new Date().getTime() // 计算token过期时间 // 缓存token的过期时间 uni.setStorageSync('expiresTimeStamp', expiresTimeStamp) - wx.setStorageSync('Token', result.accessToken) // 把token存入缓存,请求接口数据时要用 + // 将accessToken保存到本地存储,以便后续请求使用 + wx.setStorageSync('Token', result.accessToken) + // 执行登录成功后的回调函数 if (fn) { fn() } } } + export default http diff --git a/front-end/mall4uni/src/utils/login.js b/front-end/mall4uni/src/utils/login.js index 2a5a458..6b27192 100644 --- a/front-end/mall4uni/src/utils/login.js +++ b/front-end/mall4uni/src/utils/login.js @@ -1,37 +1,58 @@ const loginMethods = { /** * 刷新token + * 当用户的Token即将过期时,自动发起请求以获取新的Token。 + * 这个过程会检查当前Token是否有效以及是否正在进行刷新操作,以避免重复请求。 */ refreshToken: () => { + // 从本地存储中获取Token的过期时间戳 const expiresTimeStamp = uni.getStorageSync('expiresTimeStamp') + + // 如果没有有效的Token或过期时间戳,则直接返回,不进行刷新 if (!uni.getStorageSync('Token') || !expiresTimeStamp) return + + // 检查Token是否已经过期 const isExpires = expiresTimeStamp < new Date().getTime() + + // 检查是否已经有刷新Token的操作正在进行 const isRefreshing = uni.getStorageSync('isRefreshingToken') + + // 如果Token未过期或已有刷新操作正在进行,则直接返回 if (!isExpires || isRefreshing) { return } + + // 设置标志位,表示正在刷新Token,防止并发刷新 uni.setStorageSync('isRefreshingToken', true) + + // 发起刷新Token的请求 http.request({ - url: '/token/refresh', - method: 'POST', - login: true, - isRefreshing: true, - dontTrunLogin: true + url: '/token/refresh', // 刷新Token的API接口 + method: 'POST', // 使用POST方法发送请求 + login: true, // 标记这是一个与登录相关的请求 + isRefreshing: true, // 标记这是刷新Token的请求 + dontTrunLogin: true // 即使刷新失败也不跳转到登录页面 }).then(res => { + // 刷新成功后,更新本地存储中的Token过期时间 uni.setStorageSync('isRefreshingToken', false) uni.setStorageSync('expiresTimeStamp', res.data * 1000 / 2 + new Date().getTime()) }).catch(() => { + // 刷新失败后,重置标志位 uni.setStorageSync('isRefreshingToken', false) }) }, /** * 设置登录后的跳转地址 + * 在用户登录之前,记录当前页面的路径,以便在登录成功后能够返回到该页面。 */ setRouteUrlAfterLogin: () => { + // 获取当前所有页面的栈 const pages = getCurrentPages() - // 登录后的回跳地址 + + // 确保当前页面不是登录页面(避免循环跳转) if (pages[pages.length - 1].route.indexOf('user-login') === -1) { + // 记录当前页面的完整路径,用于登录成功后的跳转 uni.setStorageSync('routeUrlAfterLogin', pages[pages.length - 1].$page.fullPath) } } diff --git a/front-end/mall4uni/src/utils/util.js b/front-end/mall4uni/src/utils/util.js index 553e5bb..616160f 100644 --- a/front-end/mall4uni/src/utils/util.js +++ b/front-end/mall4uni/src/utils/util.js @@ -1,34 +1,71 @@ const util = { + /** + * 格式化日期时间 + * 将传入的Date对象格式化为"YYYY/MM/DD HH:MM:SS"的字符串形式。 + * @param {Date} date - 要格式化的日期对象 + * @returns {String} - 格式化后的日期时间字符串 + */ 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() + const year = date.getFullYear() // 获取年份 + const month = date.getMonth() + 1 // 获取月份(注意:getMonth()返回的是0-11,所以需要加1) + const day = date.getDate() // 获取日期 + const hour = date.getHours() // 获取小时 + const minute = date.getMinutes() // 获取分钟 + const second = date.getSeconds() // 获取秒 + + // 使用formatNumber方法确保所有时间部分都是两位数,并用'/'连接日期部分,':'连接时间部分 return [year, month, day].map(util.formatNumber).join('/') + ' ' + [hour, minute, second].map(util.formatNumber).join(':') }, + /** + * 格式化数字 + * 确保传入的数字是两位数,如果不是,则在前面补零。 + * @param {Number|String} n - 需要格式化的数字 + * @returns {String} - 格式化后的两位数字符串 + */ formatNumber: n => { - n = n.toString() - return n[1] ? n : '0' + n + n = n.toString() // 将数字转换为字符串 + return n[1] ? n : '0' + n // 如果长度大于1则直接返回,否则在前面补零 }, + /** + * 格式化HTML内容 + * 对传入的HTML字符串进行样式调整,以适应移动端显示,特别是处理图片、表格等内容的宽度和布局。 + * @param {String} content - 需要格式化的HTML字符串 + * @returns {String} - 格式化后的HTML字符串 + */ formatHtml: content => { if (!content) { - return + return // 如果没有内容,直接返回 } + + // 替换

标签,设置最大宽度、单词换行等样式 content = content.replace(/

标签,设置最大宽度、高度自适应、边距等样式 content = content.replace(/标签中的样式,确保内部样式不会覆盖外部样式 content = content.replace(/style="/gi, 'style="max-width:100% !important;table-layout:fixed;word-wrap:break-word;word-break:break-word;') + + // 替换标签,设置表格布局和单词换行等样式 content = content.replace(/
标签,设置单元格间距、填充、边框等样式 content = content.replace(/
') - return content - }, + return content // 返回格式化后的HTML字符串 + } +} + +export default util /** * 移除购物车Tabbar的数字 */