Compare commits

...

86 Commits

Author SHA1 Message Date
msb_39367 550ea9ddf9 feature: 添加打包资源
5 months ago
王景 a83f41c883 feat: update package-lock
1 year ago
王景 0237f70511 docs: 添加Node版本描述
1 year ago
ch 24df19af14 Merge branch 'fix/0714-ch'
2 years ago
ch fad9ff6ccb fix:修改服务启动名
2 years ago
ch f360233caa Merge branch 'fix/0714-ch' of https://internel-git.mashibing.cn/yanxuan-frontend/shop-app
2 years ago
ch 0508a6d9df pref:固定端口号
2 years ago
ch 041e15495d fix:下架商品
2 years ago
ch 2a42d55fb6 fix:static地址
2 years ago
ch d1f0e5fbd4 支付回调页面
2 years ago
ch 874340f948 修改打包方式
2 years ago
ch 39f379875b pay
2 years ago
ch 5d8a42f48c pay
2 years ago
ch b59d0698ae clear
2 years ago
ch 194587ba1b fix: 商品已下架
2 years ago
ch 9f195f09b7 fix: 商品已下架
2 years ago
ch a35cb72501 fix:点赞提示,已够吗问题
2 years ago
ch c010790f96 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch f20ced40ad 分页最后一页判断修改
2 years ago
ch 03dab5bd96 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 314f79f2ae 分页最后一页判断修改
2 years ago
ch 24ba55fa25 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 7e7ab987b1 分页最后一页判断修改
2 years ago
ch 5832a43169 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch b3cd9615ca 分页最后一页判断修改
2 years ago
ch fb70e2306f 修改分页判断
2 years ago
ch 0ce97eb86b Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 460ba55458 提交
2 years ago
ch 325bee7e80 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch ffc9769565 修改评论跳转
2 years ago
ch 0ce7d20886 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 4011d2d49c 上传预览
2 years ago
ch 774b4f4064 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 4880836a27 产品验收问题
2 years ago
ch 251d091312 Merge branch 'feature/alipay-0629-ch' into msb_test
2 years ago
ch 987566558d 增长支付订单状态查询
2 years ago
ch ffdb3e549f Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch e0b48c9ea6 fix:修改产品验收问题
2 years ago
ch 1e6de755bd APP支付
2 years ago
ch d4a93fed3d Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch b198706159 取消商家回复
2 years ago
ch 6cc4720315 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 71f9e086d7 评论回复实时显示顺序问题
2 years ago
ch df1a27323d Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 4490d1af99 追评
2 years ago
ch f278d52028 修改标签统计接口Token
2 years ago
ch 0391e24745 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 3e9f8e617e fix:回复长英文显示问题
2 years ago
ch 907bcabad2 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 3739301d83 fix:修改页面刷新全局样式丢失问题
2 years ago
ch 5dc332c05f Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 3d61ca3c1e 修改回复自己用户名
2 years ago
ch 410a721436 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 588a41d196 修改
2 years ago
ch 03e27975b4 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 9722f26b90 fix:评论
2 years ago
ch b2d1f2d9c0 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch f6c4182e68 纯空格不让提交
2 years ago
ch efdf803082 纯空格不让提交
2 years ago
ch e5634eeacb 配置支付宝支付
2 years ago
ch d1ba4b1842 Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 2b3e4a954b config
2 years ago
ch 46a6767afb Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch f11b0ee085 config
2 years ago
ch 96def57eaa Merge branch 'feature/comment-0620-ch' into msb_test
2 years ago
ch 6b2adcaf6a config
2 years ago
ch 2f1332b05d Merge branch 'feature/alipay-0629-ch' into msb_test
2 years ago
ch ec932a429b 支付宝支付
2 years ago
ch 5b6e2d46d2 评论统计不做TK校验
2 years ago
ch a27ce47f65 评论统计不做TK校验
2 years ago
ch 6892041093 修改评论数量
2 years ago
ch a75e6b163c fix:去追评报错
2 years ago
ch 98f910dbe9 fix:评论商品信息跳转到详情
2 years ago
ch 1d3fa277b2 fix:其他评价的页面点击事件
2 years ago
ch ac0fc976ed fix:其他评价的页面点击事件
2 years ago
ch 4e65eeb11a fix: 修复预览相关BUg
2 years ago
ch dd0b6345d5 修改BUg
2 years ago
ch 8f0bc44425 fix:修改点赞
2 years ago
ch 5c62b79812 修改图标
2 years ago
ch 925d13cc40 fix:个人中心添加待评价按钮
2 years ago
ch 90e514436b 修改预览页面
2 years ago
ch 8891cc6734 评价
2 years ago
ch e814e1aa0c Merge branch 'fix/0614-ch' into msb_prod
2 years ago
ch 5aff24319d fix:修改?
2 years ago
ch 47c4d8c11c Merge branch 'fix/0614-ch' into msb_prod
2 years ago
ch c2d0857ca1 fix:消息不显示
2 years ago

@ -1,4 +1,3 @@
VUE_APP_BASE_URL = https://k8s-horse-gateway.mashibing.cn
VUE_APP_STATIC_URL = https://k8s-shop-app.mashibing.cn
#VUE_APP_IM_URL = ws://192.168.10.94:8090
VUE_APP_IM_URL = wss://k8s-horse-gateway.mashibing.cn

@ -1,3 +1,3 @@
VUE_APP_BASE_URL = https://you-gateway.mashibing.com
VUE_APP_STATIC_URL = https://you-gateway.mashibing.com
VUE_APP_STATIC_URL = https://you-app.mashibing.com
VUE_APP_IM_URL = wss://you-gateway.mashibing.com

@ -1,3 +1,3 @@
VUE_APP_BASE_URL = https://you-gateway.mashibing.com
VUE_APP_STATIC_URL = https://you-gateway.mashibing.com
VUE_APP_STATIC_URL = https://you-app.mashibing.com
VUE_APP_IM_URL = wss://you-gateway.mashibing.com

@ -5,17 +5,27 @@
* @LastEditTime: 2022-05-23 21:18:34
* @Description: file content
-->
# shopping-app
严选移动端
## 前置环境
由于项目依赖问题,开发 `node` 版本必须是 `14` or `16`
如果想安装多个版本,可以通过使用 `nvm` 进行版本管理。然具体安装可以参考下面教程
[window install nvm](https://juejin.cn/post/7074108351524634655)
[mac install nvm](https://juejin.cn/post/7206882855200047161)
## 公共方法 utils
- 公共方法统一放置 utils 文件夹内,可以按分类建方法文件 如:验证类 verify.js 请求类 request.js
- 所有公共方法采用大驼峰命名法
- 所有的方法都从 index.js 输出,引入时统一引入 index不允许直接引入方法文件
- 所有方法文件如果导出的是多个方法,不允许在定义方法时导出,必须在文件底部一一导出,并附上方法简单的注释
```js
// 正确
import {Req, IsPhone} from '@/common/utils';
@ -39,16 +49,19 @@ export const IsPhone = (str) => {....}
export const IsEmail = (str) => {....}
```
## 组件
- 请务必使用 easycom 模式引入第三方组件
- 根目录的 components 只放置真正的组件,某个页面的业务模块应该在 pages 的相应目录下新建 components 目录放置
- 所有的自定义组件文件名以大驼峰命名,且在 templet 中使用也用大驼峰形式使用
## 请求
- 所有请求方法命名以Api+请求类型+具体方) 法命名
- 所有请求使用 ToAsyncAwait 包裹
- 不允许使用 try catch 和 then 处理返回结果
```js
// 使用示例
// xxapi.js
@ -71,6 +84,8 @@ export const IsEmail = (str) => {....}
}
```
## 图片
- 按 pages 目录结果放置图片
- 有公共使用的图片请放到 static/common 文件夹内

@ -1,47 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-05 14:40:00
* @LastEditors: ch
* @LastEditTime: 2022-06-09 11:25:44
* @Description: 根据git分支生成对应环境的环境变量
* 开发时如果环境变量换了可以不用重启服务直接运行node env.config.js即可
*/
const fs = require('fs');
const path = require('path');
const envConfig = {
dev : {
baseUrl: 'https://k8s-horse-gateway.mashibing.cn',
staticUrl : 'https://k8s-shop-app.mashibing.cn',
// imUrl : 'ws://192.168.10.94:8090'
imUrl : 'wss://k8s-horse-gateway.mashibing.cn'
},
test : {
baseUrl: 'https://k8s-horse-gateway.mashibing.cn',
staticUrl : 'https://k8s-shop-app.mashibing.cn',
imUrl : 'wss://k8s-horse-gateway.mashibing.cn'
},
beta : {
baseUrl: 'https://you-gateway.mashibing.com',
staticUrl : 'https://you-app.mashibing.com',
imUrl : 'wss://you-gateway.mashibing.com'
},
prod : {
baseUrl: 'https://you-gateway.mashibing.com',
staticUrl : 'https://you-app.mashibing.com',
imUrl : 'wss://you-gateway.mashibing.com'
}
}
let curEnvConfig = null;
const argv = global.process.argv;
for(key in envConfig){
if(argv.includes(`--ENV:${key}`)){
curEnvConfig = envConfig[key];
break;
}
}
if(!curEnvConfig){
curEnvConfig = envConfig.dev;
}
fs.writeFileSync(`${path.resolve(__dirname, './src/common/config')}/env.js`,
`const ENV = ${JSON.stringify(curEnvConfig)}; export default ENV;`);

23183
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -3,15 +3,18 @@
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "node env.config.js & npm run dev:h5",
"serve:bate": "node env.config.js --ENV:beta & npm run dev:h5",
"serve:prod": "node env.config.js --ENV:prod & npm run dev:h5",
"build": "npm run build:h5",
"server": "npm run dev:h5",
"server:test": "npm run dev:h5-test",
"server:bate": "npm run dev:h5-bate",
"server:prod": "npm run dev:h5-prod",
"build:test": "npm run build:h5-test",
"build:bate": "npm run build:h5-bate",
"build:prod": "npm run build:h5-prod",
"build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",
"build:custom": "cross-env NODE_ENV=production uniapp-cli custom",
"build:h5": "node env.config.js --ENV:test & cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
"build:h5:bate": "node env.config.js --ENV:beta & cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
"build:h5:prod": "node env.config.js --ENV:prod & cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
"build:h5-test": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode test",
"build:h5-bate": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode bate",
"build:h5-prod": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode prod",
"build:mp-360": "cross-env NODE_ENV=production UNI_PLATFORM=mp-360 vue-cli-service uni-build",
"build:mp-alipay": "cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build",
"build:mp-baidu": "cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build",
@ -29,6 +32,9 @@
"dev:app-plus": "cross-env NODE_ENV=development UNI_PLATFORM=app-plus vue-cli-service uni-build --watch",
"dev:custom": "cross-env NODE_ENV=development uniapp-cli custom",
"dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve",
"dev:h5-test": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve --mode test",
"dev:h5-bate": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve --mode bate",
"dev:h5-prod": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve --mode prod",
"dev:mp-360": "cross-env NODE_ENV=development UNI_PLATFORM=mp-360 vue-cli-service uni-build --watch",
"dev:mp-alipay": "cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch",
"dev:mp-baidu": "cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch",
@ -71,35 +77,36 @@
"@dcloudio/uni-quickapp-webview": "^2.0.1-34720220422002",
"@dcloudio/uni-stat": "^2.0.1-34720220422002",
"@vue/shared": "^3.0.0",
"caniuse-lite": "^1.0.30001640",
"core-js": "^3.6.5",
"flyio": "^0.6.2",
"regenerator-runtime": "^0.12.1",
"vue": "^2.6.11",
"vuex": "^3.2.0",
"js-util-all": "^1.0.6",
"mp-html": "^2.2.2",
"regenerator-runtime": "^0.12.1",
"uni-read-pages": "^1.0.5",
"uni-simple-router": "^2.0.7",
"uview-ui": "^2.0.29"
"uview-ui": "^2.0.29",
"vue": "^2.6.11",
"vuex": "^3.2.0"
},
"devDependencies": {
"@babel/runtime": "~7.12.0",
"@dcloudio/types": "^2.6.7",
"@dcloudio/uni-automator": "^2.0.1-34720220422002",
"@dcloudio/uni-cli-i18n": "^2.0.1-34720220422002",
"@dcloudio/uni-cli-shared": "^2.0.1-34720220422002",
"@dcloudio/uni-migration": "^2.0.1-34720220422002",
"@dcloudio/uni-template-compiler": "^2.0.1-34720220422002",
"@dcloudio/vue-cli-plugin-hbuilderx": "^2.0.1-34720220422002",
"@dcloudio/vue-cli-plugin-uni": "^2.0.1-34720220422002",
"@dcloudio/vue-cli-plugin-uni-optimize": "^2.0.1-34720220422002",
"@dcloudio/webpack-uni-mp-loader": "^2.0.1-34720220422002",
"@dcloudio/webpack-uni-pages-loader": "^2.0.1-34720220422002",
"@dcloudio/uni-automator": "2.0.2-4010520240507001",
"@dcloudio/uni-cli-i18n": "2.0.2-4010520240507001",
"@dcloudio/uni-cli-shared": "2.0.2-4010520240507001",
"@dcloudio/uni-migration": "2.0.2-4010520240507001",
"@dcloudio/uni-template-compiler": "2.0.2-4010520240507001",
"@dcloudio/vue-cli-plugin-hbuilderx": "2.0.2-4010520240507001",
"@dcloudio/vue-cli-plugin-uni": "2.0.2-4010520240507001",
"@dcloudio/vue-cli-plugin-uni-optimize": "2.0.2-4010520240507001",
"@dcloudio/webpack-uni-mp-loader": "2.0.2-4010520240507001",
"@dcloudio/webpack-uni-pages-loader": "2.0.2-4010520240507001",
"@vue/cli-plugin-babel": "~4.5.15",
"@vue/cli-service": "~4.5.15",
"babel-plugin-import": "^1.11.0",
"cross-env": "^7.0.2",
"jest": "^25.4.0",
"babel-plugin-import": "1.13.8",
"cross-env": "7.0.3",
"jest": "25.5.4",
"mini-types": "*",
"miniprogram-api-typings": "*",
"postcss-comment": "^2.0.0",

@ -1,3 +1,10 @@
<!--
* @Author: ch
* @Date: 2022-05-27 17:44:36
* @LastEditors: ch
* @LastEditTime: 2022-06-29 21:37:10
* @Description: file content
-->
<!DOCTYPE html>
<html lang="zh-CN">
@ -14,7 +21,7 @@
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
</head>
<body>
<body class="page">
<noscript>
<strong>Please enable JavaScript to continue.</strong>
</noscript>

@ -0,0 +1,66 @@
/*
* @Author: ch
* @Date: 2022-06-20 11:38:48
* @LastEditors: ch
* @LastEditTime: 2022-06-30 11:53:57
* @Description: file content
*/
import {ToAsyncAwait, MsbRequest, MsbRequestTk} from '@/common/utils';
const BASE_URL = '/mall/comment';
/**
* 根据商品获取评论列表
* @param {*} param0
*/
export const ApiGetCommentList = (params) =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/comment`,params, {
notVerifyToken: true
}));
/**
* 根据商品获取评论总数
* @param {*} param0
*/
export const ApiGetCommentCount = ({productId}) =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/comment/getAllCommentCountByProductId/${productId}`,{}, {
notVerifyToken: true
}));
/**
* 根据商品获取标签评论总数
* @param {*} param0
*/
export const ApiGetCommentTabCount = ({productId}) =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/comment/listCommentLabel/${productId}`,{}, {
notVerifyToken: true
}));
/**
* 获取订单评论详情
* @param {*} param0
*/
export const ApiGetOrderCommentDetail = ({orderId}) =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/comment/listOrderCommentByOrderId/${orderId}`));
/**
* 获取评论详情
* @param {*} param0
*/
export const ApiGetCommentDetail = ({commentId}) =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/comment/getCommentDetail/${commentId}`,{}, {
notVerifyToken: true
}));
/**
* 新增评论
* @param {*} param0
*/
export const ApiPostComment = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/app/comment`, data));
/**
* 更新评论有用数
* @param {*} param0
*/
export const ApiPutCommentUseful = (data) =>
ToAsyncAwait(MsbRequestTk.put(`${BASE_URL}/app/comment/updateUsefulCount`,data));

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-29 17:38:17
* @LastEditors: ch
* @LastEditTime: 2022-05-10 16:14:53
* @LastEditTime: 2022-06-23 16:21:32
* @Description: file content
*/
import {ToAsyncAwait, MsbRequestTk} from '@/common/utils';
@ -84,8 +84,11 @@ export const ApiPutCancelOrder = (data) =>
export const ApiGetOrderStatistics = () =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/tradeOrder/statistics`));
/**
* 获取待评价订单详请列表
*/
export const ApiGetCommentOrderDetailList = (params) =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/tradeOrder/listOrderProductWaitComment`,params))
/**

@ -0,0 +1,51 @@
/*
* @Author: ch
* @Date: 2022-04-28 16:30:54
* @LastEditors: ch
* @LastEditTime: 2022-07-09 10:16:00
* @Description: file content
*/
import {ToAsyncAwait, MsbRequest, MsbRequestTk} from '@/common/utils';
const BASE_URL = '/mall/trade';
export const ApiPostCashierPrepay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/cashierPrepay`, data));
/**
* 微信h5支付获取支付URL
* @param {*} data
*/
export const ApiPostWxH5Pay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/wxPay/h5`, data));
/**
* 微信JSAPI支付获取支付参数
* @param {*} data
*/
export const ApiPostWxJsApiPay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/wxPay/jsapi`, data));
/**
* 微信APP支付
* @param {*} data
*/
export const ApiPostWxAppPay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/wxPay/app`, data));
/**
* 支付宝APP支付
* @param {*} data
*/
export const ApiPostAliAppPay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/aliPay/app`, data));
/**
* 支付宝h5支付获取支付URL
* @param {*} data
*/
export const ApiPostAliH5Pay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/aliPay/wap`, data));

@ -2,13 +2,12 @@
* @Author: ch
* @Date: 2022-04-28 16:30:54
* @LastEditors: ch
* @LastEditTime: 2022-06-15 14:29:03
* @LastEditTime: 2022-06-29 17:16:50
* @Description: file content
*/
import {ToAsyncAwait, MsbRequest, MsbRequestTk} from '@/common/utils';
const BASE_URL = '/mall/trade';
// 第三方鉴权服务
const AUTH_URL = '/third';
const APPID = 'wxd2015f0c56defa02';
@ -33,24 +32,3 @@ export const ApiGetOpenId = ({code}) =>
*/
export const ApiPostThirdInfo = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${AUTH_URL}/third/saveThirdInfo`, {...data, appId:APPID}));
/**
* 微信h5支付获取支付URL
* @param {*} data
*/
export const ApiPostWxH5Pay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/wxPay/h5`, data));
/**
* 微信JSAPI支付获取支付参数
* @param {*} data
*/
export const ApiPostWxJsApiPay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/wxPay/jsapi`, data));
/**
* 微信APP支付
* @param {*} data
*/
export const ApiPostWxAppPay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/payCenter/wxPay/app`, data));

@ -0,0 +1,33 @@
/*
* @Author: ch
* @Date: 2022-06-20 11:10:23
* @LastEditors: ch
* @LastEditTime: 2022-06-28 16:33:25
* @Description: file content
*/
export default {
TYPE : {
// 评价
COMMENT: 1,
// 追评
FOLLOW_COMMENT: 2,
// 回复
ANSWER: 3,
},
// 是否显示
DISPLAY: {
SHOW: 1,
HIDE : 0
},
// 用户类型
USER_TYPE: {
STORE : 1,
USER : 2
},
// 是否默认评价
IS_DEFAULT_COMMENT: {
YES: 1,
NOT : 0
},
RATE_LABEL : ['非常不满意','不满意','一般','满意','非常满意']
}

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-05-26 11:49:16
* @LastEditors: ch
* @LastEditTime: 2022-05-26 17:00:06
* @LastEditTime: 2022-06-22 11:23:02
* @Description: file content
*/
@ -11,7 +11,8 @@ export const ORDER_STATUS = {
// 待支付
AWAIT_PAY: 1
}
export const ORDER_TYPE = {
export default {
TYPE : {
//(1, "普通订单"),
NORMAL: 1,
//(2, "免费订单"),
@ -20,4 +21,15 @@ export const ORDER_TYPE = {
SECKILL: 3,
//(4, "虚拟商品订单"),
VIRTUAL : 4
},
// 订单状态 1待支付2已关闭3已支付4已发货5已收货6已完成7已追评
STATUS: {
AWAIT_PAY: 1,
CLOSE: 2,
FINISH_PAY: 3,
FINISH_SEND_GOODS: 4,
FINISH_TAKE_GOODS: 5,
FINISH: 6,
FINISH_FOLLOW_COMMENT : 7
}
}

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-18 11:11:05
* @LastEditors: ch
* @LastEditTime: 2022-03-18 11:11:05
* @LastEditTime: 2022-07-12 18:31:15
* @Description: file content
*/
import {RouterMount,createRouter} from 'uni-simple-router';
@ -13,6 +13,11 @@ const router = createRouter({
});
//全局路由前置守卫
router.beforeEach((to, from, next) => {
// 兼容页面刷新body样式丢失问题
// console.log(document);
if (document) {
document.body.setAttribute('class', `uni-body ${to.path.replace('/', '').replace(/\//g, '-')}`)
}
next();
});
// 全局路由后置守卫

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-22 18:28:52
* @LastEditors: ch
* @LastEditTime: 2022-06-14 17:33:42
* @LastEditTime: 2022-06-22 15:31:09
* @Description: file content
*/
import Vue from 'vue'
@ -19,7 +19,9 @@ const
// oppenId
OPPED_ID = 'oi',
// 每个浏览器创建一个UUID作为同一个用户的标识
UUID = 'uid';;
UUID = 'uid',
// 评价图片预览数据
COMMENT_PREVIEW = 'comment_preview';
export default new Vuex.Store({
state: {
@ -28,6 +30,7 @@ export default new Vuex.Store({
address: JSON.parse(uni.getStorageSync(ADDRESS) || '[]'),
openId: uni.getStorageSync(OPPED_ID) || '',
uuid: uni.getStorageSync(UUID) || '',
comment_preview: JSON.parse(uni.getStorageSync(COMMENT_PREVIEW) || '{}'),
imData : [],
imMsgCount : 0
},
@ -52,6 +55,10 @@ export default new Vuex.Store({
state.openId = data;
uni.setStorageSync(OPPED_ID, data);
},
SET_COMMENT_PREVIEW(state, data) {
state.comment_preview = data;
uni.setStorageSync(COMMENT_PREVIEW, JSON.stringify(data));
},
SET_IM_DATA (state, data){
state.imData = data ;
},

@ -0,0 +1,50 @@
/*
* @Author: ch
* @Date: 2022-04-29 14:26:10
* @LastEditors: ch
* @LastEditTime: 2022-07-13 10:37:21
* @Description: file content
*/
import { ApiPostAliH5Pay, ApiPostAliAppPay } from '@/common/api/pay';
const ENV = process.env;
export const Alipay = async ({orderId})=>{
// #ifdef APP-PLUS
const {error, result} = await ApiPostAliAppPay({orderId});
if(error){
uni.$u.toast(error.message);
return false;
}
const par = result.payDataInfo;
uni.requestPayment({
provider: 'alipay',
orderInfo :par.payData,
success(res) {
uni.navigateTo({
url : `/payResult?orderId=${orderId}&payType=appWx`
});
},
fail(e) {
uni.navigateTo({
url : `/payResult?orderId=${orderId}&payType=appWx`
});
}
}).then(res => {
console.log('res',res);
})
// #endif
// #ifdef H5
const { error, result } = await ApiPostAliH5Pay({
orderId,
returnUrl : decodeURIComponent(`${ENV.VUE_APP_STATIC_URL}/payResult?orderId=${orderId}&payType=alih5`)
});
if(error){
uni.$u.toast(error.message);
return false;
}
window.location.href = result.payDataInfo.payUrl;
// #endif
}

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-05-20 11:00:07
* @LastEditors: ch
* @LastEditTime: 2022-06-13 10:11:33
* @LastEditTime: 2022-07-13 10:37:52
* @Description: file content
*/
@ -11,7 +11,7 @@ import { ToAsyncAwait, FormatJsonSearch } from '@/common/utils';
import { ApiGetCurrentUser } from '@/common/api/account';
import { ApiGetSoketTicket } from '@/common/api/im';
import $store from '@/common/store';
import ENV from '@/common/config/env';
const ENV = process.env;
const Im = new MsbIm({
reconnect: true,
@ -31,7 +31,7 @@ const ImInit = async () => {
avatar : $store.state.userInfo.avatar
})
await ToAsyncAwait(Im.init({
url: `${ENV.imUrl}/ws${par}`
url: `${ENV.VUE_APP_IM_URL}/ws${par}`
}))
};

@ -2,17 +2,22 @@
* @Author: ch
* @Date: 2022-03-22 16:52:28
* @LastEditors: ch
* @LastEditTime: 2022-05-20 11:42:33
* @LastEditTime: 2022-06-29 17:28:39
* @LastEditTime: 2022-06-29 17:22:32
* @Description: 所有工具类统一在这输出
*/
import * as util from './utils';
import * as requset from './requset';
import * as im from './im';
import * as wxpay from './wxpay';
import * as uploadFileOss from './uploadFileOss';
import * as alipay from './alipay';
export * from './utils';
export * from './requset';
export * from './im';
export * from './wxpay';
export * from './uploadFileOss';
export * from './alipay';
export default { ...util, ...requset, ...im, ...wxpay}
export default { ...util, ...requset, ...im, ...wxpay, ...uploadFileOss, ...alipay}

@ -2,10 +2,9 @@
* @Author: ch
* @Date: 2022-05-06 15:33:55
* @LastEditors: ch
* @LastEditTime: 2022-06-15 14:26:16
* @LastEditTime: 2022-07-13 10:38:34
* @Description: file content
*/
import ENV from '@/common/config/env';
import { Wxpay } from './wxpay';
export const pay = ({orderId, openId, payType})=>{
if(payType === 'wxpay'){

@ -2,14 +2,14 @@
* @Author: ch
* @Date: 2022-03-17 17:42:32
* @LastEditors: ch
* @LastEditTime: 2022-06-14 17:33:14
* @LastEditTime: 2022-07-13 10:39:07
* @Description: 项目接口请求统一处理器返回一个需要token和不需要token的请求封装方法
*/
import MsbUniRequest from '@/common/plugins/msbUniRequest';
import $store from '@/common/store';
import ENV from '@/common/config/env';
import { CreateUUID } from '@/common/utils';
const ENV = process.env;
// 获取已有的UUID没则创建一个并保存到locaStorage中下次使用
let uuid = $store.state.uuid
@ -82,8 +82,7 @@ const clearRepeat = (option) =>{
// 不需要token的接口封装
const MsbRequest = new MsbUniRequest();
console.log(process.env,'process.envprocess.envprocess.env');
MsbRequest.baseUrl = ENV.baseUrl;
MsbRequest.baseUrl = ENV.VUE_APP_BASE_URL;
MsbRequest.use('request', (option) => {
if(option.header.repeat){
@ -103,18 +102,19 @@ MsbRequest.use('error', errorIntercept);
// 需要token的接口封装
const MsbRequestTk = new MsbUniRequest();
MsbRequestTk.baseUrl = ENV.baseUrl;
MsbRequestTk.baseUrl = ENV.VUE_APP_BASE_URL;
MsbRequestTk.use('request', (option) => {
const token = $store.state.token;
option.header.uid = uuid;
if(!token){
if(!token && !option.header.notVerifyToken){
// 登录状态处理没有token直接跳转至登录
uni.redirectTo({
url: '/login'
});
return Promise.reject({message:'要先登录才能操作哦~'});
}else{
}
delete option.header.notVerifyToken
option.header = {...option.header, Authorization:token};
if(option.header.repeat){
@ -125,7 +125,6 @@ MsbRequestTk.use('request', (option) => {
}
}
return option;
}
})
MsbRequestTk.use('success', successIntercept);
MsbRequestTk.use('error', errorIntercept);

@ -0,0 +1,46 @@
/*
* @Author: ch
* @Date: 2022-06-21 15:03:11
* @LastEditors: ch
* @LastEditTime: 2022-06-22 14:49:20
* @Description: file content
*/
import { ApiPostGetOssConfig } from '@/common/api/oss';
import {ToAsyncAwait} from '@/common/utils'
/**
*
* @param {*} file 文件
* @param {*} param1 获取OSS鉴权信息参数参考ApiPostGetOssConfig接口
* @returns {Promise}
*/
export const uploadFileOss = (file, {configId, serviceName}) =>{
return ToAsyncAwait(new Promise(async (resolve, reject) => {
const urlArr = file.url.split('/');
const fileName = file.name || urlArr[urlArr.length - 1];
const { error, result:oss } = await ApiPostGetOssConfig({ configId : `${configId}/`, serviceName });
if (error) {
reject(error);
return false
}
uni.uploadFile({
name : 'file',
filePath : file.url,
url : oss.host,
formData : {
name : fileName,
key : `${oss.dir}${'${filename}'}`,
policy : oss.policy,
OSSAccessKeyId : oss.accessId,
success_action_status : 200,
signature : oss.signature
},
success : async (res)=>{
resolve(`${oss.host}/${oss.dir}${fileName}`);
},
fail(e) {
reject(e);
}
})
}
))
}

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-17 19:15:10
* @LastEditors: ch
* @LastEditTime: 2022-06-02 14:55:45
* @LastEditTime: 2022-07-13 10:39:35
* @Description: 一些无法归类的公共方法容器
*/
@ -15,7 +15,6 @@ import {
formatJsonSearch as FormatJsonSearch
} from "js-util-all";
import ENV from '@/common/config/env';
import {AD_JUMP_TYPE} from '@/common/dicts/ad';
/**
@ -43,11 +42,6 @@ const Debounce = (fn, delay) => {
* @param {*} link
*/
const AdJump = (item) => {
// if (!/^(http|https):\/\/./.test(link)) {
// uni.$u.toast('非法链接,暂不跳转!');
// return false;
// }
console.log(item);
switch (item.jumpType) {
case AD_JUMP_TYPE.GOODS:
uni.navigateTo({
@ -71,6 +65,21 @@ const AdJump = (item) => {
break
}
}
/**
* api接口错误处理
* @param {*} error 错误体
* @param {*} name 接口名 非必传如操作时错误提示不需要提示接口名时可不传
* @return Boolean true 存在错误并处理 false无错误
*/
const HandleApiError = (error, name) => {
let result = false
if (error) {
const tip = name ? `${name}错误:` : ``;
uni.$u.toast(`${tip}${error.message}`);
result = true;
}
return result;
}
// 工具类的文件需要把文件提供的工具类统一放最下方做一个统一输出
export {
// async await 标识结果处理
@ -85,5 +94,6 @@ export {
// 防抖函数
Debounce,
// 广告跳转
AdJump
AdJump,
HandleApiError
}

@ -2,12 +2,12 @@
* @Author: ch
* @Date: 2022-04-29 14:26:10
* @LastEditors: ch
* @LastEditTime: 2022-06-15 14:43:50
* @LastEditTime: 2022-07-13 10:40:10
* @Description: file content
*/
import { ApiPostWxH5Pay, ApiPostWxJsApiPay, ApiPostWxAppPay } from '@/common/api/wx';
import ENV from '@/common/config/env';
import { ApiPostWxH5Pay, ApiPostWxJsApiPay, ApiPostWxAppPay } from '@/common/api/pay';
const ENV = process.env;
export const Wxpay = async ({orderId,openId})=>{
// #ifdef APP-PLUS
@ -74,7 +74,7 @@ export const Wxpay = async ({orderId,openId})=>{
uni.$u.toast(error.message);
return false;
}
const redirect_url = decodeURIComponent(`${ENV.staticUrl}/payResult?orderId=${orderId}&payType=wxh5`);
const redirect_url = decodeURIComponent(`${ENV.VUE_APP_STATIC_URL}/payResult?orderId=${orderId}&payType=wxh5`);
window.location.href = `${result.payDataInfo.h5Url}&redirect_url=${redirect_url}`;
}
// #endif

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-20 16:45:27
* @LastEditors: ch
* @LastEditTime: 2022-05-06 14:26:57
* @LastEditTime: 2022-06-22 19:34:13
* @Description: file content
-->
<template>
@ -38,10 +38,10 @@ export default {
...this.params
});
const res = result.records.map(item => {
// item.labelList[{text:'x',code : 'recommended'},{text:'x',code : 'second_kill'}]
//
item.seckill = false;
item.tagList = [];
item.labelList = item.labelList || [];
item.labelList.forEach(i => {
if(i.code === 'second_kill'){
item.seckill = true;

@ -0,0 +1,85 @@
<!--
* @Author: ch
* @Date: 2022-06-23 10:40:04
* @LastEditors: ch
* @LastEditTime: 2022-06-30 18:01:46
* @Description: file content
-->
<template>
<view class="follow">
<view class="follow--title">{{day}}追评:</view>
<view class="follow--ctx">{{followComment.commentContent}}</view>
<view class="follow--img" v-if="imgs.length">
<image class="follow--img-item" v-for="(item, idx) in imgs" :src="item" :key="idx" @click="preview(idx)" mode="aspectFit"/>
</view>
</view>
</template>
<script>
export default {
props : {
commentDetail : {
type : Object,
default : () => ({})
}
},
computed:{
followComment(){
return this.commentDetail.followComment || {}
},
day(){
const followTime = (new Date(this.followComment.createTime)).getTime();
const commentTime = (new Date(this.commentDetail.createTime)).getTime();
const day = Math.floor((followTime - commentTime) / (24 * 60 * 60 * 1000));
return day > 0 ? `${day}天后` : `当天`;
},
imgs (){
let urls = this.followComment.pictureUrl || '';
return urls ? urls.split(',') : [];
}
},
methods:{
preview(idx){
this.$store.commit('SET_COMMENT_PREVIEW', {
...this.commentDetail,
commentContent : this.followComment.commentContent,
pictureUrl : this.followComment.pictureUrl
});
this.$Router.push({
path : '/goodsCommentPreview',
query : {
idx
}
});
}
}
}
</script>
<style lang="scss" scoped>
.follow{
margin-top: 40rpx;
&--title{
color: $color-yellow3;
font-size: 28rpx;
}
&--ctx{
margin-top: 20rpx;
font-size: 30rpx;
line-height: 46rpx;
word-break: break-all;
}
&--img{
margin-top: 30rpx;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
&-item{
width: 210rpx;
height: 210rpx;
margin:20rpx 0;
}
}
}
</style>

@ -0,0 +1,66 @@
<!--
* @Author: ch
* @Date: 2022-06-20 14:30:45
* @LastEditors: ch
* @LastEditTime: 2022-06-28 21:14:46
* @Description: file content
-->
<template>
<view class="goods" @click="$Router.push(`/goodsDetail?id=${goods.productId}`)">
<image class="goods--img" :src="goods.productPicture" mode="aspectFit" ></image>
<view class="goods--ctx">
<view class="goods--title">{{ goods.productName }}</view>
<view class="goods--footer">
<view class="goods--sku">{{ goods.skuName }}</view>
<view><slot name="btns"></slot></view>
</view>
</view>
</view>
</template>
<script>
export default {
props : {
goods : {
type : Object,
default : ()=>({})
}
}
}
</script>
<style lang="scss" scoped>
.goods {
display: flex;
&--img {
width: 130rpx;
height: 130rpx;
margin-right: 30rpx;
}
&--ctx{
flex: 1;
overflow: hidden;
padding: 20rpx 0;
}
&--title{
font-size: 28rpx;
overflow:hidden;
text-overflow:ellipsis;
white-space: nowrap;
padding-right: 30rpx;
}
&--footer{
display: flex;
justify-content: space-between;
padding-right: 30rpx;
}
&--sku{
font-size: 24rpx;
color: #999;
margin-top: 20rpx;
}
}
</style>

@ -0,0 +1,93 @@
<!--
* @Author: ch
* @Date: 2022-06-21 15:50:01
* @LastEditors: ch
* @LastEditTime: 2022-06-30 18:00:16
* @Description: file content
-->
<template>
<view>
<view class="top">
<u-rate count="5" size="30rpx" :value="commentDetail.commentScore" activeColor="#FFA35B" readonly inactiveColor="#DDD"></u-rate>
<text class="top--time">{{ FormatDate(commentDetail.createTime, 'yyyy-mm-dd hh:ii') }}</text>
</view>
<view class="ctx">{{ commentDetail.commentContent }}</view>
<view class="img" v-if="imgs.length">
<image class="img--item" mode="aspectFit"
v-for="(item, idx) in imgs" :src="item" :key="idx" @click="preview(idx)"/>
</view>
</view>
</template>
<script>
import {FormatDate} from '@/common/utils';
export default {
props : {
commentDetail : {
type : Object,
default : () => ({})
},
imgPreview : {
type: Boolean,
default : true,
require : true
}
},
data(){
return {
curPreview : -1
}
},
computed : {
imgs (){
let urls = this.commentDetail.pictureUrl || '';
return urls ? urls.split(',') : [];
}
},
methods:{
FormatDate,
preview(idx){
if(!this.imgPreview){
return false
}
this.$store.commit('SET_COMMENT_PREVIEW', this.commentDetail);
this.$Router.push({
path : '/goodsCommentPreview',
query : {
idx
}
});
}
}
}
</script>
<style lang="scss" scoped>
.top{
display: flex;
justify-content: space-between;
margin: 20rpx 0;
&--time{
font-size: 24rpx;
color: #999;
}
}
.ctx{
font-size: 30rpx;
line-height: 46rpx;
word-break: break-all;
}
.img{
margin-top: 30rpx;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
&--item{
width: 210rpx;
height: 210rpx;
margin:20rpx 0;
}
}
</style>

@ -0,0 +1,56 @@
<!--
* @Author: ch
* @Date: 2022-06-21 15:59:23
* @LastEditors: ch
* @LastEditTime: 2022-06-30 17:57:25
* @Description: file content
-->
<template>
<view class="merchant">
<view class="merchant--title">
<text class="merchant--name">{{merchantComment.userName}}</text>
<text class="merchant--time">{{ FormatDate(merchantComment.createTime, 'yyyy-mm-dd hh:ii') }}
</text>
</view>
<view class="merchant--ctx">{{merchantComment.commentContent}}</view>
</view>
</template>
<script>
import {FormatDate} from '@/common/utils';
export default {
props : {
merchantComment : {
type : Object,
default : () => ({})
}
},
data(){
return {
}
},
methods : {
FormatDate
}
}
</script>
<style lang="scss" scoped>
.merchant{
margin-top: 40rpx;
padding: 30rpx;
background: #F5F5F5;
&--title{
display: flex;
justify-content: space-between;
margin-bottom: 24rpx;
}
&--time{
color: #999;
font-size: 24rpx;
}
&--ctx,&--name{
font-size: 26rpx;
color: #666;
}
}
</style>

@ -0,0 +1,138 @@
<!--
* @Author: ch
* @Date: 2022-06-20 16:36:14
* @LastEditors: ch
* @LastEditTime: 2022-06-30 21:06:31
* @Description: file content
-->
<template>
<view>
<view class="rate" v-if="type === COMMENT.TYPE.COMMENT">
<text class="rate--title">满意度评分</text>
<u-rate :count="5" v-model="rate" size="47rpx" activeColor="#FFA35B" inactiveColor="#DDD"></u-rate>
<text class="rate--desc">{{rateDesc}}</text>
</view>
<textarea class="textarea" placeholder="从多个维度评价,可以帮助更多想买的人哦~"
:maxlength="500" v-model="commentContent"></textarea>
<u-upload class="upload"
@afterRead="handleUpdateImg" @delete="handleDelImg"
:fileList="fileList" :maxCount="6" :previewFullImage="true">
</u-upload>
<view class="footer">
<UiButton type="solid" :disable="isVerify" @click="handleSubmit">
{{type === COMMENT.TYPE.COMMENT ? '发表评价' : '发表追评'}}
</UiButton>
</view>
</view>
</template>
<script>
import UiButton from '@/components/UiButton.vue';
import {ApiPostComment} from '@/common/api/comment';
import COMMENT from '@/common/dicts/comment';
import {uploadFileOss, HandleApiError} from '@/common/utils';
export default {
components: { UiButton },
props:{
type : {
type : String | Number,
default : COMMENT.TYPE.COMMENT
},
commentDetail : {
type : Object,
default : ()=> ({})
}
},
data(){
return {
COMMENT,
rate : 5,
commentContent : '',
fileList : []
}
},
computed:{
isVerify(){
if(this.type === COMMENT.TYPE.COMMENT){
return !this.rate || !this.commentContent.trim();
}else{
return !this.commentContent.trim();
}
},
isEdit (){
return ( this.commentContent || this.fileList.length > 0) ? true : false
},
rateDesc(){
return COMMENT.RATE_LABEL[this.rate-1];
}
},
watch:{
isEdit(){
this.$emit('editChang',this.isEdit)
}
},
methods:{
async handleSubmit(){
let data = {
commentContent : this.commentContent,
commentType : this.type,
orderProductId : this.commentDetail.orderProductId,
pictureUrl : this.fileList.map(i => i.url).join(',')
}
if(this.type === COMMENT.TYPE.COMMENT){
data.productId = this.commentDetail.productId;
data.commentScore = this.rate;
}else if(this.type === COMMENT.TYPE.FOLLOW_COMMENT){
data.originId = data.parentId = this.commentDetail.id;
}
const {error, result} = await ApiPostComment(data);
if(!HandleApiError(error)){
this.commentContent = '';
this.fileList = [];
this.$nextTick(()=>{
this.$emit('submit',result);
})
}
},
async handleUpdateImg(val){
const {error, result} = await uploadFileOss(val.file, {
configId : 'account-comment',
serviceName : 'comment'
})
if(error){
uni.$u.toast(error);
}
this.fileList.push({url : result});
},
handleDelImg(target){
this.fileList.splice(target.index, 1)
}
}
}
</script>
<style lang="scss" scoped>
.rate{
display: flex;
margin: 50rpx 0;
align-items: center;
&--title{
font-size: 28rpx;
margin-right: 30rpx;
}
&--desc{
font-size: 30rpx;
color: #999;
margin-left: 40rpx;
}
}
.textarea{
height: 200rpx;
margin-bottom: 40rpx;
}
.footer{
width: 100%;
text-align: right;
margin-top: 50rpx;
}
</style>

@ -0,0 +1,96 @@
<!--
* @Author: ch
* @Date: 2022-06-21 16:01:19
* @LastEditors: ch
* @LastEditTime: 2022-07-01 17:55:01
* @Description: file content
-->
<template>
<view class="thumb">
<view class="thumb--item" @click="handleUseful">
<u-icon name="thumb-up-fill" v-if="isLike"></u-icon>
<u-icon name="thumb-up" v-else></u-icon>
<text>{{usefulCount}}</text>
</view>
<view class="thumb--item" @click="$Router.push(`/goodsCommentDetail?id=${commentDetail.id}`)">
<u-icon name="chat"></u-icon>
<text>{{commentDetail.replyCount}}</text>
</view>
</view>
</template>
<script>
import {Debounce, HandleApiError} from '@/common/utils';
import {ApiPutCommentUseful} from '@/common/api/comment'
export default {
props : {
commentDetail : {
type : Object,
default : ()=>({})
}
},
data(){
return {
debounce : null,
isLike : false,
usefulCount : 0
}
},
watch :{
commentDetail :{
handler(){
this.isLike = this.commentDetail.isLike;
this.usefulCount = this.commentDetail.usefulCount;
},
deep:true
}
},
mounted(){
this.isLike = this.commentDetail.isLike;
// console.log('---',this.isLike,this.commentDetail.usefulCount);
this.usefulCount = this.commentDetail.usefulCount;
},
methods:{
handleUseful(){
this.isLike = !this.isLike
if(this.isLike){
this.usefulCount++;
}else{
this.usefulCount--;
}
if(!this.debounce){
this.debounce = Debounce(this.updateUseFul, 500);
}
this.debounce();
},
async updateUseFul(){
if(this.isLike === this.commentDetail.isLike){
return false
}
const {error, result} = await ApiPutCommentUseful({
commentId : this.commentDetail.id,
isLike : this.isLike
});
HandleApiError(error);
}
}
}
</script>
<style lang="scss" scoped>
.thumb{
display: flex;
justify-content: flex-end;
margin-top: 40rpx;
&--item{
display: flex;
align-items: center;
margin-left: 50rpx;
text{
font-size: 24rpx;
margin-left: 10rpx;
}
}
}
</style>

@ -0,0 +1,47 @@
<!--
* @Author: ch
* @Date: 2022-06-21 22:27:52
* @LastEditors: ch
* @LastEditTime: 2022-07-01 17:14:36
* @Description: file content
-->
<template>
<view class="comment-user">
<image class="comment-user--avatr" :src="userData.userAvatar" shape="circle"/>
<view>
<view class="comment-user--name">{{userData.userName}}</view>
<text class="comment-user--sku" v-if="userData.skuName">{{userData.skuName}}</text>
</view>
</view>
</template>
<script>
export default {
props : {
userData : {
type : Object,
default : ()=> ({})
}
}
}
</script>
<style lang="scss" scoped>
.comment-user{
display: flex;
justify-content: flex-start;
&--avatr{
width: 71rpx;
height: 71rpx;
margin-right: 17rpx;
}
&--name{
margin-top: 5rpx;
}
&--sku{
margin-top: 10rpx;
font-size: 24rpx;
color: #999;
}
}
</style>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-04-19 11:37:50
* @LastEditors: ch
* @LastEditTime: 2022-05-05 11:08:44
* @LastEditTime: 2022-06-29 17:27:12
* @Description: file content
-->
<template>
@ -12,7 +12,7 @@
<script>
import UiRadioPicker from './UiRadioPicker.vue'
import { ApiPostWxPay } from '@/common/api/order';
import { Wxpay } from '@/common/utils';
import { Wxpay, Alipay } from '@/common/utils';
export default {
components: { UiRadioPicker },
props : {
@ -32,13 +32,19 @@ export default {
label : '微信支付',
value : 'wxpay'
},
// {
// label : '',
// value : 'alipay'
// }
]
}
},
mounted(){
// APP
if(!this.$store.state.openId){
this.options.push({
label : '支付宝支付',
value : 'alipay'
})
}
},
methods:{
confirm(val){
const orderId = this.order.orderId;
@ -46,7 +52,8 @@ export default {
Wxpay({orderId, openId: this.$store.state.openId});
this.close();
}else{
uni.$u.toast('暂不支持支付宝支付');
// uni.$u.toast('');
Alipay({orderId})
}
},
close(){

@ -2,11 +2,11 @@
* @Author: ch
* @Date: 2022-03-31 15:42:55
* @LastEditors: ch
* @LastEditTime: 2022-04-19 13:57:30
* @LastEditTime: 2022-06-22 14:12:46
* @Description: file content
-->
<template>
<view class="ui-white-box">
<view class="ui-white-box" @click="$emit('click')">
<slot></slot>
</view>
</template>
@ -14,6 +14,6 @@
.ui-white-box{
margin: 20rpx 30rpx;
background: $color-grey0;
border-radius: 20rpx;
border-radius: 8rpx;
}
</style>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2021-07-26 23:22:16
* @LastEditors: ch
* @LastEditTime: 2022-06-13 10:15:03
* @LastEditTime: 2022-06-20 17:38:48
* @Description: file content
*/
import Vue from 'vue';
@ -13,6 +13,7 @@ import uView from 'uview-ui';
import store from '@/common/store';
import {FormatSearchJson} from '@/common/utils';
import {ApiGetOpenId, ApiGetAuthUrl} from '@/common/api/wx';
import {ApiGetCurrentUser} from '@/common/api/account';
import {Im, ImInit} from '@/common/utils';
import { ApiSktSysGetSession, ApiSktSysHeart } from './common/api/im';
@ -30,11 +31,23 @@ const socketInit = () => {
});
}
const getUserInfo = async () => {
const { error, result } = await ApiGetCurrentUser();
if (error) {
uni.$u.toast(error.message);
return false;
}
store.commit('SET_USER_INFO', result);
};
if (store.state.token) {
socketInit();
getUserInfo();
}
// 微信打开需要授权
const ua = navigator ? navigator.userAgent.toLowerCase() : '';
if(ua.includes('micromessenger')) {

@ -1,6 +1,6 @@
{
"name" : "马士兵严选",
"appid" : "__UNI__3FB31B6",
"appid" : "__UNI__5FEB250",
"description" : "",
"versionName" : "1.0.1",
"versionCode" : "100",
@ -40,10 +40,14 @@
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
],
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
"minSdkVersion" : 21
},
/* ios */
"ios" : {},
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"ad" : {},
@ -52,39 +56,18 @@
"__platform__" : [ "android" ],
"appid" : "wx17b34a4a90ef18f7",
"UniversalLinks" : ""
},
"alipay" : {
"__platform__" : [ "android" ]
}
}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
"hdpi" : "src/static/app-icon/72.png",
"xhdpi" : "src/static/app-icon/96.png",
"xxhdpi" : "src/static/app-icon/144.png",
"xxxhdpi" : "src/static/app-icon/192.png"
}
}
}
@ -118,20 +101,7 @@
"base" : ""
},
"devServer" : {
"proxy" : {
"/uc/" : {
"target" : "https://k8s-horse-gateway.mashibing.cn"
},
"/mall/" : {
"target" : "https://k8s-horse-gateway.mashibing.cn"
},
"/pay/" : {
"target" : "https://k8s-horse-gateway.mashibing.cn"
},
"/oss/" : {
"target" : "https://k8s-horse-gateway.mashibing.cn"
}
}
"port" : 8080
},
"optimization" : {
"treeShaking" : {

@ -10,6 +10,13 @@
"backgroundColor" : "#69ADE5"
}
},
{
"path": "pages/webView",
"aliasPath" : "/webView",
"style": {
"navigationBarTitleText": "收银台"
}
},
{
"path": "pages/login",
"aliasPath" : "/login",
@ -58,6 +65,42 @@
"navigationBarTitleText": "马士兵严选"
}
},
{
"path": "pages/goods/enable",
"aliasPath" : "/enable",
"style": {
"navigationBarTitleText": "商品详情"
}
},
{
"path": "pages/goods/comment/list",
"aliasPath" : "/goodsCommentList",
"style": {
"navigationBarTitleText": "全部评价"
}
},
{
"path": "pages/goods/comment/otherList",
"aliasPath" : "/goodsCommentOtherList",
"style": {
"navigationBarTitleText": "全部评价"
}
},
{
"path": "pages/goods/comment/preview",
"aliasPath" : "/goodsCommentPreview",
"style": {
"navigationStyle" : "custom",
"navigationBarTitleText": "马士兵严选"
}
},
{
"path": "pages/goods/comment/detail",
"aliasPath" : "/goodsCommentDetail",
"style": {
"navigationBarTitleText": "全部评价"
}
},
{
"path": "pages/account/index",
"aliasPath" : "/account",
@ -177,6 +220,20 @@
"navigationBarTitleText": "支付中"
}
},
{
"path": "pages/order/comment/index/index",
"aliasPath" : "/comment",
"style": {
"navigationBarTitleText": "发表评价"
}
},
{
"path": "pages/order/comment/success",
"aliasPath" : "/commentSuccess",
"style": {
"navigationBarTitleText": "评价成功"
}
},
{
"path": "pages/order/saleAfter/saleAfterList",
"aliasPath" : "/saleAfterList",

@ -3,7 +3,7 @@
components: { UiCell },: ch
* @Date: 2019-08-22 19:41:20
* @LastEditors: ch
* @LastEditTime: 2022-06-01 15:15:11
* @LastEditTime: 2022-06-28 16:38:33
* @Description: file content
-->
<template>
@ -38,6 +38,11 @@
<image class="item-icon" src="@/static/account/sh.png"/>
<view>待收货</view>
</view>
<view class="order-tabs--item" @click="$Router.push('/orderList?tab=5')">
<u-badge class="item-badge" max="99" :value="statistic.waitComment"></u-badge>
<image class="item-icon" src="@/static/account/pj.png"/>
<view>待评价</view>
</view>
</view>
</view>
<view class="cell">

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-22 16:13:00
* @LastEditors: ch
* @LastEditTime: 2022-06-14 21:40:11
* @LastEditTime: 2022-06-17 16:31:20
* @Description: file content
-->
<template>
@ -18,15 +18,15 @@
<text class="msgItem--text" v-if="item.lastMessage">
<template v-if="item.lastMessage.type == msgType.TXT">{{item.lastMessage.payload.content || item.lastMessage.payload.text}}</template>
<template v-if="item.lastMessage.type == msgType.CUSTOM">
<template v-if="['returnLogistics','orderAutoDelivery','orderPay'].includes(item.lastMessage.payload.customType)">
{{item.lastMessage.payload.content}}
</template>
<template v-if="item.lastMessage.payload.customType === 'app_push'">
{{item.lastMessage.payload.link ? '[链接]' : item.lastMessage.payload.content}}
</template>
<template v-if="item.lastMessage.payload.customType === 'transferWaiterSession'">
[客服转移]
</template>
<template v-else>
{{item.lastMessage.payload.content || '[未知消息]'}}
</template>
</template>
<template v-if="item.lastMessage.type == msgType.IMG">[]</template>
<template v-if="item.lastMessage.type == msgType.VIDEO">[]</template>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-22 15:09:06
* @LastEditors: ch
* @LastEditTime: 2022-06-12 13:46:04
* @LastEditTime: 2022-06-23 17:45:29
* @Description: file content
-->
<template>
@ -28,6 +28,7 @@ export default {
return this.$store.state.userInfo
}
},
methods:{
logout(){
uni.showModal({

@ -0,0 +1,268 @@
<!--
* @Author: ch
* @Date: 2022-06-21 18:19:13
* @LastEditors: ch
* @LastEditTime: 2022-07-01 17:12:16
* @Description: file content
-->
<template>
<view>
<view class="box">
<BsCommentUserInfo :userData="detail"/>
<BsCommentInfo :commentDetail="detail"/>
<BsCommentFollowInfo v-if="detail.followComment" :commentDetail="detail"/>
<BsCommentGoodsInfo class="goods-info" :goods="detail" />
</view>
<view class="reply-title">全部评论( {{detail.replyCount}})</view>
<view class="reply">
<template v-if="detail.replyCount">
<view class="reply--item" v-if="detail.merchantComment">
<view class="reply--title">
<text>
{{detail.merchantComment.userName}}
</text>
<text>{{FormatDate(detail.merchantComment.createTime, 'yyyy-mm-dd hh:ii')}}</text>
</view>
<view class="reply--ctx">{{detail.merchantComment.commentContent}}</view>
</view>
<view class="reply--item" v-for="item in detail.answerCommentList" :key="item.id" @click="handleAnswer(item)">
<view class="reply--title">
<text>
{{item.userName}} {{item.parentId !== detail.id ? ` 回复 ${item.parentUserName}` : ''}}
</text>
<text>{{FormatDate(item.createTime, 'yyyy-mm-dd hh:ii')}}</text>
</view>
<view class="reply--ctx">{{item.commentContent}}</view>
</view>
</template>
<BsEmpty v-else tips="还没有人评论哦,快来抢沙发~"/>
</view>
<view class="footer">
<view class="footer--item" v-if="!detail.followComment && detail.userId === $store.state.userInfo.id"
@click="$Router.push(`/comment?commentId=${commentId}&follow=true`)">
<u-icon name="chat" size="28rpx"></u-icon>
追评
</view>
<view class="footer--item" @click="isShowAnswer = true">
<u-icon name="chat" size="28rpx"></u-icon>
评论
</view>
<view class="footer--item" :class="{'footer--item__active' : isLike}" @click="handleUseful">
<u-icon name="thumb-up" size="28rpx" :color="isLike ? '#FF875B' : ''"></u-icon>
有用<template v-if="detail.usefulCount">({{detail.usefulCount}})</template>
</view>
</view>
<template v-if="isShowAnswer" >
<view class="reply-comment--bg" @click="handleHideAnswer"></view>
<view class="reply-comment">
<view class="reply-comment--box">
<input class="reply-comment--input" maxlength="500" v-model="commentContent" :placeholder="placeholder" />
<UiButton type="gradual" :disable="!commentContent.trim()" @click="handleSubmit"></UiButton>
</view>
</view>
</template>
</view>
</template>
<script>
import BsCommentGoodsInfo from '../../../components/BsCommentGoodsInfo.vue'
import BsCommentInfo from '../../../components/BsCommentInfo.vue'
import BsCommentUserInfo from '../../../components/BsCommentUserInfo.vue'
import UiButton from '../../../components/UiButton.vue'
import {ApiGetCommentDetail, ApiPostComment, ApiPutCommentUseful} from '@/common/api/comment'
import {HandleApiError, Debounce, FormatDate} from '@/common/utils'
import COMMENT from '@/common/dicts/comment'
import BsEmpty from '../../../components/BsEmpty.vue'
import BsCommentFollowInfo from '../../../components/BsCommentFollowInfo.vue'
export default {
components: { BsCommentGoodsInfo, BsCommentInfo, UiButton, BsCommentUserInfo, BsEmpty, BsCommentFollowInfo },
data(){
return {
isShowAnswer : false,
answer : null,
commentId : this.$Route.query.id,
detail : {},
commentContent : '',
isLike : false
}
},
computed:{
placeholder(){
return this.answer ? `回复:${this.answer.userName}` : '说点什么吧?'
},
replyCount(){
}
},
onShow(){
this.getDetail();
},
methods:{
FormatDate,
async getDetail(){
const {error, result} = await ApiGetCommentDetail({
commentId : this.commentId
});
if(!HandleApiError(error,'getDetail')){
this.detail = result;
this.isLike = result.isLike || false;
this.detail.usefulCount = this.detail.usefulCount || 0;
this.detail.replyCount = this.detail.replyCount || 0;
// if(result.merchantComment){
// this.detail.answerCommentList.unshift({
// ...result.merchantComment,
// parentId : result.id
// })
// }
}
},
async handleSubmit(){
let data = {
commentContent : this.commentContent,
commentType : COMMENT.TYPE.ANSWER,
originId : this.detail.id,
parentId : this.answer ? this.answer.id : this.detail.id
}
const {error, result} = await ApiPostComment(data);
if(!HandleApiError(error)){
this.detail.answerCommentList.unshift({
...result,
userName : this.$store.state.userInfo.nickname,
parentUserName: this.answer ? this.answer.userName : ''
});
this.commentContent = '';
this.detail.replyCount++;
uni.$u.toast('评论成功!');
}
},
handleAnswer(item){
this.isShowAnswer = true;
this.answer = item;
},
handleHideAnswer(...e){
this.isShowAnswer = false;
this.answer = null;
},
handleUseful(){
this.isLike = !this.isLike
if(this.isLike){
this.detail.usefulCount++;
}else{
this.detail.usefulCount--;
}
if(!this.debounce){
this.debounce = Debounce(this.updateUseFul, 500);
}
this.debounce();
},
async updateUseFul(){
if(this.isLike === this.detail.isLike){
return false
}
const {error, result} = await ApiPutCommentUseful({
commentId : this.detail.id,
isLike : this.isLike
});
HandleApiError(error);
}
}
}
</script>
<style lang="scss">
page{
background: $color-grey1;
padding-bottom: 140rpx;
}
</style>
<style lang="scss" scoped>
.box{
background: $color-grey0;
padding: 40rpx;
}
.goods-info{
margin-top: 30rpx;
border: 1px solid #f8f8f8;
}
.reply-title{
height: 70rpx;
line-height: 70rpx;
margin-bottom:1rpx;
margin-top: 20rpx;
background: #fff;
padding: 0 40rpx;
}
.reply{
background: #fff;
padding: 0 40rpx;
overflow: hidden;
&--item{
border-bottom: 1px solid $color-grey1;
padding-top: 40rpx;
}
&--title{
display: flex;
justify-content: space-between;
text{
color: #999;
}
}
&--ctx{
margin: 26rpx 0;
line-height: 36rpx;
word-break: break-all;
}
}
.footer{
height: 124rpx;
position: fixed;
bottom: var(--window-bottom);
left: 0;
right: 0;
display: flex;
justify-content: space-around;
align-items: center;
background: #fff;
border-top: 1px solid #f8f8f8;
&--item{
display: flex;
align-items: center;
&__active{
color: $color-yellow3;
}
}
}
.reply-comment--bg{
position: fixed;
bottom: 0;
top: 0;
left: 0;
right: 0;
z-index: 1;
}
.reply-comment{
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
background: #fff;
height: 124rpx;
padding: 24rpx 40rpx;
border-top: 1px solid #f8f8f8;
&--box{
display: flex;
background: #F5F5F5;
border-radius: 38rpx;
}
&--input{
flex: 1;
padding:0 20rpx 0 40rpx;
height: 76rpx;
line-height: 76rpx;
}
}
</style>

@ -0,0 +1,203 @@
<!--
* @Author: ch
* @Date: 2022-06-21 16:51:03
* @LastEditors: ch
* @LastEditTime: 2022-06-30 22:40:31
* @Description: file content
-->
<template>
<view>
<view class="header">
<view class="tab">
<view class="tab--item" :class="{'tab--item__active' : tabActive == i.labelType}"
v-for="i in tabs" :key="i.labelType" @click="handleChangeTab(i)">
{{i.labelName}}({{i.commentCount}})
</view>
</view>
<view @click="sortChange">
<image v-if="timeSortType" class="header--sort" src="@/static/comment/sort_active.png"/>
<image v-else class="header--sort" src="@/static/comment/sort.png"/>
</view>
</view>
<view class="comment" v-for="item in list" :key="item.id" >
<view>
<BsCommentUserInfo :userData="item"/>
<BsCommentInfo :commentDetail="item"/>
<BsCommentFollowInfo v-if="item.followComment" :commentDetail="item"/>
<BsCommentMerchant v-if="item.merchantComment" :merchantComment="item.merchantComment"/>
</view>
<BsCommentThumbup :commentDetail="item"/>
</view>
<u-loadmore :status="loadingStatus" v-if="loadingStatus === 'loading'"/>
<view class="other" v-if="otherCount" @click="$Router.push(`/goodsCommentOtherList?id=${productId}`)">
已折叠{{otherCount}}条帮助不大的评价
<u-icon name="arrow-right" color="#999" size="15"></u-icon>
</view>
</view>
</template>
<script>
import BsCommentInfo from '../../../components/BsCommentInfo.vue'
import BsCommentUserInfo from '../../../components/BsCommentUserInfo.vue'
import {ApiGetCommentList, ApiGetCommentCount, ApiGetCommentTabCount} from '@/common/api/comment';
import {HandleApiError} from '@/common/utils'
import BsCommentFollowInfo from '../../../components/BsCommentFollowInfo.vue';
import BsCommentThumbup from '../../../components/BsCommentThumbup.vue';
import BsCommentMerchant from '../../../components/BsCommentMerchant.vue';
export default {
components: { BsCommentInfo, BsCommentUserInfo, BsCommentFollowInfo, BsCommentThumbup, BsCommentMerchant },
data (){
return {
list : [],
pageIndex : 1,
pageSize : 10,
productId : this.$Route.query.id,
loadingStatus : 'loading',
otherCount : 0,
timeSortType : false,
tabActive : -1,
tabs : [
{
labelName : '全部',
labelType : -1,
commentCount : 0
}
]
}
},
onLoad(){
this.getList();
this.getTabCount();
this.getCount()
},
onReachBottom(){
this.next();
},
methods:{
async getList(){
this.loadingStatus = 'loading';
const {error, result} = await ApiGetCommentList({
pageIndex : this.pageIndex,
length : this.pageSize,
productId : this.productId,
commentLabel : this.tabActive == -1 ? null : this.tabActive,
sortType : this.timeSortType ? 2 : 1,
isContent : true
});
if(!HandleApiError(error, 'getList')){
this.list = this.list.concat(result.records);
//
if(result.records.length == 0 && this.pageIndex < result.pages){
this.next();
return false;
}
//
// if(result.records.length < this.pageSize){
if(result.pages == this.pageIndex){
this.loadingStatus = 'nomore';
}
}
},
async getTabCount (){
const {error, result} = await ApiGetCommentTabCount({
productId : this.productId
});
if(!HandleApiError(error, 'getTabCount')){
this.tabs = this.tabs.concat(result.filter(i => i.commentCount > 0));
}
},
async getCount(){
const {error, result} = await ApiGetCommentCount({
productId : this.productId
});
if(!HandleApiError(error, 'getCount')){
this.otherCount = result.defaultCommentCount;
this.$set(this.tabs[0],'commentCount', result.allCommentCount)
}
},
calcDay(item, createTime){
const followTime = (new Date(item.createTime)).getTime();
const commentTime = (new Date(createTime)).getTime();
const day = Math.floor((followTime - commentTime) / (24 * 60 * 60 * 1000));
return day > 0 ? `${day}天后` : `当天`;
},
sortChange(){
this.timeSortType = !this.timeSortType;
this.list = [];
this.pageIndex = 1;
this.getList();
},
handleChangeTab(item){
this.tabActive = item.labelType;
this.pageIndex = 1;
this.list = [];
this.getList();
},
next(){
if(this.loadingStatus === 'nomore'){
return false
}
this.pageIndex++;
this.getList();
}
}
}
</script>
<style lang="scss">
page{
background: $color-grey1;
}
</style>
<style lang="scss" scoped>
.header{
background: $color-grey0;
height: 79rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 40rpx;
.tab{
display: flex;
justify-content: flex-start;
&--item{
font-size: 28rpx;
line-height: 75rpx;
margin-right: 64rpx;
&__active{
border-bottom: 4rpx solid $color-yellow3;
}
}
}
&--sort{
width: 30rpx;
height: 30rpx;
}
}
.comment{
margin-top:20rpx ;
background: $color-grey0;
padding: 40rpx;
}
.follow{
margin-top: 40rpx;
&--title{
color: $color-yellow3;
font-size: 28rpx;
}
&--ctx{
margin-top: 20rpx;
font-size: 30rpx;
line-height: 46rpx;
}
}
.other{
display: flex;
align-items: center;
color: #999;
width: 360rpx;
margin: 20rpx auto;
height: 100rpx;
}
</style>

@ -0,0 +1,109 @@
<!--
* @Author: ch
* @Date: 2022-06-21 16:51:03
* @LastEditors: ch
* @LastEditTime: 2022-06-28 20:44:13
* @Description: file content
-->
<template>
<view>
<view class="comment" v-for="item in list" :key="item.id">
<BsCommentUserInfo :userData="item"/>
<BsCommentInfo :commentDetail="item"/>
<BsCommentThumbup :commentDetail="item"/>
</view>
<u-loadmore :status="loadingStatus" v-if="loadingStatus === 'loading'"/>
</view>
</template>
<script>
import BsCommentInfo from '../../../components/BsCommentInfo.vue'
import BsCommentUserInfo from '../../../components/BsCommentUserInfo.vue'
import {ApiGetCommentList, ApiGetCommentCount, ApiGetCommentTabCount} from '@/common/api/comment';
import {HandleApiError} from '@/common/utils'
import BsCommentThumbup from '../../../components/BsCommentThumbup.vue';
export default {
components: { BsCommentInfo, BsCommentUserInfo, BsCommentThumbup },
data (){
return {
list : [],
pageIndex : 1,
pageSize : 10,
productId : this.$Route.query.id,
loadingStatus : ''
}
},
onLoad(){
this.getList();
},
onReachBottom(){
this.next();
},
methods:{
async getList(){
if(this.loadingStatus === 'loading'){
return false
}
this.loadingStatus = 'loading';
const {error, result} = await ApiGetCommentList({
pageIndex : 1,
length : this.pageSize,
productId : this.productId,
sortType : 1,
isContent : false
});
if(!HandleApiError(error, 'getList')){
this.list = result.records;
//
if(result.records.length < this.pageSize){
this.loadingStatus = 'nomore';
}
}
},
next(){
if(this.loadingStatus === 'nomore'){
return false
}
this.pageIndex++;
this.getList();
}
}
}
</script>
<style lang="scss">
page{
background: $color-grey1;
}
</style>
<style lang="scss" scoped>
.header{
background: $color-grey0;
height: 79rpx;
display: flex;
justify-content: space-between;
padding: 0 40rpx;
.tab{
display: flex;
justify-content: flex-start;
&--item{
font-size: 28rpx;
line-height: 75rpx;
margin-right: 64rpx;
&__active{
border-bottom: 4rpx solid $color-yellow3;
}
}
}
}
.comment{
margin-top:20rpx ;
background: $color-grey0;
padding: 40rpx;
}
.other{
text-align: center;
color: #999;
margin: 40rpx 0 20rpx;
}
</style>

@ -0,0 +1,187 @@
<!--
* @Author: ch
* @Date: 2022-06-22 15:15:22
* @LastEditors: ch
* @LastEditTime: 2022-07-01 17:14:16
* @Description: file content
-->
<template>
<view class="preview">
<view class="preview--top">
<image class="preview--back" src="@/static/common/back_white.png" @click="$Router.back()"></image>
<view class="preview--title">{{current + 1}}/{{imgs.length}}</view>
</view>
<u-swiper height="calc(100vh - 420rpx)" :list="imgs" :current="current"
@change="handleChange" :autoplay="false" imgMode="aspectFit" radius="0"/>
<view class="preview--footer">
<view class="preview--user">
<image class="preview--avatar" :src="data.userAvatar"></image>
<view>
<view>{{data.userName}}</view>
<view v-if="data.skuName">{{data.skuName}}</view>
</view>
</view>
<view>
<view class="preview--rate">
<u-rate count="5" size="30rpx" :value="data.commentScore" activeColor="#FFA35B" readonly inactiveColor="#DDD"></u-rate>
<text class="preview--time">{{FormatDate(data.createTime, 'yyyy-mm-dd hh:ii')}}</text>
</view>
<view class="preview--ctx">{{ data.commentContent }}</view>
</view>
<view class="thumb">
<view class="thumb--item" @click="handleUseful">
<u-icon color="#fff" :name="isLike ? 'thumb-up-fill' : 'thumb-up'"></u-icon>
<text>{{data.usefulCount || 0}}</text>
</view>
<view class="thumb--item" @click="$Router.replace(`/goodsCommentDetail?id=${data.id}`)">
<u-icon color="#fff" name="chat"></u-icon>
<text>{{data.replyCount}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
import BsCommentUserInfo from '@/components/BsCommentUserInfo.vue';
import BsCommentThumbup from '../../../components/BsCommentThumbup.vue';
import {ApiPutCommentUseful} from '@/common/api/comment'
import { Debounce,FormatDate, HandleApiError} from '@/common/utils'
export default {
components: { BsCommentUserInfo,BsCommentThumbup },
data (){
return {
data : this.$store.state.comment_preview,
current : Number(this.$Route.query.idx),
isLike : false
}
},
computed : {
imgs(){
const arr = this.data.pictureUrl || [];
return arr.split(',')
}
},
onShow(){
if(!this.data.id){
this.$Router.back();
};
this.isLike = this.data.isLike
},
methods:{
FormatDate,
handleChange(idx){
this.current = idx.current
},
handleUseful(){
this.isLike = !this.isLike
if(this.isLike){
this.data.usefulCount++;
}else{
this.data.usefulCount--;
}
if(!this.debounce){
this.debounce = Debounce(this.updateUseFul, 500);
}
this.debounce();
},
async updateUseFul(){
if(this.isLike === this.data.isLike){
return false
}
const {error, result} = await ApiPutCommentUseful({
commentId : this.data.id,
isLike : this.isLike
});
HandleApiError(error);
}
}
}
</script>
<style lang="scss">
page{
background: #000;
}
</style>
<style lang="scss" scoped>
.preview{
&--top{
height: 44px;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
position: -webkit-sticky;
position: sticky;
top: var(--window-top);
z-index: 999;
}
&--back{
width: 14rpx;
height: 28rpx;
}
&--title{
flex: 1;
text-align: center;
color: #fff;
font-size: 32rpx;
}
&--footer{
padding: 40rpx;
}
&--user{
display: flex;
view{
color: #fff;
}
}
&--avatar{
width: 70rpx;
height: 70rpx;
background: #ccc;
margin-right: 20rpx;
border-radius: 50%;
}
&--rate{
display: flex;
align-items: center;
justify-content: space-between;
margin: 20rpx 0 ;
}
&--time{
color: #fff;
font-size: 24rpx;
}
&--ctx{
color: #fff;
@include ellipses(2);
line-height: 32rpx;
height: 60rpx;
}
}
.thumb{
display: flex;
justify-content: flex-end;
margin-top: 20rpx;
&--item{
display: flex;
align-items: center;
margin-left: 50rpx;
text{
font-size: 24rpx;
margin-left: 10rpx;
color: #fff;
}
}
&--icon{
font-size: 24rpx;
margin-left: 10rpx;
color: #fff;
}
}
</style>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-23 17:27:21
* @LastEditors: ch
* @LastEditTime: 2022-06-02 14:39:30
* @LastEditTime: 2022-07-04 16:26:33
* @Description: file content
-->
<template>
@ -22,14 +22,16 @@
</view>
<view class="goods-info--title">{{goods.name}}</view>
</view>
<view class="select">
<view class="box">
<Service></Service>
<u-cell v-if="stock > 0" label="选择" :value="curSku.name || '请选择规格'" :border="false" isLink @click="onShowSkuPopup(1)"></u-cell>
<SkuPopup v-model="curSku" :visible.sync="showSkuPopup" :mode="skuMode"
:goodsInfo="goods" :skuInfo="skuInfoData" :activityStatus="activityStatus">
</SkuPopup>
</view>
<view class="goods-desc">
<Comment v-if="commentCount" :commentList="commentList" :count="commentCount" :productId="goodsId"/>
<view class="box goods-desc">
<mp-html :content="goods.detail"/>
</view>
<view class="footer--not-stock" v-if="stock === 0">~</view>
@ -47,20 +49,23 @@
</template>
<script>
import {FormatDate} from '@/common/utils';
import {FormatDate, HandleApiError} from '@/common/utils';
import {ApiGetGoodsDetail, ApiGetGoodsSkus} from '@/common/api/goods';
import {ApiGetCommentList, ApiGetCommentCount} from '@/common/api/comment';
import SlideImage from './modules/SlideImage.vue';
import Service from './modules/Service.vue';
import SkuPopup from './modules/SkuPopup.vue';
import SeckillPrice from './modules/SeckillPrice.vue';
import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html';
import UiButton from '../../../components/UiButton.vue';
import Comment from './modules/Comment.vue';
export default {
components: { SlideImage, mpHtml, Service, SkuPopup, UiButton, SeckillPrice},
components: { SlideImage, mpHtml, Service, SkuPopup, UiButton, SeckillPrice, Comment},
data(){
return {
// 1
stock : 1,
goodsId : this.$Route.query.id,
goods : {
pictureList : []
},
@ -73,7 +78,10 @@ export default {
sku : '',
num : 1
},
productActivityVO : {}
productActivityVO : {},
commentList : [],
commentCount : 0
}
},
computed:{
@ -96,8 +104,11 @@ export default {
async getGoodsDetail(){
const {query} = this.$Route;
const {error, result} = await ApiGetGoodsDetail({id : query.id});
if(error){
uni.$u.toast(error.message);
if(HandleApiError(error, 'getGoodsDetail')){
return false;
}
if(!result.isEnable){
this.$Router.replace('/enable')
return false;
}
this.goods = {...result,
@ -119,15 +130,13 @@ export default {
originalPrice:result.startingPrice
};
this.getGoodsSkus();
this.getComment();
this.getCommentCount();
},
async getGoodsSkus(){
const {query} = this.$Route;
const {error, result} = await ApiGetGoodsSkus({productId : query.id});
if(error) {
uni.$u.toast(error.message);
return false;
}
const {error, result} = await ApiGetGoodsSkus({productId : this.goodsId});
if(!HandleApiError(error, 'getGoodsSkus')){
//
this.stock = 0;
this.skuInfoData = result.map(i => {
@ -135,6 +144,28 @@ export default {
// i.attributeSymbolList = i.attributeSymbolList.split(',')
return i;
});
}
},
async getCommentCount (){
const {error, result} = await ApiGetCommentCount({
productId : this.goods.id
});
if(!HandleApiError(error, 'getCommentCount')){
this.commentCount = result.allCommentCount;
}
},
async getComment(){
const {error, result} = await ApiGetCommentList({
pageIndex : 1,
length : 2,
productId : this.goods.id,
isContent : true,
sortType : 1
});
if(!HandleApiError(error, 'getComment')){
this.commentList = result.records;
}
},
/**
* 显示/隐藏SKU弹窗
@ -206,15 +237,12 @@ page {
}
.select{
.box{
margin: 20rpx 30rpx;
background: $color-grey0;
border-radius: 16rpx;
}
.goods-desc{
margin: 20rpx 30rpx;
background: $color-grey0;
border-radius: 16rpx;
padding: 20rpx;
}
.footer{

@ -0,0 +1,90 @@
<!--
* @Author: ch
* @Date: 2022-06-21 16:23:27
* @LastEditors: ch
* @LastEditTime: 2022-06-28 11:31:02
* @Description: file content
-->
<template>
<UiWhiteBox @click="handleJumpCmment">
<view class="comment-title">
<text class="comment-title--left">用户评价({{count}})</text>
<text class="comment-title--right">查看全部</text>
</view>
<view class="comment-ctx" v-if="commentList && commentList.length">
<view v-for="item in commentList" :key="item.id">
<BsCommentUserInfo :userData="item"/>
<BsCommentInfo class="comment-ctx--item" :commentDetail="item" :imgPreview="false"/>
</view>
</view>
</UiWhiteBox>
</template>
<script>
import BsCommentInfo from '../../../../components/BsCommentInfo.vue'
import BsCommentUserInfo from '../../../../components/BsCommentUserInfo.vue'
import UiCell from '../../../../components/UiCell.vue'
import UiWhiteBox from '../../../../components/UiWhiteBox.vue'
export default {
components: { BsCommentInfo, UiCell, UiWhiteBox, BsCommentUserInfo },
props : {
count : {
type : Number,
default : 0
},
productId : {
type : Number | String,
default : 0
},
commentList : {
type : Array,
default : () => ([])
}
},
data(){
return {
}
},
methods:{
handleJumpCmment(){
let url = '/goodsCommentOtherList'
if(this.commentList.length){
url = '/goodsCommentList'
}
this.$Router.push({
path : url,
query : {
id : this.productId
}
})
}
}
}
</script>
<style lang="scss" scoped>
.comment-title{
display: flex;
justify-content: space-between;
padding:30rpx;
align-items: center;
&--left{
font-size: 30rpx;
font-weight: bold;
}
&--right{
font-size: 24rpx;
color: #999;
background: url('@/static/common/arrow.png') no-repeat right center;
background-size: 10rpx;
padding-right: 32rpx;
}
}
.comment-ctx{
padding: 0 30rpx;
&--item{
padding: 20rpx 0;
}
}
</style>

@ -0,0 +1,83 @@
<!--
* @Author: ch
* @Date: 2022-03-28 17:16:44
* @LastEditors: ch
* @LastEditTime: 2022-07-13 20:05:42
* @Description: file content
-->
<template>
<view>
<UiWhiteBox class="main">
<image class="icon" src="@/static/goods/cart.png"/>
<view class="title">商品已下架</view>
<view class="btns">
<UiButton class="btn" @click="$Router.pushTab('/')"></UiButton>
</view>
</UiWhiteBox>
<view class="recommend-title">为您推荐</view>
<BsChoiceGoods/>
</view>
</template>
<script>
import UiButton from '@/components/UiButton.vue'
import BsChoiceGoods from '../../components/BsChoiceGoods.vue'
import UiWhiteBox from '../../components/UiWhiteBox.vue'
export default {
components: { UiButton, BsChoiceGoods, UiWhiteBox }
}
</script>
<style lang="scss">
page {
background: $color-grey1;
text-align: center;
}
</style>
<style lang="scss" scoped>
.main{
padding-bottom: 40rpx;
}
.icon{
width: 400rpx;
height: 256rpx;
margin: 169rpx auto 42rpx;
}
.title{
font-size: $font-size-lg;
line-height: 44rpx;
color: $color-grey6;
}
.desc{
font-size: $font-size-sm;
line-height: 34rpx;
color: $color-grey4;
}
.btns{
margin: 74rpx 105rpx 0;
display: flex;
justify-content: space-between;
}
.recommend-title{
font-size: $font-size-lg;
text-align: center;
margin: 51rpx auto 30rpx auto;
display: flex;
align-items: center;
justify-content: space-between;
width: 500rpx;
&::after,&::before{
display: inline-block;
content: '';
width: 160rpx;
height: 2rpx;
background: linear-gradient(90deg, $color-grey3 0%, rgba(204, 204, 204, 0) 100%);
}
&::before{
background: linear-gradient(270deg, $color-grey3 0%, rgba(204, 204, 204, 0) 100%);
}
}
</style>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2019-08-22 19:41:20
* @LastEditors: ch
* @LastEditTime: 2022-06-13 14:25:25
* @LastEditTime: 2022-06-22 19:39:05
* @Description: file content
-->
<template>
@ -108,7 +108,7 @@ export default {
const {error, result} = await ApiGetAdList({
location : AD_LOCATION.HOME_BANNER
});
this.bannerList = result;
this.bannerList = result || [];
},
async getSeckillList(){
const {error, result} = await ApiGetHomeSeckill();

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-23 10:31:12
* @LastEditors: ch
* @LastEditTime: 2022-05-31 17:19:26
* @LastEditTime: 2022-06-22 19:38:00
* @Description: file content
-->
<template>
@ -40,7 +40,7 @@ export default {
props:{
data : {
type : Array,
default : []
default : ()=>([])
}
},
methods:{

@ -0,0 +1,155 @@
<!--
* @Author: ch
* @Date: 2022-06-20 14:55:54
* @LastEditors: ch
* @LastEditTime: 2022-06-30 23:43:00
* @Description: file content
-->
<template>
<view>
<view class="box" v-for="(item, idx) in list" :key="item.productId">
<BsCommentGoodsInfo :goods="item" />
<BsCommentSubmit v-if="!item.id" :commentDetail="item" :type="COMMENT.TYPE.COMMENT"
@submit="submitComment($event,idx)" @editChang="editChange($event, idx)"/>
<!-- 已评价过显示详情 -->
<template v-else>
<BsCommentInfo :commentDetail="item" v-if="!isFollow"/>
<SubmitFollowComment :commentDetail="item"
@submit="submitFollowComment($event, idx)"
@editChange="editChange($event, idx)" :isFollow="isFollow"/>
<BsCommentMerchant v-if="item.merchantComment && !isFollow" :merchantComment="item.merchantComment"/>
<BsCommentThumbup :commentDetail="item" v-if="!isFollow"/>
</template>
</view>
</view>
</template>
<script>
import { ApiGetOrderCommentDetail,ApiGetCommentDetail } from "@/common/api/comment";
import UiWhiteBox from "@/components/UiWhiteBox.vue";
import UiButton from "@/components/UiButton.vue";
import BsCommentSubmit from "@/components/BsCommentSubmit.vue";
import BsCommentGoodsInfo from '@/components/BsCommentGoodsInfo.vue';
import BsCommentInfo from '@/components/BsCommentInfo.vue';
import BsCommentMerchant from '@/components/BsCommentMerchant.vue';
import BsCommentThumbup from '@/components/BsCommentThumbup.vue';
import SubmitFollowComment from './modules/SubmitFollowComment.vue';
import COMMENT from '@/common/dicts/comment';
const SOURCE = ['goodsComment','orderList','orderDetail','comment']
export default {
components: {
UiWhiteBox,
UiButton,
BsCommentSubmit,
BsCommentGoodsInfo,
BsCommentInfo,
BsCommentMerchant,
BsCommentThumbup,
SubmitFollowComment,
},
data() {
const query = this.$Route.query;
return {
COMMENT,
list: [],
isFollow : query.follow == 'true' ? true : false,
orderId: query.orderId,
commentId : query.commentId
};
},
onLoad() {
if(this.orderId){
this.getOrderCommentDetail();
}else if(this.commentId){
this.getCommentDetail()
}
uni.setNavigationBarTitle({
title : this.isFollow ? '发表追评' : '发表评价'
});
},
beforeRouteLeave(to, from, next) {
if(this.list.findIndex(i => i.isEdit) > -1 &&
!(to.aliasPath == '/goodsCommentPreview' || to.fullPath == '/preview-image')){
uni.showModal({
content : '你正在进行商品评价,退出后评价的内容将不保存!',
cancelColor : '#999',
confirmColor : '#3A83FB',
success: async ({confirm}) => {
if(confirm){
next()
}
}
});
}else{
next();
}
},
methods: {
async getOrderCommentDetail() {
const { error, result } = await ApiGetOrderCommentDetail({
orderId: this.orderId,
});
if (error) {
uni.$u.toast(error.message);
return false;
}
this.list = result;
},
/**
* 按评论查询追评时用
*/
async getCommentDetail(){
const {error, result} = await ApiGetCommentDetail({
commentId : this.commentId
});
if (error) {
uni.$u.toast(error.message);
return false;
}
this.list = [result];
},
getFollowType(item){
let type= 'info'
//
if(this.isFollow){
type = 'form'
}
return type;
},
submitComment(result, idx){
this.$set(this.list, idx, {...this.list[idx],...result});
if(this.list.findIndex(i => !i.id) > -1){
uni.$u.toast('评论成功~');
}else{
this.$Router.replace('/commentSuccess');
}
},
editChange(isEdit, idx){
this.$set(this.list[idx], 'isEdit', isEdit);
},
submitFollowComment(result, idx){
this.$set(this.list[idx],'followComment',{
...this.list[idx].followComment,
...result
});
}
},
};
</script>
<style lang="scss">
page {
background: $color-grey1;
}
</style>
<style lang="scss" scoped>
.box{
background: $color-grey0;
margin-bottom: 20rpx;
padding:40rpx;
}
</style>

@ -0,0 +1,74 @@
<!--
* @Author: ch
* @Date: 2022-06-20 16:36:41
* @LastEditors: ch
* @LastEditTime: 2022-06-29 20:32:02
* @Description: file content
-->
<template>
<view class="follow">
<BsCommentFollowInfo v-if="commentDetail.followComment"
:commentDetail="commentDetail" />
<template v-else>
<UiButton type="primaryLine" @click="showInput = true" v-if="!showInput"></UiButton>
<template v-else>
<BsCommentSubmit :commentDetail="commentDetail" :type="COMMENT.TYPE.FOLLOW_COMMENT"
@submit="handleSubmit" @editChang="handleEditChange"/>
</template>
</template>
</view>
</template>
<script>
import UiButton from '@/components/UiButton.vue'
import BsCommentFollowInfo from '@/components/BsCommentFollowInfo.vue';
import BsCommentSubmit from '@/components/BsCommentSubmit.vue';
import COMMENT from '@/common/dicts/comment';
export default {
components: { UiButton, BsCommentFollowInfo, BsCommentSubmit },
props : {
commentDetail : {
type : Object,
default : () => ({})
},
isFollow : {
type : Boolean,
default : false
}
},
data(){
return {
showInput : this.isFollow,
COMMENT,
}
},
computed:{
},
methods:{
async handleSubmit(data){
this.$emit('submit',data);
},
handleEditChange(data){
this.$emit('editChange',data);
}
}
}
</script>
<style lang="scss" scoped>
.follow{
margin-top: 40rpx;
&--title{
color: $color-yellow3;
font-size: 28rpx;
}
&--ctx{
margin-top: 20rpx;
font-size: 30rpx;
line-height: 46rpx;
}
}
.footer{
text-align: right;
}
</style>

@ -0,0 +1,137 @@
<!--
* @Author: ch
* @Date: 2022-06-21 15:32:28
* @LastEditors: ch
* @LastEditTime: 2022-06-30 17:23:32
* @Description: file content
-->
<template>
<view class="main">
<view class="ctx">
<image class="icon" src="@/static/order/paySuccess.png"/>
<view class="title">评价成功</view>
<view class="btns">
<UiButton class="btn" @click="$Router.back()"></UiButton>
</view>
</view>
<view class="await" v-if="goodsList.length">
<view class="await--title">这些宝贝还在等你的评价哦~</view>
<BsCommentGoodsInfo class="await--goods" :goods="item" v-for="item in goodsList" :key="item.productId">
<UiButton slot="btns" size="small" type="primaryLine"
@click="$Router.push(`/comment?commentId=${item.orderId}`)">
{{item.commentStatus == 1 ? '评价' : '追评'}}
</UiButton>
</BsCommentGoodsInfo>
</view>
<view class="recommend-title">为您推荐</view>
<BsChoiceGoods></BsChoiceGoods>
</view>
</template>
<script>
import UiButton from '@/components/UiButton.vue'
import BsChoiceGoods from '../../../components/BsChoiceGoods.vue';
import {ApiGetCommentOrderDetailList} from '@/common/api/order';
import {HandleApiError} from '@/common/utils'
import BsCommentGoodsInfo from '../../../components/BsCommentGoodsInfo.vue';
export default {
components: { UiButton, BsChoiceGoods, BsCommentGoodsInfo },
data(){
return {
goodsList : []
}
},
onLoad(){
this.getAwaitGoodsList();
},
methods:{
async getAwaitGoodsList (){
const {error, result} = await ApiGetCommentOrderDetailList({
length:2,
pageIndex : 1
});
if(!HandleApiError(error, 'getAwaitGoodsList')){
this.goodsList = result.records.map(item => {
return {
productPicture : item.productImageUrl,
productName : item.productName,
skuName : item.skuDescribe,
commentStatus : item.commentStatus,
orderId : item.orderId
}
});
}
}
}
}
</script>
<style lang="scss">
page{
background: $color-grey1;
}
</style>
<style lang="scss" scoped>
.main {
text-align: center;
}
.ctx{
background: $color-grey0;
padding-bottom: 40rpx;
.icon{
width: 400rpx;
height: 256rpx;
margin: 169rpx auto 42rpx;
}
.title{
font-size: $font-size-lg;
line-height: 44rpx;
color: $color-grey6;
}
.desc{
font-size: $font-size-sm;
line-height: 34rpx;
color: $color-grey4;
}
.btns{
margin: 74rpx 105rpx 0;
display: flex;
justify-content: space-between;
}
}
.await{
margin-top: 20rpx;
background: $color-grey0;
&--title{
text-align: left;
padding: 40rpx;
border-bottom: 1px solid #f8f8f8;
}
&--goods{
padding: 20rpx 40rpx;
text-align: left;
}
}
.recommend-title{
font-size: $font-size-lg;
text-align: center;
margin: 51rpx auto 30rpx auto;
display: flex;
align-items: center;
justify-content: space-between;
width: 500rpx;
&::after,&::before{
display: inline-block;
content: '';
width: 160rpx;
height: 2rpx;
background: linear-gradient(90deg, $color-grey3 0%, rgba(204, 204, 204, 0) 100%);
}
&::before{
background: linear-gradient(270deg, $color-grey3 0%, rgba(204, 204, 204, 0) 100%);
}
}
</style>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-31 14:26:09
* @LastEditors: ch
* @LastEditTime: 2022-05-30 17:46:53
* @LastEditTime: 2022-06-22 11:22:41
* @Description: file content
-->
<template>
@ -29,7 +29,7 @@
</template>
</UiGoodsInfo>
</UiWhiteBox>
<LogisitcsInfo v-if="orderInfo.orderType !== ORDER_TYPE.VIRTUAL"
<LogisitcsInfo v-if="orderInfo.orderType !== ORDER.TYPE.VIRTUAL"
:logisitcsInfo="orderInfo.logistics" :orderId="orderInfo.orderId"/>
<OrderInfo :orderInfo="orderInfo" />
<Operation :orderInfo="orderInfo" v-if="orderInfo.orderStatus !== 3"></Operation>
@ -44,12 +44,12 @@ import StatusTips from './modules/StatusTips.vue';
import OrderInfo from './modules/OrderInfo.vue';
import LogisitcsInfo from './modules/LogisitcsInfo.vue';
import Operation from './modules/Operation.vue';
import {ORDER_TYPE} from '@/common/dicts/order'
import ORDER from '@/common/dicts/order'
export default {
components: { UiGoodsInfo, UiWhiteBox, UiButton, StatusTips, OrderInfo, LogisitcsInfo, Operation },
data(){
return {
ORDER_TYPE,
ORDER,
orderInfo : {
products:[],
logistics:{}
@ -79,7 +79,7 @@ export default {
this.getOrderInfo();
},
handleSaleAfter(item){
if(this.orderInfo.orderType === ORDER_TYPE.VIRTUAL){
if(this.orderInfo.orderType === ORDER.TYPE.VIRTUAL){
uni.$u.toast('虚拟商品的订单不满足退款要求,不支持申请售后,如有问题请联系客服。');
}else{
this.$Router.push(`/saleAfterSelect?id=${item.orderProductId}`)

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-04-15 17:46:10
* @LastEditors: ch
* @LastEditTime: 2022-05-27 11:13:24
* @LastEditTime: 2022-07-13 18:20:38
* @Description: file content
-->
<template>
@ -13,10 +13,17 @@
<UiButton class="footer--btn" v-if="orderInfo.orderStatus === 2" @click="service"></UiButton>
<!-- 已发货可以确认收货 -->
<UiButton class="footer--btn" v-if="orderInfo.orderStatus === 4" type="gradual" @click="receive"></UiButton>
<UiButton class="footer--btn" type="primaryLine" v-if="orderInfo.orderStatus === ORDER.STATUS.FINISH_TAKE_GOODS"
@click="$Router.push(`/comment?orderId=${orderInfo.orderId}`)">去评价</UiButton>
<UiButton size="min" type="primaryLine" v-if="orderInfo.orderStatus === ORDER.STATUS.FINISH"
@click="$Router.push(`/comment?orderId=${orderInfo.orderId}&follow=true`)">去追评</UiButton>
<!-- 待支付可以取消支付订单 -->
<template v-if="orderInfo.orderStatus === 1">
<UiButton class="footer--btn" @click="cancelShow = true">取消订单</UiButton>
<UiButton class="footer--btn" type="gradual" @click="payShow = true">去支付</UiButton>
<UiButton class="footer--btn" type="gradual" @click="handlePay"></UiButton>
</template>
<u-popup class="cancel" :show="cancelShow" @close="closeCancel" round="16rpx" closeable>
<view class="cancel--title">取消订单原因</view>
@ -42,14 +49,17 @@
<UiButton type="gradual" :disabed="cancelValue == 0" @click="cancelOrder"></UiButton>
</view>
</u-popup>
<BsPay class="modal" :show.sync="payShow" :order="orderInfo"></BsPay>
<!-- <BsPay class="modal" :show.sync="payShow" :order="orderInfo"></BsPay> -->
</view>
</template>
<script>
import UiButton from '@/components/UiButton.vue'
import UiCell from '@/components/UiCell.vue'
import {ApiPutCancelOrder,ApiPutOrderReceive} from '@/common/api/order'
import BsPay from '../../../../components/BsPay.vue'
import {ApiPutCancelOrder,ApiPutOrderReceive} from '@/common/api/order';
import {ApiPostCashierPrepay} from '@/common/api/pay';
import BsPay from '../../../../components/BsPay.vue';
import ORDER from '@/common/dicts/order';
const ENV = process.env;
export default {
components: { UiButton, UiCell, BsPay },
props : {
@ -60,11 +70,10 @@ export default {
},
data(){
return {
ORDER,
//
cancelShow : false,
cancelValue : 0,
//
payShow : false
}
},
methods : {
@ -77,16 +86,16 @@ export default {
this.cancelValue = val;
},
async cancelOrder(){
const ooderId = this.$Route.query.id;
const orderId = this.orderInfo.orderId;
const {error, result} = await ApiPutCancelOrder({
cancelReasonType : this.cancelValue,
orderId : ooderId
orderId : orderId
});
if(error){
uni.$u.toast(error.message);
return false;
}
this.$Router.replace(`/orderDetail?id=${ooderId}`);
this.$Router.replace(`/orderDetail?id=${orderId}`);
//
},
/**
@ -100,39 +109,49 @@ export default {
success: async ({confirm}) => {
if(confirm){
const {error} = await ApiPutOrderReceive({
orderId : this.$Route.query.id
orderId : this.orderInfo.orderId
});
if(error){
uni.$toast(error.message);
return false;
}
this.$Router.push('/orderSuccess');
this.$Router.push(`/orderSuccess?orderId=${this.orderInfo.orderId}`);
}
}
})
// this.$msb.confirm({
// content : '',
// confirm : async ()=>{
// const {error} = await ApiPutOrderReceive({
// orderId : this.$Route.query.id
// });
// if(error){
// uni.$toast(error.message);
// return false;
// }
// this.$Router.push('/orderSuccess');
// }
// })
},
service(){
// uni.$u.toast('')
this.$Router.push({
path : '/messageChat',
query : {
orderId : this.orderInfo.orderId
}
})
},
async handlePay(){
let payType = 'wxjsapi'
if(!this.$store.state.openId){
payType = 'h5'
}
const {error, result} = await ApiPostCashierPrepay({
orderId:this.orderInfo.orderId,
returnUrl : `${ENV.VUE_APP_STATIC_URL}/payResult?orderId=${this.orderInfo.orderId}&payType=${payType}`
});
if(error){
uni.$u.toast(error.message);
return false;
}
// #ifdef H5
window.location.href = result.wapCashierUrl;
// #endif
// #ifndef H5
this.$Router.push(`/webView?url=${encodeURIComponent(result.wapCashierUrl)}`);
// #endif
}
}
}

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-31 17:53:43
* @LastEditors: ch
* @LastEditTime: 2022-05-05 20:43:19
* @LastEditTime: 2022-06-28 16:24:52
* @Description: file content
-->
<template>
@ -35,6 +35,8 @@ export default {
'5' : {name:'已收货', icon: require('@/static/order/fh.png')},
//
'6' : {name:'交易成功', icon: require('@/static/order/cg.png')},
//
'7' : {name:'交易成功', icon: require('@/static/order/cg.png')},
},
ctxCon : {},
startSecondNum : 0,

@ -2,13 +2,13 @@
* @Author: ch
* @Date: 2022-03-22 10:58:24
* @LastEditors: ch
* @LastEditTime: 2022-05-24 09:57:16
* @LastEditTime: 2022-07-13 18:21:13
* @Description: file content
-->
<template>
<view>
<view class="tabs">
<text :class="item.key === currentTabKey && 'tabs__active'"
<text :class="item.key == currentTabKey && 'tabs__active'"
v-for="item in tabListData" :key="item.key" @click="changeTab(item.key)">
{{item.name}}</text>
</view>
@ -19,7 +19,7 @@
<view class="orders" v-for="item in orderListData" :key="item.orderId">
<view class="orders--title">
<text class="orders--name">官方自营</text>
<text class="orders--status" :class="[1,3].includes(item.orderStatus) && 'orders--status__warn'">{{item.orderStatusDesc}}</text>
<text class="orders--status" :class="[ORDER.STATUS.AWAIT_PAY,ORDER.STATUS.FINISH_PAY].includes(item.orderStatus) && 'orders--status__warn'">{{item.orderStatusDesc}}</text>
</view>
<UiGoodsInfoMax v-for="item in item.products" :key="item.orderProductId"
:data="item" @click="$Router.push(`/orderDetail?id=${item.orderId}`)" />
@ -32,39 +32,49 @@
<view class="orders--footer">
<UiButton size="min" type="gradual"
v-if="item.orderStatus === 1" @click="pay(item)">去支付</UiButton>
<UiButton size="min" v-if="[2,3].includes(item.orderStatus)"
v-if="item.orderStatus === ORDER.STATUS.AWAIT_PAY" @click="handlePay(item)">去支付</UiButton>
<UiButton size="min" v-if="[ORDER.STATUS.CLOSE,ORDER.STATUS.AWAIT_PAY].includes(item.orderStatus)"
@click="$Router.push(`/orderDetail?id=${item.orderId}`)">查看详情</UiButton>
<UiButton size="min" v-if="item.orderStatus >= 4"
<UiButton size="min" v-if="item.orderStatus >= ORDER.STATUS.FINISH_SEND_GOODS"
@click="$Router.push(`/logisitcsInfo?orderId=${item.orderId}`)">查看物流</UiButton>
<UiButton size="min" type="gradual" v-if="item.orderStatus === 4" @click="receive(item)"></UiButton>
<UiButton size="min" type="primaryLine"
v-if="item.orderStatus === ORDER.STATUS.FINISH_TAKE_GOODS"
@click="$Router.push(`/comment?orderId=${item.orderId}`)">去评价</UiButton>
<UiButton size="min" type="primaryLine"
v-if="item.orderStatus === ORDER.STATUS.FINISH"
@click="$Router.push(`/comment?orderId=${item.orderId}&follow=true`)">去追评</UiButton>
<UiButton size="min" type="gradual" v-if="item.orderStatus === ORDER.STATUS.FINISH_SEND_GOODS" @click="receive(item)"></UiButton>
</view>
</view>
<u-loadmore :status="loadingStatus" v-if="loadingStatus === 'loading'"/>
<u-loadmore :status="loadingStatus" v-if="loadingStatus !== 'nomore'"/>
<BsPay :show.sync="payShow" :order="payOrder"></BsPay>
<!-- <BsPay :show.sync="payShow" :order="payOrder"></BsPay> -->
</view>
</template>
<script>
import BsEmpty from '@/components/BsEmpty.vue';
import UiButton from '@/components/UiButton.vue';
import { ApiGetOrderList, ApiPutOrderReceive } from '@/common/api/order';
import {ApiPostCashierPrepay} from '@/common/api/pay';
import BsPay from '../../components/BsPay.vue';
import UiGoodsInfo from '../../components/UiGoodsInfo.vue';
import UiGoodsInfoMax from '../../components/UiGoodsInfoMax.vue';
import UiMoney from '../../components/UiMoney.vue';
import ORDER from '@/common/dicts/order';
const ENV = process.env;
export default {
components: { BsEmpty, UiButton, BsPay, UiGoodsInfo, UiGoodsInfoMax, UiMoney },
data () {
return {
ORDER,
tabListData : [
{key : '-1', name : '全部'},
{key : '1', name : '待付款'},
{key : '3', name : '待发货'},
{key : '4', name : '待收货'}
// {key : '6', name : ''}
{key : ORDER.STATUS.AWAIT_PAY, name : '待付款'},
{key : ORDER.STATUS.FINISH_PAY, name : '待发货'},
{key : ORDER.STATUS.FINISH_SEND_GOODS, name : '待收货'},
{key : ORDER.STATUS.FINISH_TAKE_GOODS, name : '待评价'}
],
currentTabKey : this.$Route.query.tab || '-1',
orderListData : [],
@ -72,12 +82,11 @@ export default {
pageIndex : 1,
pageSize : 10,
payShow : false,
payOrder : null
}
},
onLoad(){
this.getOrderList()
this.getOrderList();
},
onReachBottom(){
this.next();
@ -87,6 +96,9 @@ export default {
* 切换tab 拉取当前分类第一页数据
*/
changeTab(key){
if(this.loadingStatus == 'loading' || this.currentTabKey == key){
return false;
}
this.currentTabKey = key;
this.pageIndex = 1;
this.orderListData = [];
@ -103,6 +115,7 @@ export default {
uni.$u.toast(error.message);
return false;
}
this.loadingStatus = 'finish';
//
if(result.records.length < this.pageSize){
this.loadingStatus = 'nomore';
@ -122,9 +135,25 @@ export default {
/**
* 立即支付
*/
pay(item){
this.payShow = true;
this.payOrder = item;
async handlePay(item){
let payType = 'wxjsapi'
if(!this.$store.state.openId){
payType = 'h5'
}
const {error, result} = await ApiPostCashierPrepay({
orderId:item.orderId,
returnUrl : `${ENV.VUE_APP_STATIC_URL}/payResult?orderId=${item.orderId}&payType=${payType}`
});
// #ifdef H5
window.location.href = result.wapCashierUrl
// #endif
// #ifndef H5
this.$Router.push(`/webView?url=${encodeURIComponent(result.wapCashierUrl)}`);
// #endif
},
/**
@ -144,7 +173,7 @@ export default {
uni.$toast(error.message);
return false;
}
this.$Router.push('/orderSuccess')
this.$Router.push(`/orderSuccess?orderId=${item.orderId}`)
}
}
})

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-04-18 15:28:14
* @LastEditors: ch
* @LastEditTime: 2022-06-01 15:34:49
* @LastEditTime: 2022-06-22 11:22:21
* @Description: file content
-->
<template>
@ -11,7 +11,7 @@
<UiGoodsInfo :class="idx === orderInfo.products.length-1 ? 'goods-info__last' : ''" :key="item.orderProductId"
v-for="(item, idx) in orderInfo.products" :data="item"></UiGoodsInfo>
</UiWhiteBox>
<UiWhiteBox class="company" v-if="orderInfo.orderType !== ORDER_TYPE.VIRTUAL">
<UiWhiteBox class="company" v-if="orderInfo.orderType !== ORDER.TYPE.VIRTUAL">
<text class="company--name">{{orderInfo.companyName}}</text>
<view class="company--no">
<text>{{orderInfo.trackingNo}}</text>
@ -38,12 +38,12 @@ import UiGoodsInfo from '@/components/UiGoodsInfo.vue'
import UiWhiteBox from '@/components/UiWhiteBox.vue'
import {ApiGetOrderLogistics} from '@/common/api/order';
import UiCopy from '../../components/UiCopy.vue';
import {ORDER_TYPE} from '@/common/dicts/order';
import ORDER from '@/common/dicts/order';
export default {
components: { UiWhiteBox, UiGoodsInfo, UiCopy },
data(){
return {
ORDER_TYPE,
ORDER,
orderInfo : {}
}
},

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-28 17:16:44
* @LastEditors: ch
* @LastEditTime: 2022-04-29 23:03:47
* @LastEditTime: 2022-06-28 16:46:43
* @Description: file content
-->
<template>
@ -10,7 +10,8 @@
<image class="icon" src="@/static/order/paySuccess.png"/>
<view class="title">交易成功</view>
<view class="btns">
<UiButton class="btn" type="primaryLine" @click="$Router.replaceAll('/')"></UiButton>
<UiButton class="btn" @click="$Router.replaceAll('/')"></UiButton>
<UiButton class="btn" type="primaryLine" @click="$Router.replace(`/comment?orderId=${orderId}`)"></UiButton>
</view>
</view>
</template>
@ -18,6 +19,11 @@
import UiButton from '@/components/UiButton.vue'
export default {
components: { UiButton },
data(){
return {
orderId : this.$Route.query.orderId
}
}
}
</script>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-04-28 15:01:41
* @LastEditors: ch
* @LastEditTime: 2022-05-06 10:49:00
* @LastEditTime: 2022-07-13 18:41:57
* @Description: file content
-->
@ -55,10 +55,10 @@ export default {
this.reuqestNum++;
const {error, result} = await ApiGetOrderPaySatus({orderId : this.$Route.query.orderId});
if(error){
uin.$u.toast(error.message);
uni.$u.toast(error.message);
return false
}
if(!result.isSuccess && this.reuqestNum < 5){
if(!result.isSuccess && this.reuqestNum < 10){
setTimeout(()=>{
this.getOrderInfo();
}, 1000)
@ -69,9 +69,11 @@ export default {
},
back(){
const payType = this.$Route.query.payType;
if(payType !== 'wxjsapi'){
this.$Router.back(2);
}else{
if(payType === 'wxjsapi'){
this.$Router.back();
}else if(payType === 'h5'){
history.back(2);
}else if(payType === 'appWx'){
this.$Router.back();
}
}

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-20 14:14:53
* @LastEditors: ch
* @LastEditTime: 2022-05-26 16:33:14
* @LastEditTime: 2022-07-13 18:18:18
* @Description: file content
-->
<template>
@ -34,21 +34,6 @@
maxlength="50" placeholder="填写您想要备注的信息50字以内" />
</UiCell>
</UiWhiteBox>
<UiWhiteBox>
<text class="play--title">支付方式</text>
<radio-group>
<u-cell title="微信支付" :border="false" @click="payType = 'wxpay'">
<image class="play--icon" slot="icon" src="@/static/order/wx.png"/>
<radio class="play--radio" slot="right-icon" color="#FF875B"
:checked="payType == 'wxpay'" ></radio>
</u-cell>
<!-- <u-cell title="支付宝支付" :border="false" @click="payType = 'alipay'">
<image class="play--icon" slot="icon" src="@/static/order/zfb.png"/>
<radio class="play--radio" slot="right-icon" color="#FF875B"
:checked="payType == 'alipay'"></radio>
</u-cell> -->
</radio-group>
</UiWhiteBox>
<UiWhiteBox class="amount">
<u-cell title="商品总额" :value="`¥${orderInfo.productAmount}`" :border="false"></u-cell>
@ -71,11 +56,13 @@
import {GOODS_TYPE} from '@/common/dicts/goods';
import UiCell from '@/components/UiCell';
import {ApiPostSubmitOrder, ApiGetBeforeOrder, ApiGetBeforeCartOrder} from '@/common/api/order';
import {ApiPostCashierPrepay} from '@/common/api/pay';
import {ApiGetAddress } from '@/common/api/base';
import {Wxpay} from '@/common/utils';
import {Wxpay, Alipay} from '@/common/utils';
import UiButton from '@/components/UiButton.vue';
import UiWhiteBox from '../../components/UiWhiteBox.vue';
import UiGoodsInfo from '../../components/UiGoodsInfo.vue';
const ENV = process.env;
export default {
components : {UiCell, UiButton, UiWhiteBox, UiGoodsInfo },
data(){
@ -84,7 +71,6 @@ export default {
address : {},
userMessage : '',
orderInfo : {},
payType : 'wxpay',
productType : this.$Route.query.productType,
}
},
@ -189,11 +175,28 @@ export default {
uni.$u.toast(error.message);
return false;
}
if(this.payType === 'wxpay'){
Wxpay({orderId : result.orderId, openId : this.$store.state.openId});
}else{
uni.$u.toast('暂不支持支付宝支付');
let payType = 'wxjsapi'
if(!this.$store.state.openId){
payType = 'h5'
}
const {error:er, result:res} = await ApiPostCashierPrepay({
orderId:result.orderId,
returnUrl : `${ENV.VUE_APP_STATIC_URL}/payResult?orderId=${result.orderId}&payType=${payType}`
});
if(er){
uni.$u.toast(er.message);
return false;
}
// #ifdef H5
window.location.replace(res.wapCashierUrl)
// #endif
// #ifndef H5
this.$Router.push(`/webView?url=${encodeURIComponent(res.wapCashierUrl)}`);
// #endif
}
}
}

@ -0,0 +1,35 @@
<!--
* @Author: ch
* @Date: 2022-07-12 17:19:59
* @LastEditors: ch
* @LastEditTime: 2022-07-12 18:35:24
* @Description: file content
-->
<template><view>
<web-view :src="url"></web-view>
</view>
</template>
<script>
export default {
data (){
return {
url : ''
}
},
onLoad(){
this.url = decodeURIComponent(this.$Route.query.url);
},
onReady() {
var currentWebview = this.$scope.$getAppWebview() //html5plusplus.webview.currentWebview()uni-appvue使plus.webview.currentWebview()
setTimeout(function() {
let wv = currentWebview.children()[0];
wv.addEventListener('loaded',function() {
console.log('xxxxx',wv.getURL())
console.log(wv.getURL()) //url
console.log(wv.getTitle()) //
}, false);
}, 1000); //
}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Loading…
Cancel
Save