Browse Source

上传

master
前端-胡立永 1 month ago
parent
commit
2642c8b136
35 changed files with 1407 additions and 433 deletions
  1. +417
    -13
      README.md
  2. +14
    -10
      api/api.js
  3. +19
    -77
      api/http.js
  4. +215
    -0
      api/model/index.js
  5. +115
    -0
      api/model/info.js
  6. +6
    -10
      api/model/login.js
  7. +20
    -0
      api/model/vip.js
  8. +1
    -1
      components/base/navbar.vue
  9. +81
    -76
      components/base/tabbar.vue
  10. +7
    -7
      config.js
  11. BIN
      doc/address.png
  12. BIN
      doc/c.png
  13. BIN
      doc/cart.png
  14. BIN
      doc/category.png
  15. BIN
      doc/center.png
  16. BIN
      doc/editAddress.png
  17. BIN
      doc/home-s.png
  18. BIN
      doc/home.png
  19. BIN
      doc/order.png
  20. BIN
      doc/productDetail.png
  21. BIN
      doc/productUnit.png
  22. BIN
      doc/purse.png
  23. +7
    -3
      mixins/configList.js
  24. +30
    -22
      mixins/list.js
  25. +70
    -0
      mixins/order.js
  26. +1
    -0
      pages/index/cart.vue
  27. +221
    -54
      pages_order/auth/loginAndRegisterAndForgetPassword.vue
  28. +9
    -7
      pages_order/auth/wxLogin.vue
  29. +0
    -93
      pages_order/components/commodity/commoditySelect.vue
  30. +0
    -3
      pages_order/order/refundsOrExchange.vue
  31. +53
    -0
      utils/authorize.js
  32. +30
    -0
      utils/index.js
  33. +1
    -10
      utils/oss-upload/oss/index.js
  34. +20
    -12
      utils/pay.js
  35. +70
    -35
      utils/utils.js

+ 417
- 13
README.md View File

@ -1,13 +1,417 @@
#酒店桌布小程序
![](./doc/home.png)
![](./doc/home-s.png)
![](./doc/cart.png)
![](./doc/order.png)
![](./doc/purse.png)
![](./doc/center.png)
![](./doc/address.png)
![](./doc/editAddress.png)
![](./doc/category.png)
![](./doc/productDetail.png)
![](./doc/productUnit.png)
# 商城项目文档
## 项目概述
本项目是一个基于uni-app开发的商城小程序,采用Vue框架开发,集成了完整的商城功能模块。
## 目录结构
```
├── api # API接口目录
│ ├── api.js # API统一出口
│ ├── http.js # HTTP请求封装
│ └── model # 业务模块API
├── components # 公共组件
├── mixins # 混入文件
├── pages # 页面文件
├── static # 静态资源
├── store # Vuex状态管理
├── utils # 工具函数
└── uni_modules # uni-app插件模块
```
## 分包结构说明
### pages_order分包
分包是小程序优化加载性能的重要手段,pages_order作为独立分包,包含以下模块:
```
├── auth # 认证相关页面
│ ├── loginAndRegisterAndForgetPassword.vue # 登录注册
│ ├── wxLogin.vue # 微信登录
│ └── wxUserInfo.vue # 微信用户信息
├── components # 分包内公共组件
│ ├── address/ # 地址选择组件
│ ├── areaSelector/ # 区域选择器
│ └── product/ # 商品相关组件
├── home # 首页相关
│ ├── addEnterprise.vue # 添加企业
│ ├── contact.vue # 联系我们
│ ├── introduce.vue # 介绍页面
│ ├── journalism.vue # 新闻资讯
│ └── notice.vue # 公告
├── mine # 我的模块
│ ├── address.vue # 收货地址
│ ├── balance.vue # 余额
│ ├── commission.vue # 佣金
│ ├── coupon.vue # 优惠券
│ ├── memberCenter.vue # 会员中心
│ └── more... # 更多功能页面
├── order # 订单模块
│ ├── createOrder.vue # 创建订单
│ ├── orderDetail.vue # 订单详情
│ └── giftList.vue # 礼品列表
├── product # 商品模块
│ └── productDetail.vue # 商品详情
└── static # 分包静态资源
├── address/ # 地址相关图片
├── auth/ # 认证相关图片
├── coupon/ # 优惠券图片
└── more... # 其他静态资源
```
**分包特点:**
- 静态资源就近原则:分包相关的图片等静态资源存放在分包目录下,避免主包体积过大
- 模块化组织:按功能模块划分目录,便于维护和管理
- 组件复用:分包内的通用组件集中管理,提高代码复用性
## 配置文件说明
### config.js
项目核心配置文件,包含以下配置:
**1. 环境配置**
```javascript
// 当前环境
const type = 'prod'
// 环境配置
const config = {
dev: {
baseUrl: 'http://h5.xzaiyp.top/jewelry-admin',
},
prod: {
baseUrl: 'https://jewelry-admin.hhlm1688.com/jewelry-admin',
}
}
```
**2. 默认配置**
```javascript
const defaultConfig = {
// 腾讯地图Key
mapKey: 'XMBBZ-BCPCV-SXPPQ-5Y7MY-PHZXK-YFFVU',
// 阿里云OSS配置
aliOss: {
url: 'https://image.hhlm1688.com/',
config: {
region: 'oss-cn-guangzhou',
accessKeyId: '***',
accessKeySecret: '***',
bucket: 'hanhaiimage',
endpoint: 'oss-cn-shenzhen.aliyuncs.com',
}
}
}
```
**3. UI框架配置**
```javascript
uni.$uv.setConfig({
config: {
unit: 'rpx' // 设置默认单位
},
})
// UI文档地址 https://www.uvui.cn/
```
## 核心模块详解
### 1. Mixins 混入
#### 1.1 list.js - 列表数据加载混入
提供列表数据的加载、分页、下拉刷新、上拉加载更多等功能。
**主要功能:**
- 统一的分页参数处理
- 下拉刷新和上拉加载更多
- 数据加载状态管理
**使用示例:**
```javascript
// 在页面中使用list混入
import listMixin from '@/mixins/list.js'
export default {
mixins: [listMixin],
data() {
return {
// 指定API接口
mixinsListApi: 'productList'
}
}
}
```
#### 1.2 configList.js - 全局配置混入
已全局引入的配置管理混入,无需手动引入即可使用。
**主要功能:**
- 统一的分享配置
- 全局配置管理
- 用户信息关联
**配置参数:**
```javascript
// 分享配置示例
this.Gshare.title = '分享标题'
this.Gshare.path = '分享路径'
```
### 2. API 模块
#### 2.1 http.js - 请求封装
统一的HTTP请求处理,包含:
- 请求拦截器
- 响应拦截器
- 统一的错误处理
- Token管理
#### 2.2 api.js - 接口管理
统一管理API接口,支持模块化组织。API模块采用分层结构,便于维护和扩展。
**目录结构:**
```
api/
├── api.js # API统一出口
├── http.js # HTTP请求封装
└── model/ # 业务模块API
├── product.js # 商品相关接口
├── order.js # 订单相关接口
└── user.js # 用户相关接口
```
**接口定义示例:**
```javascript
// api/model/product.js
export default {
// GET请求示例
list: {
url: '/api/product/list',
method: 'GET',
loading: true // 显示加载提示
},
// POST请求示例
create: {
url: '/api/product/create',
method: 'POST',
loading: true // 显示加载提示
auth : true,//效验登录
debounce : 1000,//接口防抖,1s
limit : 500,//接口限流,0.5s
},
}
```
**调用接口示例:**
```javascript
// 第一种写法:callback方式处理响应
this.$api('product.list', {
pageNo: 1,
pageSize: 10,
categoryId: '123'
}, res => {
// 处理列表数据
})
// 第二种写法:Promise方式处理响应
this.$api('product.create', {
name: '商品名称',
price: 99.99,
description: '商品描述'
}).then(res => {
if (res.code === 200) {
// 创建成功
uni.showToast({ title: '创建成功' })
}
})
```
### 3. 公共代码
#### 3.1 工具函数 (utils)
- authorize.js: 授权处理
- pay.js: 微信网页支付相关
- utils.js: 通用工具函数
- timeUtils.js: 时间处理
- position.js: 定位与位置计算
- oss-upload: 阿里云OSS上传模块
**使用示例:**
```javascript
// 授权处理
async preservationImg(img) {
await this.$authorize('scope.writePhotosAlbum')
//在执行$authorize之后,await下面的代码都是确保授权完成的情况下执行
},
// 时间格式化
const formattedTime = this.$timeUtils.formatTime(new Date())
// 项目中在Vue集成了dayjs >>,可以直接使用
// 在utils/index中Vue.prototype.$dayjs
this.$dayjs()
// 微信网页支付调用
import { wxPay } from '@/utils/pay'
wxPay(orderData)
```
#### 3.2 公共组件
- navbar.vue: 自定义导航栏
- tabbar.vue: 底部导航栏
- productItem.vue: 商品列表项
**使用示例:**
```html
<template>
<view>
<navbar title="商品列表" />
<product-item
v-for="item in list"
:key="item.id"
:product="item"
/>
</view>
</template>
```
#### 3.3 OSS上传模块
**配置说明:**
项目使用阿里云OSS进行文件存储,相关配置位于config.js中:
**使用示例:**
1. 单文件上传
```javascript
export default {
methods: {
onUpload(file) {
this.$Oss.ossUpload(file.path).then(url => {
this.filePath = url
})
}
}
}
```
2. 在uv-upload组件中使用
```html
<template>
<uv-upload
:fileList="fileList"
@afterRead="afterRead"
@delete="deleteImage"
name="1"
multiple
:maxCount="maxCount"
></uv-upload>
</template>
<script>
export default {
data() {
return {
fileList: [],
maxCount: 9
}
},
methods: {
// 新增图片
afterRead(e) {
e.file.forEach(file => {
this.$Oss.ossUpload(file.url).then(url => {
this.fileList.push({
url
})
})
})
},
// 删除图片
deleteImage(e) {
this.fileList.splice(e.index, 1)
},
}
}
</script>
```
**注意事项:**
1. 上传前请确保OSS配置正确
2. 建议对上传文件大小进行限制
3. 支持的文件类型:图片、视频、文档等
4. 上传失败时会抛出异常,请做好错误处理
## 最佳实践
### 1. 列表页面开发
```javascript
// pages/product/list.vue
import listMixin from '@/mixins/list.js'
export default {
mixins: [listMixin],
data() {
return {
mixinsListApi: 'productList',
}
},
methods: {
// 分类切换
onCategoryChange(categoryId) {
this.queryParams.categoryId = categoryId
this.getData()
}
}
}
```
### 2. 详情页面开发
```javascript
// pages/product/detail.vue
import configMixin from '@/mixins/configList.js'
export default {
mixins: [configMixin],
data() {
return {
productId: '',
detail: {}
}
},
onLoad(options) {
this.productId = options.id
this.getDetail()
},
methods: {
getDetail() {
this.$api('productDetail', {
id: this.productId
}, res => {
this.detail = res.result
// 设置分享信息
this.Gshare.title = this.detail.name
this.Gshare.path = `/pages/product/detail?id=${this.productId}`
})
}
}
}
```
## 注意事项
1. 使用mixins时注意命名冲突
2. API调用建议统一使用this.$api方式
3. 页面开发建议继承相应的混入来复用通用功能
## 常见问题
1. 列表加载失败
- 检查mixinsListApi是否正确配置
- 确认网络请求是否正常
- 查看请求参数格式是否正确

+ 14
- 10
api/api.js View File

@ -5,7 +5,7 @@ import utils from '../utils/utils.js'
let limit = {}
let debounce = {}
const models = []
const models = ['login', 'index', 'vip', 'info']
const config = {
// 示例
@ -14,7 +14,7 @@ const config = {
// limit : 1000
// },
getConfig : {url : '/api/getConfig', method : 'GET', limit : 500},
getConfig : {url : '/config_common/getConfig', method : 'GET', limit : 500},
}
@ -22,8 +22,8 @@ export function api(key, data, callback, loadingTitle) {
let req = config[key]
if (!req) {
console.error('无效key--------' + key);
return
console.error('无效key' + key);
return Promise.reject()
}
if (typeof callback == 'string') {
@ -40,7 +40,7 @@ export function api(key, data, callback, loadingTitle) {
let storageKey = req.url
let storage = limit[storageKey]
if (storage && new Date().getTime() - storage < req.limit) {
return
return Promise.reject()
}
limit[storageKey] = new Date().getTime()
}
@ -49,8 +49,8 @@ export function api(key, data, callback, loadingTitle) {
if (req.auth) {
if (!uni.getStorageSync('token')) {
utils.toLogin()
console.error('需要登录')
return
console.error('需要登录', req.url)
return Promise.reject()
}
}
@ -74,19 +74,22 @@ export function api(key, data, callback, loadingTitle) {
loadingTitle || req.showLoading, loadingTitle || req.loadingTitle)
}, req.debounce)
return
return Promise.reject()
}
http.http(req.url, data, callback, req.method,
return http.http(req.url, data, callback, req.method,
loadingTitle || req.showLoading, loadingTitle || req.loadingTitle)
}
function addApiModel(model, key){
for(let k in model){
if(config[`${k}`]){
console.error(`重名api------model=${key},key=${k}`);
uni.showModal({
title: `重名api`,
content: `model=${key},key=${k}`
})
continue
}
config[`${k}`] = model[k]
@ -98,4 +101,5 @@ models.forEach(key => {
addApiModel(require(`./model/${key}.js`).default, key)
})
export default api

+ 19
- 77
api/http.js View File

@ -1,7 +1,7 @@
import Vue from 'vue'
import utils from '../utils/utils.js'
import store from '../store/store.js'
function http(uri, data, callback, method = 'GET', showLoading, title) {
@ -11,16 +11,23 @@ function http(uri, data, callback, method = 'GET', showLoading, title) {
});
}
let reject, resolve;
let promise = new Promise((res, rej) => {
reject = rej
resolve = res
})
uni.request({
url: Vue.prototype.$config.baseUrl + uri,
data: enhanceData(data),
data,
method: method,
header: {
'X-Access-Token': uni.getStorageSync('token'),
'Content-Type' : method == 'POST' ? 'application/x-www-form-urlencoded' : 'application/json'
'Content-Type' : 'application/x-www-form-urlencoded'
},
success: (res) => {
// console.log(res,'res')
if(showLoading){
uni.hideLoading();
}
@ -28,12 +35,13 @@ function http(uri, data, callback, method = 'GET', showLoading, title) {
if(res.statusCode == 401 ||
res.data.message == '操作失败,token非法无效!' ||
res.data.message == '操作失败,用户不存在!'){
uni.removeStorageSync('token')
store.commit('logout')
console.error('登录过期');
utils.toLogin()
}
if(res.statusCode == 200 && res.data.code != 200){
if(res.statusCode == 200 && res.data.code != 200
&& res.data.code != 902){
uni.showToast({
mask: true,
duration: 1000,
@ -42,10 +50,12 @@ function http(uri, data, callback, method = 'GET', showLoading, title) {
});
}
callback(res.data)
callback && callback(res.data)
resolve(res.data)
},
fail: () => {
reject('api fail')
uni.showLoading({})
setTimeout(()=>{
uni.hideLoading()
@ -57,79 +67,11 @@ function http(uri, data, callback, method = 'GET', showLoading, title) {
}
}
});
return promise
}
function deleted(uri, data, callback) {
http(uri, data, callback, 'DELETE')
}
function post(uri, data, callback) {
http(uri, data, callback, 'POST')
}
function get(uri, data, callback) {
http(uri, data, callback, 'GET')
}
function enhanceData(data) {
const userid = uni.getStorageSync("userid")
if (!data) {
data = {}
}
if (userid) {
data.userid = userid
}
return data
}
function sync(method, uri, data) {
return new Promise((resolve, reject) => {
uni.request({
url: uri,
data: data,
method: method,
header: {
'auth': '1AS9F1HPC4FBC9EN00J7KX2L5RJ99XHZ'
},
success: (res) => {
resolve(res.data)
},
fail: (err) => {
reject(err);
}
})
})
}
let cache = null
function async (method, uri, data) {
const promise = sync(method, uri, data).then(res => {
cache = res
}).catch(err => {
})
}
function syncHttp(uri, data, method = 'GET') {
async (method, uri, data)
}
export default {
http: http,
delete: deleted,
post: post,
get: get,
syncHttp: syncHttp
}

+ 215
- 0
api/model/index.js View File

@ -0,0 +1,215 @@
// 首页相关接口
const api = {
// 获取首页轮播图
getRiceBanner: {
url: '/index_common/getRiceBanner',
method: 'GET',
},
// 获取首页常规产品【废弃】
// getRiceCommonProductList: {
// url: '/index_common/getRiceCommonProductList',
// method: 'GET',
// },
// 获取首页跳转图标
getRiceIconList: {
url: '/index_common/getRiceIconList',
method: 'GET',
},
// 获取首页新闻详情
getRiceNewsDetail: {
url: '/index_common/getCommonNewsDetail',
method: 'GET',
},
// 获取首页新闻列表
getRiceNewsList: {
url: '/index_common/getRiceNewsList',
method: 'GET',
},
// 获取首页公告列表
getRiceNoticeList: {
url: '/index_common/getRiceNoticeList',
method: 'GET',
},
// 获取首页商品详情
getRiceProductDetail: {
url: '/index_common/getRiceProductDetail',
method: 'GET',
},
// 获取首页体验产品
getRiceProductList: {
url: '/index_common/getRiceProductList',
method: 'GET',
},
// 查询分类接口
getCategoryList: {
url: '/index_common/getCategoryList',
method: 'GET',
},
// 新查询分类以及商品数据接口
getCategoryPidList: {
url: '/index_common/getCategoryPidList',
method: 'GET',
debounce : 250,
},
// 查询一级分类接口
getPidList: {
url: '/index_common/getCategoryPidList',
method: 'GET',
},
// 获取分类分页商品列表接口
getClassShopPageList: {
url: '/index_common/getClassShopPageList',
method: 'GET',
},
// 加入购物车
addCart: {
url: '/index_common/addCart',
method: 'GET',
auth: true,
showLoading: true,
limit : 500,
},
// 删除购物车信息
deleteCart: {
url: '/index_common/deleteCart',
method: 'DELETE',
auth: true,
showLoading: true,
},
// 修改购物车信息数量
updateCartNum: {
url: '/index_common/updateCartNum',
method: 'POST',
auth: true,
debounce: 300,
},
// 创建订单
createOrder: {
url: '/index_common/createOrder',
method: 'GET',
auth: true,
limit: 1000,
showLoading: true,
},
// 创建订单-再次支付
createOrderTwo: {
url: '/index_common/createOrderTwo',
method: 'GET',
auth: true,
limit: 1000,
showLoading: true,
},
// 多商品创建订单
createSumOrder: {
url: '/index_common/createSumOrder',
method: 'POST',
auth: true,
limit: 1000,
showLoading: true,
},
// 多商品订单再次支付
createSumOrderAgain: {
url: '/index_common/createSumOrderAgain',
method: 'POST',
auth: true,
limit: 1000,
showLoading: true,
},
// 确认收货
confirmOrder: {
url: '/index_common/confirmOrder',
method: 'GET',
auth: true,
limit: 1000,
showLoading: true,
},
// 取消订单
cancelOrder: {
url: '/index_common/cancelOrder',
method: 'GET',
auth: true,
limit: 1000,
showLoading: true,
},
// 获取首页广告列表
getRiceProductList: {
url: '/index_common/getRiceAdList',
method: 'GET',
},
// 获取首页广告列表
getRiceAdDetail: {
url: '/index_common/getRiceAdDetail',
method: 'GET',
},
//获取优惠券信息
getRiceCouponList: {
url: '/info_common/getRiceCouponList',
method: 'GET',
},
//增加或者修改合伙人申请信息
addOrUpdateCommonUser: {
url: '/index_common/addOrUpdateCommonUser',
method: 'POST',
},
//根据用户查询渠合伙人申请信息表单
getCommonUser: {
url: '/index_common/getCommonUser',
method: 'GET'
},
//提交反馈信息
addFeedback: {
url: '/info_common/addFeedback',
method: 'POST'
},
// 获取我的直接推荐间接推荐用户列表带分页
getHanHaiMemberUser: {
url: '/info_common/getHanHaiMemberUser',
method: 'GET'
},
// 获取祝福背景图
getRiceBlessing: {
url: '/index_common/getRiceBlessing',
method: 'GET'
},
// 随机获取祝福语
getRiceBlessingWords: {
url: '/index_common/getRiceBlessingWords',
method: 'GET'
},
// 根据订单标识修改订单祝福语背景
updateOrderBlessing: {
url: '/index_common/updateOrderBlessing',
method: 'POST',
auth : true,
limit : 1000,
},
// 1.收礼流程 =》点击收礼
getGiveShop: {
url: '/index_common/getGiveShop',
method: 'GET',
auth : true,
limit : 1000,
},
// 2.点击抽奖 =》抽奖
getGiveShopLottery: {
url: '/index_common/getGiveShopLottery',
method: 'GET',
auth : true,
limit : 1000,
},
// 获取我的礼品订单
getMyGiftOrder: {
url: '/index_common/getMyGiftOrder',
method: 'GET',
auth : true,
},
// 获取我的礼品订单详情
getMyGiftOrderDetail: {
url: '/index_common/getMyGiftOrderDetail',
method: 'GET',
auth : true,
},
}
export default api

+ 115
- 0
api/model/info.js View File

@ -0,0 +1,115 @@
// 个人相关接口
const api = {
// 充值
recharge: {
url: '/info_common/withdraw',
method: 'GET',
auth: true,
limit: 1000,
showLoading: true,
},
// 提现
withdraw: {
url: '/info_common/withdraw',
method: 'GET',
auth: true,
limit: 1000,
showLoading: true,
},
// 获取地址列表带分页
getAddressPageList: {
url: '/info_common/getAddressPageList',
method: 'GET',
auth: true,
},
// 增加或修改地址信息
addOrUpdateAddress: {
url: '/info_common/addOrUpdateAddress',
method: 'POST',
limit: 500,
auth: true,
showLoading: true,
},
// 删除地址
deleteAddress: {
url: '/info_common/deleteAddress',
method: 'GET',
limit: 500,
auth: true,
showLoading: true,
},
// 修改默认地址
updateDefaultAddress: {
url: '/info_common/updateDefaultAddress',
method: 'GET',
auth: true,
limit: 1000,
},
// 获取粉丝列表带分页
getFansPageList: {
url: '/info_common/getFansPageList',
method: 'GET',
auth: true,
},
// 获取相关介绍
getInfoIntroduce: {
url: '/info_common/getInfoIntroduce',
method: 'GET',
auth: true,
},
// 获取个人邀请码
getInviteCode: {
url: '/info_common/getInviteCode',
method: 'GET',
auth: true,
},
// 获取订单列表带分页
getOrderPageList: {
url: '/info_common/getOrderPageList',
method: 'GET',
auth: true,
},
// 获取订单详情
getOrderDetail: {
url: '/info_common/getOrderDetail',
method: 'GET',
auth: true,
},
// 获取流水记录带分页
getWaterPageList: {
url: '/info_common/getWaterPageList',
method: 'GET',
auth: true,
},
// 获取相关介绍
getInfoIntroduce: {
url: '/info_common/getInfoIntroduce',
method: 'GET',
},
// 获取相关介绍详情
getInfoIntroduceDetail: {
url: '/info_common/getRiceNewsDetail',
method: 'GET',
},
// 查询个人信息相关
getRiceInfo: {
url: '/info_common/getRiceInfo',
method: 'GET',
limit: 500,
},
// 获取购物车信息列表带分页
getCartPageList: {
url: '/info_common/getCartPageList',
method: 'GET',
},
// 领取新人优惠券
getRiceCoupon: {
url: '/info_common/getRiceCoupon',
method: 'GET',
limit: 500,
auth: true,
},
}
export default api

+ 6
- 10
api/model/login.js View File

@ -10,6 +10,12 @@ const api = {
limit : 500,
showLoading : true,
},
// 获取绑定手机号码
bindPhone: {
url: '/login_common/bindPhone',
method: 'GET',
auth: true,
},
// 修改个人信息接口
updateInfo: {
url: '/info_common/updateInfo',
@ -24,16 +30,6 @@ const api = {
method: 'GET',
auth: true,
},
//隐私政策
getPrivacyPolicy: {
url: '/login/getPrivacyPolicy',
method: 'GET',
},
//用户协议
getUserAgreement: {
url: '/login/getUserAgreement',
method: 'GET',
},
}
export default api

+ 20
- 0
api/model/vip.js View File

@ -0,0 +1,20 @@
// vip相关接口
const api = {
// 获取会员权益列表
getRiceVipList: {
url: '/index_common/getVipInfoList',
method: 'GET',
},
// 申请成为会员
applyRiceVip: {
url: '/rice_vip/applyRiceVip',
method: 'POST',
limit : 500,
auth : true,
showLoading : true,
},
}
export default api

+ 1
- 1
components/base/navbar.vue View File

@ -116,7 +116,7 @@
justify-content: center;
font-size: 32rpx;
align-items: center;
z-index: 99999;
z-index: 999;
.left{
position: absolute;
left: 40rpx;


+ 81
- 76
components/base/tabbar.vue View File

@ -1,19 +1,14 @@
<template>
<view class="">
<view class="tabbar-box"></view>
<view class="tabbar-box">
<view class="tabbar">
<view
:class="{item : true, active : select == index}"
v-for="(item, index) in list"
:key="index"
v-if="!item.isNotShop || !userShop"
@click="toPath(item, index)">
<view class="icon">
<image :src="select == index ?
<view :class="{ 'tabbar-active' : select == item.key}" v-for="(item, index) in list" :key="index"
v-if="!item.isNotShop || !userShop" @click="toPath(item, index)" class="tabbar-item">
<view class="tabbar-icon">
<image :src="select == item.key ?
item.selectedIconPath :
item.iconPath" class="icon-image" mode=""></image>
item.iconPath" class="tabbar-icon-image" mode="aspectFill"></image>
</view>
<view class="title">
<view class="tabbar-title">
{{ item.title }}
</view>
</view>
@ -22,54 +17,58 @@
</template>
<script>
import { mapGetters } from 'vuex'
import {
mapGetters
} from 'vuex'
export default {
name:"tabbar",
props : ['select'],
computed : {
name: "tabbar",
props: ['select'],
computed: {
...mapGetters(['userShop']),
},
data() {
return {
list : [
{
"selectedIconPath": "/static/image/tabbar/home-a.png",
list: [{
"selectedIconPath": "/static/image/tabbar/home-active.png",
"iconPath": "/static/image/tabbar/home.png",
"pagePath": "/pages/index/index",
"title": "首页"
"title": "首页",
key: 'home',
},
{
"selectedIconPath": "/static/image/tabbar/category-a.png",
"iconPath": "/static/image/tabbar/category.png",
"selectedIconPath": "/static/image/tabbar/product-list-active.png",
"iconPath": "/static/image/tabbar/product-list.png",
"pagePath": "/pages/index/category",
"title": "分类",
isNotShop : true,
"title": "商品列表",
key: 'category',
},
{
"selectedIconPath": "/static/image/tabbar/order-a.png",
"selectedIconPath": "/static/image/tabbar/order-active.png",
"iconPath": "/static/image/tabbar/order.png",
"pagePath": "/pages/index/order",
"title": "订单中心"
"title": "订单",
key: 'order',
},
{
"selectedIconPath": "/static/image/tabbar/cart-a.png",
"selectedIconPath": "/static/image/tabbar/cart-active.png",
"iconPath": "/static/image/tabbar/cart.png",
"pagePath": "/pages/index/cart",
"title": "购物车",
isNotShop : true,
key: 'cart',
},
{
"selectedIconPath": "/static/image/tabbar/center-a.png",
"iconPath": "/static/image/tabbar/center.png",
"selectedIconPath": "/static/image/tabbar/user-center-active.png",
"iconPath": "/static/image/tabbar/user-center.png",
"pagePath": "/pages/index/center",
"title": "个人中心"
"title": "我的",
key: 'center',
}
]
};
},
methods : {
toPath(item, index){
if(index == this.select){
methods: {
toPath(item, index) {
if (item.key == this.select) {
return
}
uni.reLaunch({
@ -81,49 +80,55 @@
</script>
<style scoped lang="scss">
.tabbar-box{
height: 120rpx;
padding-bottom: env(safe-area-inset-bottom);
}
.tabbar{
position: fixed;
width: 750rpx;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
height: 120rpx;
padding-bottom: env(safe-area-inset-bottom);
z-index: 999999;
bottom: 0;
left: 0;
color: #BCBCBC;
.item{
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.icon{
width: 54rpx;
height: 54rpx;
.icon-image{
width: 54rpx;
height: 54rpx;
.tabbar-box {
height: 120rpx;
padding-bottom: env(safe-area-inset-bottom);
.tabbar {
position: fixed;
width: 750rpx;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
height: 120rpx;
padding-bottom: env(safe-area-inset-bottom);
z-index: 999999;
bottom: 0;
left: 0;
color: #BCBCBC;
.tabbar-item {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.tabbar-icon {
width: 54rpx;
height: 54rpx;
.tabbar-icon-image {
width: 54rpx;
height: 54rpx;
}
}
.tabbar-title {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
font-size: 23rpx;
line-height: 35rpx;
}
}
.tabbar-active {
color: $uni-color !important;
}
}
.title{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
font-size: 23rpx;
line-height: 35rpx;
}
}
}
.active{
color: $uni-color !important;
}
</style>

+ 7
- 7
config.js View File

@ -24,18 +24,18 @@ const config = {
// 默认配置
const defaultConfig = {
mapKey : 'XMBBZ-BCPCV-SXPPQ-5Y7MY-PHZXK-YFFVU',
aliOss : {
url : 'https://tennis-oss.xzaiyp.top/',
config : {
aliOss: {
url: 'https://image.hhlm1688.com/',
config: {
//桶的地址
region: 'oss-cn-guangzhou',
//id
accessKeyId:'LTAI5tNycA46YTwm383dRvMV',
accessKeyId: 'LTAI5tQSs47izVy8DLVdwUU9',
//密钥
accessKeySecret:'tAdbYQCmdur6jbZ8hjvgB7T1Z52mIG',
accessKeySecret: 'qHI7C3PaXYZySr84HTToviC71AYlFq',
//桶的名字
bucket: 'zhuoqiu-image',
endpoint:'oss-cn-guangzhou.aliyuncs.com',
bucket: 'hanhaiimage',
endpoint: 'oss-cn-shenzhen.aliyuncs.com',
}
},
}


BIN
doc/address.png View File

Before After
Width: 597  |  Height: 1255  |  Size: 149 KiB

BIN
doc/c.png View File

Before After
Width: 586  |  Height: 1275  |  Size: 120 KiB

BIN
doc/cart.png View File

Before After
Width: 604  |  Height: 1279  |  Size: 137 KiB

BIN
doc/category.png View File

Before After
Width: 606  |  Height: 1263  |  Size: 136 KiB

BIN
doc/center.png View File

Before After
Width: 580  |  Height: 1266  |  Size: 140 KiB

BIN
doc/editAddress.png View File

Before After
Width: 601  |  Height: 1276  |  Size: 157 KiB

BIN
doc/home-s.png View File

Before After
Width: 595  |  Height: 1270  |  Size: 176 KiB

BIN
doc/home.png View File

Before After
Width: 586  |  Height: 1276  |  Size: 271 KiB

BIN
doc/order.png View File

Before After
Width: 588  |  Height: 1270  |  Size: 107 KiB

BIN
doc/productDetail.png View File

Before After
Width: 604  |  Height: 1264  |  Size: 177 KiB

BIN
doc/productUnit.png View File

Before After
Width: 619  |  Height: 1254  |  Size: 161 KiB

BIN
doc/purse.png View File

Before After
Width: 615  |  Height: 1267  |  Size: 138 KiB

+ 7
- 3
mixins/configList.js View File

@ -13,17 +13,21 @@ export default {
}
},
computed: {
...mapState(['configList', 'userInfo']),
...mapState(['configList', 'userInfo', 'riceInfo']),
},
// 定义全局分享
// 1.发送给朋友
onShareAppMessage(res) {
let o = {
...this.Gshare,
title : this.configList.logo_name,
...this.Gshare,
}
if(this.userInfo.id){
o.path = this.Gshare.path + '?shareId=' + this.userInfo.id
if(this.Gshare.path.includes('?')){
o.path += '&shareId=' + this.userInfo.id
}else{
o.path += '?shareId=' + this.userInfo.id
}
}
return o
},


+ 30
- 22
mixins/list.js View File

@ -1,22 +1,21 @@
/**
* 处理查询参数
* @param {Object} self - 组件实例
* @param {Object} queryParams - 额外的查询参数
* @returns {Object} 合并后的查询参数
*/
function query(self, queryParams){
// return (self.beforeGetData && self.beforeGetData()) ||
// queryParams || self.queryParams
// 深度合并对象
return self.$utils.deepMergeObject(
self.$utils.deepMergeObject(self.queryParams,
(self.beforeGetData && self.beforeGetData()) || {}),
queryParams)
self.$utils.deepMergeObject(self.queryParams,
(self.beforeGetData && self.beforeGetData()) || {}),
queryParams)
}
/**
* 列表数据加载混入
* 提供列表数据的加载分页下拉刷新上拉加载更多等功能
*/
export default {
data() {
return {
@ -28,16 +27,24 @@ export default {
list : [],
}
},
// 下拉刷新
onPullDownRefresh() {
this.getData()
},
// 上拉加载更多
onReachBottom() {
this.loadMoreData()
},
// 页面显示时加载数据
onShow() {
this.getData()
},
methods: {
/**
* 获取列表数据
* @param {Object} queryParams - 查询参数
* @returns {Promise} 返回Promise对象
*/
getData(queryParams){
return new Promise((success, error) => {
if(!this.mixinsListApi){
@ -47,20 +54,21 @@ export default {
query(this, queryParams), res => {
uni.stopPullDownRefresh()
if(res.code == 200){
this.getDataThen && this.getDataThen(res.result.records, res.result.total, res.result)
success(res.result)
this[this.mixinsListKey || 'list'] = res.result.records
this.total = res.result.total
// 更新列表数据
this[this.mixinsListKey || 'list'] = res.result.records || res.result
// 更新总数
this.total = res.result.total || res.result.length
// 调用数据加载完成的回调
this.getDataThen && this.getDataThen(res.result.records, res.result.total, res.result)
}
})
})
},
/**
* 加载更多数据
*/
loadMoreData(){
console.log('loadMoreData----', this.queryParams.pageSize < this.total);
if(this.queryParams.pageSize < this.total){
this.queryParams.pageSize += 10
this.getData()


+ 70
- 0
mixins/order.js View File

@ -0,0 +1,70 @@
export default {
data() {
return {
}
},
computed: {
},
methods: {
// 立即支付
toPayOrder(item){
let api = ''
// if([0, 1].includes(item.shopState)){
// api = 'createOrderTwo'
// }else{
api = 'createSumOrderAgain'
// }
this.$api(api, {
orderId : item.id,
addressId : item.addressId
}, res => {
if(res.code == 200){
uni.requestPaymentWxPay(res)
.then(res => {
uni.showToast({
title: '支付成功',
icon: 'none'
})
this.getData()
}).catch(n => {
this.getData()
})
}
})
},
// 确认收货
confirmOrder(item){
uni.showModal({
title: '您收到货了吗?',
success : e => {
if(e.confirm){
this.$api('confirmOrder', {
orderId : item.id,
}, res => {
this.getData()
})
}
}
})
},
// 取消订单
cancelOrder(item){
uni.showModal({
title: '确认取消订单吗?',
success : e => {
if(e.confirm){
this.$api('cancelOrder', {
orderId : item.id,
}, res => {
this.getData()
})
}
}
})
},
}
}

+ 1
- 0
pages/index/cart.vue View File

@ -201,6 +201,7 @@
justify-content: center;
align-items: center;
overflow: hidden;
z-index: 999;
.icon{
position: relative;
width: 80rpx;


+ 221
- 54
pages_order/auth/loginAndRegisterAndForgetPassword.vue View File

@ -1,10 +1,63 @@
<template>
<view class="refundsOrExchange">
<navbar :title="titleList[titleIndex]" leftClick @leftClick="$utils.navigateBack" />
<navbar :title="titleList[titleIndex]" leftClick
@leftClick="$utils.redirectTo('/pages/index/index')" />
<view class="frame">
<!-- 登录和注册 -->
<view class="loginRegister" v-if='titleIndex!=2'>
<!-- 注册 -->
<view class='forgetPassword' v-if='titleIndex == 0'>
<!-- 标题 -->
<view class="title">{{titleList[titleIndex]}}</view>
<!-- 表单 -->
<view class="form1">
<view class="userName">
<uv-input v-model="form1.username" placeholder="请输入手机号" border="surround" shape='circle'
clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
<view class="code">
<view class="left">
<uv-input v-model="form1.captcha" placeholder="请输入验证码" border="surround" shape='circle'
clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
<view class="right">
<view>
<uv-toast ref="toast"></uv-toast>
<uv-code :seconds="seconds" @end="end" @start="start" ref="code"
@change="codeChange"></uv-code>
<uv-button @tap="getCode" iconSize='10rpx' color='#1f1c39'
shape='circle'>{{tips}}</uv-button>
</view>
</view>
</view>
<view class="password1">
<uv-input v-model="form1.password" placeholder="设置您的新密码(6到50个字符)" password clearable
border="surround" shape='circle' :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
<view class="password2">
<uv-input v-model="form1.newPassword" placeholder="重新确认密码" password clearable border="surround"
shape='circle' :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
</view>
<view>
<uv-checkbox-group v-model="checkboxValue" shape="circle">
<view class="content">
<view style="display: flex;">
<uv-checkbox size="30rpx" :name="1"></uv-checkbox>
请你阅读并同意我们的<span style="color: #fd5100"
@click="$refs.popup.open('getPrivacyPolicy')">隐私条款</span><span
style="color: #fd5100"
@click="$refs.popup.open('getUserAgreement')">服务协议</span>
</view>
</view>
</uv-checkbox-group>
</view>
</view>
<!-- 登录 -->
<view class="loginRegister" v-if='titleIndex==1'>
<!-- 标题 -->
<view class="title">{{titleList[titleIndex]}}</view>
@ -18,8 +71,8 @@
<!-- 用户名&密码&隐私条款 -->
<view class="form">
<view>
<uv-input v-model="form.account" placeholder="请输入账号" border="surround" shape='circle'
clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
<uv-input v-model="form.username" placeholder="请输入账号" border="surround" shape='circle' clearable
:customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
<view>
<uv-input v-model="form.password" password placeholder="请输入密码" border="surround" shape='circle'
@ -28,12 +81,12 @@
<view>
<uv-checkbox-group v-model="checkboxValue" shape="circle">
<view class="content">
<view style="display: flex;flex-wrap: wrap;">
<view style="display: flex;">
<uv-checkbox size="30rpx" :name="1"></uv-checkbox>
请你阅读并同意我们的<span style="color: #fd5100"
@click="$refs.popup.open('getPrivacyPolicy')">隐私条款</span><span
@click="$refs.popup.open('yszc')">隐私条款</span><span
style="color: #fd5100"
@click="$refs.popup.open('getUserAgreement')">服务协议</span>
@click="$refs.popup.open('fwxy')">服务协议</span>
</view>
</view>
</uv-checkbox-group>
@ -44,19 +97,19 @@
</view>
<!-- 忘记密码 -->
<view class='forgetPassword' v-if='titleIndex==2'>
<view class='forgetPassword' v-if='titleIndex == 2'>
<!-- 标题 -->
<view class="title">{{titleList[titleIndex]}}</view>
<!-- 表单 -->
<view class="form1">
<view class="userName">
<uv-input v-model="form1.userName" placeholder="请输入手机号/用户/邮箱" border="surround" shape='circle'
<uv-input v-model="form1.username" placeholder="请输入手机号" border="surround" shape='circle'
clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
<view class="code">
<view class="left">
<uv-input v-model="form1.code" placeholder="请输入验证码" border="surround" shape='circle'
<uv-input v-model="form1.captcha" placeholder="请输入验证码" border="surround" shape='circle'
clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
<view class="right">
@ -64,32 +117,31 @@
<uv-toast ref="toast"></uv-toast>
<uv-code :seconds="seconds" @end="end" @start="start" ref="code"
@change="codeChange"></uv-code>
<uv-button @tap="getCode" iconSize='10rpx' color='#fd5100'
<uv-button @tap="getCode" iconSize='10rpx' color='#1f1c39'
shape='circle'>{{tips}}</uv-button>
</view>
</view>
</view>
<view class="password1">
<uv-input v-model="form1.password1" placeholder="设置您的新密码(6到50个字符)" password clearable
<uv-input v-model="form1.password" placeholder="设置您的新密码(6到50个字符)" password clearable
border="surround" shape='circle' :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
<view class="password2">
<uv-input v-model="form1.password2" placeholder="重新确认密码" password clearable border="surround"
<uv-input v-model="form1.newPassword" placeholder="重新确认密码" password clearable border="surround"
shape='circle' :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input>
</view>
</view>
</view>
<!-- 按钮 -->
<view class="btn"
@click="submit">
<view class="btn" @click="submit">
<button class='a'>{{titleList[titleIndex]}}</button>
</view>
<!-- tab -->
<!-- <view class="bottomTab">
<view class="bottomTab">
<span :class="titleIndex==0 ? 'tabbarItemActive' : 'tabbarItemNoActive'"
@click='changePage(0)'>注册账号</span>
<span style="color: #9c9fa4">|</span>
@ -98,8 +150,8 @@
<span style="color: #9c9fa4">|</span>
<span :class="titleIndex==2 ? 'tabbarItemActive' : 'tabbarItemNoActive'"
@click='changePage(2)'>忘记密码</span>
</view> -->
</view>
</view>
@ -123,36 +175,133 @@
titleList: ['注册', '登录', '重置密码'],
checkboxValue: [],
form: {
account: '13135294009',
password: 'lzx123456',
username: '',//19330214982
password: '',//1234567
loginModel: 0,
captcha: '',
},
form1: {
userName: '',
code: '',
password1: '',
password2: '',
username: '',
captcha: '',
password: '',
newPassword: '',
},
tips: '获取验证码',
seconds: 60,
}
},
methods: {
submit(){
if(!this.checkboxValue.length){
submit() {
if (!this.checkboxValue.length && this.titleIndex != 2) {
return uni.showToast({
title: '请先同意隐私协议',
icon:'none'
icon: 'none'
})
}
if (this.titleIndex == 0) {
//
this.register()
} else if (this.titleIndex == 1) {
//
this.login()
} else {
//
this.updatePassword()
}
},
//
login(){
if (this.$utils.verificationAll(this.form, {
username: '请输入账号',
password: '请输入密码',
})) {
return
}
if (!this.$utils.verificationPhone(this.form.username)) {
return uni.showToast({
title: '请输入合法的手机号',
icon: 'none'
})
}
if(this.$utils.verificationAll(this.form, {
account: '请输入账号',
password: '请输入密码',
})){
//
this.$store.commit('login', this.form)
},
//
register(){
if (this.$utils.verificationAll(this.form1, {
username: '请输入账号',
captcha : '请输入验证码',
password: '请输入密码',
newPassword: '请确认密码',
})) {
return
}
this.$store.commit('accountLogin', this.form)
if (!this.$utils.verificationPhone(this.form1.username)) {
return uni.showToast({
title: '请输入合法的手机号',
icon: 'none'
})
}
if (this.form1.password != this.form1.newPassword) {
return uni.showToast({
title: '密码与确认密码不一致',
icon: 'none'
})
}
this.$api('registerUser', this.form1, res => {
this.form1 = {}
if (res.code == 200) {
this.titleIndex = 1
uni.showToast({
title: '注册成功,请登录!',
icon: 'none'
})
}
})
},
updatePassword(){
if (this.$utils.verificationAll(this.form1, {
username: '请输入账号',
captcha : '请输入验证码',
password: '请输入新密码',
newPassword: '请确认密码',
})) {
return
}
if (!this.$utils.verificationPhone(this.form1.username)) {
return uni.showToast({
title: '请输入合法的手机号',
icon: 'none'
})
}
if (this.form1.password != this.form1.newPassword) {
return uni.showToast({
title: '密码与确认密码不一致',
icon: 'none'
})
}
this.$api('newPassword', this.form1, res => {
this.form1 = {}
if (res.code == 200) {
this.titleIndex = 1
uni.showToast({
title: '修改成功,请登录!',
icon: 'none'
})
}
})
},
//
changePage(index) {
@ -167,17 +316,28 @@
},
getCode() {
if (this.$refs.code.canGetCode) {
//
if (!this.$utils.verificationPhone(this.form1.username)) {
return uni.showToast({
title: '请输入合法的手机号',
icon: 'none'
})
}
uni.showLoading({
title: '正在获取验证码'
})
setTimeout(() => {
uni.hideLoading();
// this.start()
uni.$uv.toast('验证码已发送');
//
this.$refs.code.start();
}, 2000);
this.$api('sendSms', {
username: this.form1.username,
}, res => {
if (res.code == 200) {
uni.hideLoading();
// this.start()
uni.$uv.toast('验证码已发送');
//
this.$refs.code.start();
}
})
} else {
uni.$uv.toast('请勿重复发送');
}
@ -197,11 +357,16 @@
* {
box-sizing: border-box;
}
.content{
font-size: 22rpx;
margin: 0 auto;
}
.refundsOrExchange {
background-color: #FFF;
height: 100vh;
.frame {
background-color: #FFF;
@ -209,6 +374,7 @@
display: flex;
flex-direction: column;
gap: 40rpx;
padding-bottom: 50rpx;
.title {
display: flex;
@ -234,7 +400,8 @@
}
.form {
line-height: 50rpx;
height: 12vh;
>view:nth-of-type(1) {
padding: 20rpx 100rpx;
}
@ -246,18 +413,18 @@
>view:nth-of-type(3) {
display: flex;
padding: 30rpx 100rpx 0 100rpx;
font-size: 22rpx
font-size: 22rpx;
}
}
}
.btn {
// height: 5vh;
display: flex;
justify-content: center;
margin: 90rpx 0 0 0;
.a {
display: flex;
justify-content: center;
@ -266,23 +433,23 @@
height: 80rpx;
color: #FFF;
background-color: $uni-color;
border: 1px solid red;
box-shadow: 0 0 4rpx 4rpx rgba($uni-color, 0.2);
border-radius: 100rpx;
font-size: 30rpx;
}
}
.bottomTab {
display: flex;
justify-content: space-between;
height: 10vh;
padding: 0 80rpx;
margin-top: 30rpx;
.tabbarItemActive {
color: $uni-color;
}
.tabbarItemNoActive {
color: #9c9fa4;
}


+ 9
- 7
pages_order/auth/wxLogin.vue View File

@ -18,6 +18,10 @@
<!-- <view class="btn b2">
使用短信验证登录
</view> -->
<view class="btn b2"
@click="qux">
取消登录
</view>
@ -58,7 +62,6 @@
}
},
methods: {
wxLogin(){
if(!this.checkboxValue.length){
return uni.showToast({
@ -68,12 +71,11 @@
}
this.$store.commit('login')
},
//
openConfigDetail(key){
this.$refs.popup.open(key)
}
qux(){
uni.reLaunch({
url: '/pages/index/index'
})
},
}
}
</script>


+ 0
- 93
pages_order/components/commodity/commoditySelect.vue View File

@ -1,93 +0,0 @@
<template>
<view style="">
<view v-for="item in commodityList" :key="item.title" class="address-item">
<view class="itme1" @click="selectSp(item)">
<view class="left">
<img src="../../../static/image/center/1.png" alt="" style="width: 100%;height: 100%;">
</view>
<view class="center">
<view>{{ item.title }}</view>
<view>{{ item.smallTitle }}</view>
</view>
<view class="right">×{{item.total}}</view>
</view>
<uv-line></uv-line>
</view>
</view>
</template>
<script>
export default {
props: {
commodityList: {
default: [],
type: Array,
}
},
data() {
return {
selectAddress: 0,
}
},
methods: {
//
openCommodity() {
this.$emit('openSpPopup')
},
//
selectSp(e) {
console.log(this.commodityList,"this.csss")
console.log(e, '选择了商品')
this.$emit('selectSp', e)
}
}
}
</script>
<style scoped lang="scss">
.itme1 {
display: flex;
height: 150rpx;
width: 100vw;
background-color: #ffffff;
.left {
padding: 40rpx;
width: 20%;
border-radius: 10rpx;
background-color: #ffffff;
}
.center {
display: flex;
flex-direction: column;
justify-content: center;
gap: 20rpx;
width: 70%;
padding: 0rpx 0 0 20rpx;
background-color: #ffffff;
// view
> view:first-of-type {
font-size: 36rpx;
color: #333;
}
// view
> view:nth-of-type(2) {
font-size: 28rpx;
color: #666666;
}
}
.right {
display: flex;
justify-content: center;
align-items: center;
width: 10%;
color: #666666;
background-color: #ffffff;
}
}
</style>

+ 0
- 3
pages_order/order/refundsOrExchange.vue View File

@ -80,21 +80,18 @@
<!--商品选择-->
<uv-popup ref="spPopup" :round="30">
<commoditySelect :commodityList="commodityList" @selectSp="selectCommodity" />
</uv-popup>
</view>
</template>
<script>
import commoditySelect from "../components/commodity/commoditySelect.vue"
export default {
onLoad(option) {
this.titleIndex = option.index
},
components: {
commoditySelect
},
data() {
return {


+ 53
- 0
utils/authorize.js View File

@ -0,0 +1,53 @@
function authorize(scope){
return new Promise((success, error) => {
uni.authorize({
/* scope.writePhotosAlbum 类型是保存到相册 */
scope,
success,
complete(res) {
/* 判断如果没有授权就打开设置选项让用户重新授权 */
uni.getSetting({
success(res) {
if (!res.authSetting[scope]) {
setting()
}
}
});
}
});
function setting(){
uni.showModal({
title: '当前操作未授权,请授权!',
content: '拒绝授权将影响本小程序部分功能的使用',
confirmText: '授权',
success(e) {
if(!e.confirm){
return error()
}
uni.openSetting({
success(res) {
if (!res.authSetting[scope]) {
uni.showToast({
title: '授权失败',
icon: 'none',
})
return error()
}
success()
}
});
}
})
}
})
}
export default authorize

+ 30
- 0
utils/index.js View File

@ -3,6 +3,8 @@ import Vue from 'vue'
import util from './utils.js'
import time from './timeUtils.js'
import authorize from './authorize.js'
import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs'
@ -24,6 +26,7 @@ import { handleTree } from './tree.js'
Vue.prototype.$handleTree = handleTree
Vue.prototype.$Oss = Oss
Vue.prototype.$dayjs = dayjs
Vue.prototype.$authorize = authorize
Vue.prototype.$timeUtils = time
Vue.prototype.$utils = util
@ -44,4 +47,31 @@ Vue.prototype.openLocation = (latitude, longitude) => {
latitude : Number(latitude),
longitude : Number(longitude),
})
}
// 封装微信支付
uni.requestPaymentWxPay = function(res){
return new Promise((success, error) => {
uni.requestPayment({
provider: 'wxpay', // 服务提提供商
timeStamp: res.result.timeStamp, // 时间戳
nonceStr: res.result.nonceStr, // 随机字符串
package: res.result.packageValue,
signType: res.result.signType, // 签名算法
paySign: res.result.paySign, // 签名
success: function (res) {
console.log('支付成功',res);
success(res)
},
fail: function (err) {
console.log('支付失败',err);
error(err)
uni.showToast({
icon:'none',
title:"支付失败"
})
}
});
})
}

+ 1
- 10
utils/oss-upload/oss/index.js View File

@ -2,10 +2,7 @@
* 阿里云OSS工具类
*/
import OSSConfig from "@/utils/oss-upload/oss/OSSConfig.js"
//支持web端
import {
uploadFileToOSS
} from '@/utils/oss-upload/oss/web.js'
import ossConfig from '@/config.js'
/**
@ -93,9 +90,6 @@ export function ossUploadImage({
count: 1,
sizeType,
success(res) {
// // #ifdef H5
// return uploadFileToOSS(res.tempFiles[0]).then(success).catch(fail)
// // #endif
ossUpload(res.tempFilePaths[0], key, folder).then(success).catch(fail)
},
fail
@ -123,9 +117,6 @@ export function ossUploadVideo({
maxDuration,
camera,
success(res) {
// // #ifdef H5
// return uploadFileToOSS(res.tempFile).then(success).catch(fail)
// // #endif
ossUpload(res.tempFilePath, key, folder).then(success).catch(fail)
},
fail


+ 20
- 12
utils/pay.js View File

@ -3,26 +3,35 @@
import jWeixin from './lib/jweixin-module.js'
// #endif
/**
* 调用微信支付
* @param {Object} res - 支付参数对象包含appIdtimeStampnonceStr等必要信息
* @param {Function} successCallback - 支付成功的回调函数
* @param {Function} failCallback - 支付失败的回调函数
* @param {Function} optionCallback - 配置失败的回调函数
*/
export function wxPay(res, successCallback, failCallback, optionCallback) {
// 配置微信JSSDK
jWeixin.config({
debug: false,
appId: res.result.appId, //必填
jsApiList: ['chooseWXPay']
appId: res.result.appId, //必填,公众号的唯一标识
jsApiList: ['chooseWXPay'] //必填,需要使用的JS接口列表
});
// JSSDK配置成功后的回调
jWeixin.ready(function() {
// 调用微信支付接口
jWeixin.chooseWXPay({
appId: res.result.appId,
timestamp: res.result
.timeStamp, // 支付签名时间戳,注意微信 jssdk 中的所有使用 timestamp 字段均为小写。但最新版的支付后台生成签名使用的 timeStamp 字段名需大写其中的 S 字符
nonceStr: res.result.nonceStr, // 支付签名随机串,不长于 32 位
package: res.result.packageValue, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: res.result.signType, // 微信支付V3的传入 RSA ,微信支付V2的传入格式与V2统一下单的签名格式保持一致
timestamp: res.result.timeStamp, // 支付签名时间戳
nonceStr: res.result.nonceStr, // 支付签名随机串
package: res.result.packageValue, // 统一支付接口返回的prepay_id参数值
signType: res.result.signType, // 签名类型,默认为MD5
paySign: res.result.paySign, // 支付签名
success: function() { // 支付成功取消处理
success: function() {
successCallback && successCallback();
},
fail: function(error) { // 支付失败或取消处理
fail: function(error) {
failCallback && failCallback();
},
cancel : function(){
@ -31,9 +40,8 @@ export function wxPay(res, successCallback, failCallback, optionCallback) {
});
});
// JSSDK配置失败处理
jWeixin.error(function(res) {
// 配置失败处理
optionCallback && optionCallback()
});
}
}

+ 70
- 35
utils/utils.js View File

@ -1,3 +1,8 @@
/**
* 将数据转换为数组格式
* @param {any} data - 需要转换的数据
* @returns {Array} 转换后的数组
*/
function toArray(data) {
if (!data) return []
if (data instanceof Array){
@ -7,6 +12,10 @@ function toArray(data) {
}
}
/**
* 生成UUID
* @returns {string} 生成的UUID字符串
*/
function generateUUID() {
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0,
@ -15,6 +24,10 @@ function generateUUID() {
});
}
/**
* 生成随机颜色
* @returns {string} 生成的十六进制颜色值
*/
function generateRandomColor() {
const letters = '0123456789ABCDEF';
let color = '#';
@ -24,6 +37,10 @@ function generateRandomColor() {
return color;
}
/**
* 生成浅色系的随机颜色
* @returns {string} 生成的RGB格式颜色值
*/
function generateLightRandomColor() {
const min = 150;
const range = 105;
@ -34,6 +51,12 @@ function generateLightRandomColor() {
return color;
}
/**
* 表单数据验证
* @param {Object} data - 需要验证的表单数据
* @param {Object} msg - 验证失败时的提示信息
* @returns {boolean} 验证结果true表示验证失败false表示验证通过
*/
function verificationAll(data, msg){
if (!msg){
@ -57,39 +80,14 @@ function verificationAll(data, msg){
return true
}
}
// let Msgs = {
// default : msg || '表单数据未填写'
// }
// if(typeof msg == 'object'){
// Msgs = {
// default : '表单数据未填写',
// ...msg,
// }
// }
// if (!data){
// uni.showToast({
// title: Msgs.default,
// icon: "none"
// })
// return true
// }
// for (let key in data) {
// if (!data[key] || data[key] === "") {
// uni.showToast({
// title: (Msgs[key] || Msgs.default),
// icon: "none"
// })
// return true
// }
// }
return false
}
//验证手机号是否合法
/**
* 验证手机号是否合法
* @param {string} phone - 需要验证的手机号
* @returns {boolean} 验证结果true表示合法false表示不合法
*/
function verificationPhone(phone){
if(!/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(phone)){
return false
@ -98,6 +96,11 @@ function verificationPhone(phone){
}
//获取url中参数的方法
/**
* 获取URL中指定参数的值
* @param {string} name - 参数名称
* @returns {string} 参数值如果不存在则返回空字符串
*/
export function getHrefParams(name) {
var url = window.location.href;
try {
@ -114,8 +117,12 @@ export function getHrefParams(name) {
}
}
//深度对比合并两个对象,相同属性b会覆盖a
/**
* 深度合并两个对象相同属性b会覆盖a
* @param {Object} a - 目标对象
* @param {Object} b - 源对象
* @returns {Object} 合并后的新对象
*/
export function deepMergeObject(a, b){
let data = JSON.parse(JSON.stringify(a))
function mergeObject(obj1, obj2){
@ -131,7 +138,10 @@ export function deepMergeObject(a, b){
return mergeObject(data, b)
}
//复制内容
/**
* 复制文本到剪贴板
* @param {string} content - 要复制的内容
*/
export function copyText(content) {
uni.setClipboardData({
data: content,
@ -144,12 +154,21 @@ export function copyText(content) {
})
}
// 将字符串中的文本格式化html
/**
* 将字符串中的文本格式化为HTML
* @param {string} str - 需要格式化的字符串
* @returns {string} 格式化后的HTML字符串
*/
export function stringFormatHtml(str){
return str && str.replace(/\n/gi, '<br>')
.replace(/ /gi, ' ')
}
/**
* 处理页面导航参数
* @param {string|Object} url - 页面路径或导航参数对象
* @returns {Object} 处理后的导航参数对象
*/
function params(url){
if(typeof url == 'object'){
return url
@ -166,18 +185,34 @@ function params(url){
return data
}
/**
* 页面导航方法
* @param {...any} args - 导航参数
*/
export function navigateTo(...args){
uni.navigateTo(params(...args))
}
/**
* 返回上一页
* @param {number} num - 返回的页面数默认为-1
*/
export function navigateBack(num = -1){
uni.navigateBack(num)
}
/**
* 重定向到指定页面
* @param {...any} args - 导航参数
*/
export function redirectTo(...args){
uni.redirectTo(params(...args))
}
/**
* 登录跳转函数防止短时间内多次调用
* @returns {Function} 节流处理后的登录跳转函数
*/
export const toLogin = function(){
let time = 0
return () => {


Loading…
Cancel
Save