Merge branch 'dev1.0.0' into develop

msb_beta
ch 4 years ago
commit 61a45c1eb3

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-22 18:28:52
* @LastEditors: ch
* @LastEditTime: 2022-04-28 18:43:18
* @LastEditTime: 2022-04-29 14:13:05
* @Description: file content
*/
import Vue from 'vue'
@ -26,6 +26,7 @@ export default new Vuex.Store({
address : JSON.parse(uni.getStorageSync(ADDRESS) || '[]'),
sessionData : [],
sessionMsgCount : 0,
sessionMsgId : '',
openId : uni.getStorageSync(OPPED_ID) || ''
},
mutations:{
@ -50,6 +51,9 @@ export default new Vuex.Store({
SET_OPEN_ID (state, data){
state.openId = data;
uni.setStorageSync(OPPED_ID, data);
},
SET_SESSION_MSG_ID (state, data){
state.sessionMsgId = data;
}
},
actions : {

@ -2,15 +2,17 @@
* @Author: ch
* @Date: 2022-03-22 16:52:28
* @LastEditors: ch
* @LastEditTime: 2022-04-26 17:52:05
* @LastEditTime: 2022-04-29 14:49:13
* @Description: 所有工具类统一在这输出
*/
import * as util from './utils';
import * as requset from './requset';
// import * as websocket from './requset';
import * as websocket from './requset';
import * as wxpay from './wxpay';
export * from './utils';
export * from './requset';
// export * from './websocket';
export * from './websocket';
export * from './wxpay';
export default { ...util, ...requset}
export default { ...util, ...requset, ...websocket, ...wxpay}

@ -2,19 +2,19 @@
* @Author: ch
* @Date: 2022-03-17 17:42:32
* @LastEditors: ch
* @LastEditTime: 2022-04-28 17:04:33
* @LastEditTime: 2022-04-29 15:15:55
* @Description: 项目接口请求统一处理器,返回一个需要token和不需要token的请求封装方法
*/
import MsbUniRequest from '@/common/plugins/msbUniRequest';
import $store from '@/common/store';
const ENV = 'prod';
const ENV = 'test';
const BASE_URL = {
'test' : 'https://k8s-horse-gateway.mashibing.cn',
'dev' : '',
'release' : '',
'prod' : '//like-gateway.mashibing.com'
'prod' : '//you-gateway.mashibing.com'
};
/**
* 接口返回成功结果统一处理
@ -22,13 +22,13 @@ const BASE_URL = {
* @param {*} option
*/
const successIntercept = (response, option) =>{
clearRepeat(option)
clearRepeat(option);
if(response.statusCode === 200){
const result = response.data;
if(result.code === 'SUCCESS'){
return result.data;
}
if(result.code === 'TOKEN_EXPIRE'){
if(result.code === 'TOKEN_FAIL'){
uni.navigateTo({url : '/login'})
return result;
}

@ -2,31 +2,13 @@
* @Author: ch
* @Date: 2022-04-25 14:39:19
* @LastEditors: ch
* @LastEditTime: 2022-04-26 16:28:01
* @LastEditTime: 2022-04-28 23:33:33
* @Description: file content
*/
import store from "../store";
import {createUUID, formatDate} from '@/common/utils';
export const MsbWebSkt = uni.connectSocket({
url : `ws://192.168.10.92:8090/ws?client=${store.state.token}`, // url是websocket连接ip
success: () => {
console.log('websocket连接成功!')
},
fail: e => {
console.log('连接失败' + e)
}
});
MsbWebSkt.onClose(()=>{
console.log('WebSocket关闭...!')
})
let sessionListFlag = false;
MsbWebSkt.onMessage((res)=>{
const data = JSON.parse(res.data || {});
if(data.code === 200){
const ctx = data.content;
switch(data.traceType){
// 会话列表
case 1 :
const sessionList = (ctx) => {
sessionListFlag = true;
// 来新消息先查会话列表是否一存在,存在则加消息数。不存在则向会话列表加一个会话框
ctx.sessionVOS.forEach(item => {
@ -44,10 +26,13 @@ MsbWebSkt.onMessage((res)=>{
}
});
// 消息总数
store.commit('SET_SESSION_MSG_COUNT', ctx.totalUnreadCount || 10);
break;
// 历史消息
case 2 :
store.commit('SET_SESSION_MSG_COUNT', ctx.totalUnreadCount);
}
const historyMsg = (ctx) => {
if(!ctx.length){
return false;
}
ctx.reverse();
let newData = store.state.sessionData;
const hisIdx = newData.findIndex(i => i.id === ctx[0].sessionId);
ctx.forEach(item => {
@ -56,27 +41,33 @@ MsbWebSkt.onMessage((res)=>{
})
newData[hisIdx].messageList = ctx.concat(newData[hisIdx].messageList);
store.commit('SET_SESSION_DATA', newData);
console.log(newData);
break;
// 会话消息
case 7 :
}
/**
* 收到某个会话的信息
* @param {*} ctx
*/
const sessionMsg = (ctx)=>{
// 没接到会话列表时接到的消息不做处理
if(!sessionListFlag){
break;
return
}
// ctx.forEach(item => {
ctx.payload = JSON.parse(ctx.payload || {});
ctx.createTimeStamp = formatDate(ctx.createTimeStamp, 'mm-dd hh:ii')
let historyData = store.state.sessionData;
const hisIndex = historyData.findIndex(i => i.id === ctx.sessionId);
// 不在当前会话框则全局消息加1
if(ctx.sessionId !== store.state.sessionMsgId){
store.commit('SET_SESSION_MSG_COUNT', store.state.sessionMsgCount + 1);
}
if(hisIndex >= 0){
// 存在会话往现有会话增加一条消息
const curHisData = historyData[hisIndex];
curHisData.messageList = [ ...(curHisData.messageList || []), ctx]
curHisData.messageList = [ ctx, ...(curHisData.messageList || [])]
// 不在当前会话框则会话框消息加1
if(ctx.sessionId !== store.state.sessionMsgId){
curHisData.unreadCount++;
}
store.commit('SET_SESSION_DATA', historyData);
}else{
// 会话列表不存在,则创建一个会话
store.commit('SET_SESSION_DATA',[...historyData, {
@ -90,17 +81,55 @@ MsbWebSkt.onMessage((res)=>{
}]);
}
// });
}
export let MsbWebSkt = null;
export const MsbWebSktInit = () => {
return new Promise((resolve, reject) => {
MsbWebSkt = uni.connectSocket({
url : `ws://192.168.10.92:8090/ws?client=${store.state.token}`, // url是websocket连接ip
fail: e => {
reject(e)
}
});
MsbWebSkt.onOpen(()=>{
MsbWebSkt.onMessage((res)=>{
const data = JSON.parse(res.data || {});
if(data.code === 200){
const ctx = data.content;
switch(data.traceType){
// 会话列表
case 1 :
sessionList(ctx);
break;
// 历史消息
case 2 :
historyMsg(ctx)
break;
// 会话消息
case 7 :
sessionMsg(ctx)
break;
default :
break;
}
}
})
setInterval(()=>{
MsbWebSkt.send({
data : JSON.stringify({
traceId : createUUID(),
traceType : "0",
content: { text : "ping"}
})
})
MsbWebSkt.onError(()=>{
console.log('WebSocket连接错误')
}, 5000);
resolve();
})
})
}

@ -0,0 +1,56 @@
/*
* @Author: ch
* @Date: 2022-04-29 14:26:10
* @LastEditors: ch
* @LastEditTime: 2022-04-29 14:54:16
* @Description: file content
*/
import { ApiPostWxH5Pay, ApiPostWxJsApiPay } from '@/common/api/wx';
export const Wxpay = async ({orderId,openId})=>{
// 有openId则表示在微信浏览器内
if(openId) {
// 微信JSAPI
const {error, result} = await ApiPostWxJsApiPay({orderId,openId});
if(error){
uni.$u.toast(error.message);
return false;
}
/*
* 公众号id appId 是 String(16) wx8888888888888888
时间戳 timeStamp 是 String(32) 1414561699 当前的时间
随机字符串 nonceStr 是 String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 随机字符串,不长于32位。推荐随机数生成算法
订单详情扩展字符串 package 是 String(128) prepay_id=123456789 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
签名方式 signType 是 String(32) MD5 签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致
签名 paySign 是 String(64) C380BEC2BFD727A4B6845133519F3AD6 签名
*/
const par = result.dataInfo;
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId : par.appId,
timeStamp : par.timeStamp,
nonceStr : par.nonceStr,
package : par.packageValue,
signType : par.signType,
paySign : par.paySign
}, res => {
if(res.err_msg === 'get_brand_wcpay_request:cancel'){
uni.navigateTo({
url : `/payResult?id=${orderId}`
});
}else{
uni.navigateTo({
url : `/payResult?orderId=${orderId}`
});
}
})
}else{
// h5支付
const {error, result} = await ApiPostWxH5Pay({orderId});
if(error){
uni.$u.toast(error.message);
return false;
}
const redirect_url = decodeURIComponent(`https://like-app.mashibing.com/payResult?orderId=${orderId}`);
window.location.href = `${result.dataInfo.payUrl}&redirect_url=${redirect_url}`;
}
}

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-04-19 11:37:50
* @LastEditors: ch
* @LastEditTime: 2022-04-22 18:11:00
* @LastEditTime: 2022-04-29 15:29:47
* @Description: file content
-->
<template>
@ -12,6 +12,7 @@
<script>
import UiRadioPicker from './UiRadioPicker.vue'
import { ApiPostWxPay } from '@/common/api/order';
import { Wxpay } from '@/common/utils';
export default {
components: { UiRadioPicker },
props : {
@ -39,13 +40,13 @@ export default {
}
},
methods:{
async confirm(val){
confirm(val){
const orderId = this.order.orderId;
const {error, result} = await ApiPostWxPay({orderId,payTypeEnum:'WXPAY'});
if(error){
this.$Router.replace(`/payFail?ordId=${orderId}`)
if(val.value === 'wxpay'){
Wxpay({orderId, openId: this.$store.state.openId});
this.close();
}else{
this.$Router.replace(`/paySuccess?ordId=${orderId}`)
uni.$u.toast('暂不支持支付宝支付');
}
},
close(){

@ -1,2 +1,2 @@
<!DOCTYPE html><html lang=zh-CN><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><title>马士兵严选</title><script>var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/static/index.a5c69d49.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/static/js/chunk-vendors.b5602bf5.js></script><script src=/static/js/index.238d1abc.js></script></body></html>
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/static/index.a5c69d49.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/static/js/chunk-vendors.b5602bf5.js></script><script src=/static/js/index.3016a170.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["pages-account-message-list"],{4783:function(t,n,e){"use strict";e("7db0"),Object.defineProperty(n,"__esModule",{value:!0}),n.default=void 0;var s={computed:{msgData:function(){var t=this,n=this.$store.state.sessionData.find((function(n){return n.id==t.$Route.query.id}));return n?n.messageList:[]}},onShow:function(){this.getHistoryMsg()},methods:{getHistoryMsg:function(){},xx:function(){console.log(this.$store.state.sessionData)}}};n.default=s},"7c81":function(t,n,e){"use strict";e.r(n);var s=e("a496"),i=e("d9ce");for(var a in i)"default"!==a&&function(t){e.d(n,t,(function(){return i[t]}))}(a);e("a2c3");var c,o=e("f0c5"),r=Object(o["a"])(i["default"],s["b"],s["c"],!1,null,"1f2074c9",null,!1,s["a"],c);n["default"]=r.exports},"82a3":function(t,n,e){t.exports=e.p+"static/img/xt.5199e39b.png"},9189:function(t,n,e){var s=e("24fb");n=s(!1),n.push([t.i,'@charset "UTF-8";\n/**\n * 这里是uni-app内置的常用样式变量\n *\n * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量\n * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App\n *\n */\n/**\n * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能\n *\n * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件\n */\n/* 颜色变量 */\n/* 行为相关颜色 */\n/* 文字基本颜色 */\n/* 背景颜色 */\n/* 边框颜色 */\n/* 透明度 */\n/* 尺寸变量 */\n/* 文字尺寸 */\n/* 间距 */\n/* 图片尺寸 */\n/* Border Radius */\n/* 水平间距 */\n/* 垂直间距 */.msgItem[data-v-1f2074c9]{padding:%?40?% 0 0 %?40?%}.msgItem--title[data-v-1f2074c9]{display:flex;justify-content:space-between;align-items:center;padding-right:%?40?%;font-size:%?32?%;color:#333}.msgItem--time[data-v-1f2074c9]{font-size:%?24?%;color:#999}.msgItem--con[data-v-1f2074c9]{display:flex;border-bottom:1px solid #eee;padding:%?40?% 0}.msgItem--img[data-v-1f2074c9]{width:%?140?%;height:%?140?%;border-radius:%?12?%;margin-right:%?40?%}.msgItem--desc[data-v-1f2074c9]{width:%?455?%;font-size:%?28?%;line-height:%?39?%;color:#666}',""]),t.exports=n},a2c3:function(t,n,e){"use strict";var s=e("fc0f"),i=e.n(s);i.a},a496:function(t,n,e){"use strict";var s;e.d(n,"b",(function(){return i})),e.d(n,"c",(function(){return a})),e.d(n,"a",(function(){return s}));var i=function(){var t=this,n=t.$createElement,s=t._self._c||n;return s("v-uni-view",t._l(t.msgData,(function(n){return s("v-uni-view",{key:n.id,staticClass:"msgItem"},[s("v-uni-view",{staticClass:"msgItem--title"},[s("v-uni-text",[t._v(t._s(n.payload.title))]),s("v-uni-text",{staticClass:"msgItem--time"},[t._v(t._s(n.createTimeStamp))])],1),s("v-uni-view",{staticClass:"msgItem--con"},[s("v-uni-image",{staticClass:"msgItem--img",attrs:{src:e("82a3"),mode:"widthFix"}}),s("v-uni-view",{staticClass:"msgItem--desc"},[t._v(t._s(n.payload.content))])],1)],1)})),1)},a=[]},d9ce:function(t,n,e){"use strict";e.r(n);var s=e("4783"),i=e.n(s);for(var a in s)"default"!==a&&function(t){e.d(n,t,(function(){return s[t]}))}(a);n["default"]=i.a},fc0f:function(t,n,e){var s=e("9189");"string"===typeof s&&(s=[[t.i,s,""]]),s.locals&&(t.exports=s.locals);var i=e("4f06").default;i("05da04a3",s,!0,{sourceMap:!1,shadowMode:!1})}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2021-07-26 23:22:16
* @LastEditors: ch
* @LastEditTime: 2022-04-28 17:15:23
* @LastEditTime: 2022-04-29 14:20:16
* @Description: file content
*/
import Vue from 'vue';
@ -15,34 +15,25 @@ import Confirm from '@/components/mount/index';
import route from 'uview-ui/libs/util/route';
import {toSearchJson} from '@/common/utils';
import {ApiGetOpenId, ApiGetAuthUrl} from '@/common/api/wx';
// import {MsbWebSkt, createUUID} from '@/common/utils';
import {MsbWebSkt, MsbWebSktInit, createUUID} from '@/common/utils';
if(store.state.token){
// 进入应用则向IM发起心跳包 以及获取IM会话数据
// MsbWebSkt.onOpen(()=>{
// MsbWebSkt.send({
// data : JSON.stringify({
// traceId : createUUID(),
// traceType : "1",
// content: { sysId : "1"}
// })
// });
// setInterval(()=>{
// MsbWebSkt.send({
// data : JSON.stringify({
// traceId : createUUID(),
// traceType : "0",
// content: { text : "ping"}
// })
// })
MsbWebSktInit().then(()=>{
MsbWebSkt.send({
data : JSON.stringify({
traceId : createUUID(),
traceType : "1",
content: { sysId : "1"}
})
});
})
}
// }, 5000)
// });
// 微信打开需要授权
const ua = navigator.userAgent.toLowerCase();
console.log(ua);
if(ua.includes('micromessenger')) {
if(!store.state.openId){
let query = toSearchJson(window.location.search)
@ -69,7 +60,6 @@ if(ua.includes('micromessenger')) {
})
}
}
// 微信JSAPI
}

@ -170,20 +170,6 @@
"navigationBarTitleText": "交易成功"
}
},
{
"path": "pages/order/paySuccess",
"aliasPath" : "/paySuccess",
"style": {
"navigationBarTitleText": "支付成功"
}
},
{
"path": "pages/order/payFail",
"aliasPath" : "/payFail",
"style": {
"navigationBarTitleText": "支付失败"
}
},
{
"path": "pages/order/payResult",
"aliasPath" : "/payResult",

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-22 13:54:15
* @LastEditors: ch
* @LastEditTime: 2022-04-22 21:23:54
* @LastEditTime: 2022-04-29 00:26:44
* @Description: file content
-->
<template>
@ -78,6 +78,9 @@ export default {
return false;
}
this.addresList = result;
if(!result.length){
this.$Router.replace(`/addressCreate?first=${!result.length}`)
}
this.$store.commit('SET_ADDRESS', result);
if(this.query.source === 'submitOrder'){
// 每次刷新列表都做一次提交订单页的选中地址更新

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-22 16:13:00
* @LastEditors: ch
* @LastEditTime: 2022-04-25 19:34:58
* @LastEditTime: 2022-04-28 23:02:54
* @Description: file content
-->
<template>
@ -10,7 +10,7 @@
<BsEmpty tips="暂时还没有消息哦~" v-if="!$store.state.sessionData.length"
:icon="require('@/static/message/empty.png')" />
<view class="msgItem" v-for="item in $store.state.sessionData" :key="item.id"
@click="$Router.push(`/messageList?id=${item.id}`)">
@click="openMsg(item)">
<image class="msgItem--headImg" src="@/static/account/tx.png"></image>
<view class="msgItem--con">
<view>
@ -33,6 +33,12 @@ export default {
return {
sessionData : this.$store.state.sessionData
}
},
methods:{
openMsg(item){
this.$store.commit('SET_SESSION_MSG_ID',item.id);
this.$Router.push(`/messageList`);
}
}
}
</script>

@ -2,14 +2,14 @@
* @Author: ch
* @Date: 2022-03-26 14:32:03
* @LastEditors: ch
* @LastEditTime: 2022-04-26 17:52:30
* @LastEditTime: 2022-04-28 23:43:35
* @Description: file content
-->
<template>
<view>
<view class="msgItem" v-for="item in msgData" :key="item.id">
<view class="msgItem--title">
<text>{{item.payload.title}}</text>
<text>{{item.payload.title }} {{item.id}}</text>
<text class="msgItem--time">{{item.createTimeStamp}}</text>
</view>
<view class="msgItem--con">
@ -17,42 +17,73 @@
<view class="msgItem--desc">{{item.payload.content}}</view>
</view>
</view>
<u-loadmore status="loading" v-if="!msgData.length"/>
</view>
</template>
<script>
// import {MsbWebSkt, createUUID} from '@/common/utils';
import {MsbWebSkt, createUUID} from '@/common/utils';
export default {
data(){
return {
}
},
computed:{
curSessionData(){
return this.$store.state.sessionData.find(i =>i.id == this.$store.state.sessionMsgId)
},
msgData (){
// console.log(this.$store.state.sessionData,'---',this.$Route.query.id);
const sessionData = this.$store.state.sessionData.find(i =>i.id == this.$Route.query.id)
return sessionData ? sessionData.messageList : [];
return this.curSessionData ? this.curSessionData.messageList : [];
}
},
onReachBottom(){
this.getHistoryMsg();
},
onShow(){
if(!this.$store.state.sessionMsgId){
this.$Router.back();
return false
}
this.getHistoryMsg();
this.readMsg();
},
methods:{
/**
* 获取历史消息
*/
getHistoryMsg(){
// MsbWebSkt.onOpen(()=>{
// MsbWebSkt.send({
// data : JSON.stringify({
// traceId : createUUID(),
// traceType : "2",
// content: { sessionId : this.$Route.query.id}
// }),
// success(){
// console.log('suxx');
// },
// fail(e){
// console.log('fxx',e);
// }
// })
// })
this.loading = true;
const lastMsg = this.msgData[this.msgData.length - 1] || {};
MsbWebSkt.send({
data : JSON.stringify({
traceId : createUUID(),
traceType : "2",
content: {
sessionId : this.$store.state.sessionMsgId,
topMessageId : lastMsg.id || null
}
})
})
},
xx(){
console.log(this.$store.state.sessionData);
/**
* 已读消息
*/
readMsg(){
MsbWebSkt.send({
data : JSON.stringify({
traceId : createUUID(),
traceType : "6",
content: {
sessionId : this.$store.state.sessionMsgId
}
})
});
// 计算页头消息数
const count = this.$store.state.sessionMsgCount - this.curSessionData.unreadCount;
// 计算会话列表消息数
this.curSessionData.unreadCount = 0;
this.$store.commit('SET_SESSION_MSG_COUNT', count)
}
}
}

@ -50,7 +50,7 @@
<template v-if="!isLoading">
<view class="title">为您推荐</view>
<!-- <BsChoiceGoods></BsChoiceGoods> -->
<BsChoiceGoods></BsChoiceGoods>
</template>
<!-- 底部操作栏 -->
@ -60,13 +60,13 @@
:checked="checkedIds.length > 0 && checkedIds.length === list.length" />
<text>全选</text>
</label>
<view class="total-info">
<view class="total-info" v-if="mode == 'normal'">
<text>合计:</text>
<UiMoney class="goods-price" :money="totalPrice" prefix/>
</view>
<view class="cart-action">
<UiButton v-if="mode == 'edit'" size="max" :disable="!checkedIds.length" @click="handleDelete">删除</UiButton>
<UiButton v-else type="gradual" size="max" :disable="!checkedIds.length" @click="handleOrder">去结算({{list.length}})</UiButton>
<UiButton v-if="mode == 'edit'" size="max" :disable="!checkedIds.length" @click="handleDelete">删除({{checkedIds.length}})</UiButton>
<UiButton v-else type="gradual" size="max" :disable="!checkedIds.length" @click="handleOrder">去结算({{checkedIds.length}})</UiButton>
</view>
</view>
</view>
@ -451,6 +451,7 @@ export default {
// 底部操作栏
.footer {
display: flex;
justify-content: space-between;
align-items: center;
height: 140rpx;
background: $color-grey0;

@ -1,368 +0,0 @@
<!--
* @Author: ch
* @Date: 2022-03-24 11:30:55
* @LastEditors: ch
* @LastEditTime: 2022-04-24 20:56:47
* @Description: file content
-->
<template>
<u-popup :show="visible" round="24rpx" closeable @close="close">
<view class="sku-popup">
<view class="product-info">
<image class="product-info--img" src="https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/test/1.png"/>
<view>
<view class="product-info--price">¥{{curSku.sellPrice}}</view>
<view class="product-info--sku">{{curSku.name}}</view>
<view>库存:{{curSku.stock}}</view>
</view>
</view>
<view class="attr-group" v-for="(item, index) in attributeGroupList" :key="item.id">
<text class="attr-name">{{item.name}}</text>
<view class="attr-items">
<text class="attr-item" :class="{'attr-item__active' : i.active, 'attr-item__disabled' : i.disabled}"
v-for="i in item.attributes" :key="i.symbol"
@click="handleAttrItem(i, index)"
>{{i.name}}</text>
</view>
</view>
<view class="sku-num">
<view class="sku-num--single-box">
<template>
<text>数量</text>
<!-- <text class="sku-num--single">{{maxBuyNum}}</text> -->
</template>
</view>
<u-number-box :min="1" :max="maxBuyNum" button-size="40rpx" bgColor="#F5F6FA"
v-model="curBuyNum" >
<text slot="minus" class="cart-item--stepper-icon">-</text>
<text slot="plus" class="cart-item--stepper-icon">+</text>
</u-number-box>
</view>
<view class="footer">
<view class="btn-bg" v-if="mode == 1">
<UiButton class="btn" @click="addCart" size="max" :disable="curSku.stock == 0">加入购物车</UiButton>
<UiButton class="btn btn__buy" @click="buyNow" size="max" :disable="curSku.stock == 0">立即购买</UiButton>
</view>
<UiButton v-else class="btn__confirm" type="gradual" size="max" @click="confirm">确认</UiButton>
</view>
</view>
</u-popup>
</template>
<script>
import UiButton from '@/components/UiButton.vue';
import {ApiPutAddCart} from '@/common/api/cart';
export default {
components: { UiButton },
props: {
// true 组件显示 false 组件隐藏
visible : {
type : Boolean,
default : false
},
// 模式 1:都显示 2:只显示购物车 3:只显示立即购买
mode: {
type: Number,
default: 1,
},
// 商品详情信息
goodsInfo: {
type: Object,
default: {},
},
// 商品sku信息
skuInfo : {
type : Array,
default : []
},
// 活动状态
activityStatus : {
type : String,
default : 'noActivity'
}
},
data() {
return {
// 属性组数据,因为会修改数据,不能直接操作props中传入的数据
attributeGroupList : [],
// 数量
curBuyNum : 1,
};
},
watch : {
goodsInfo(newData){
if(newData.attributeGroupList){
this.attributeGroupList = newData.attributeGroupList;
// 请求数据返回后设置默认选中规格
if(this.skuInfo.length){
this.setDefaultAttr();
}
}
},
skuInfo(newData){
// 请求数据返回后设置默认选中规格
if(newData.length){
this.setDefaultAttr();
}
}
},
computed : {
/**
* 当前选中SKU,根据选中规格计算
*/
curSku(){
// const skuSymbolList = this.attributeGroupList.map(item => {
// const activeAttr = item.attributes.find(i => i.active);
// return activeAttr ? activeAttr.symbol : ''
// }).filter(i => i).sort();
return this.skuInfo.find(i => i.attributeSymbolList === this.selectedSymbol.join(',')) || {};
},
selectedSymbol(){
return this.attributeGroupList.map(item => {
const activeAttr = item.attributes.find(i => i.active);
return activeAttr ? activeAttr.symbol : ''
}).filter(i => i).sort();
},
/**
* 最大可购买数量
* 1、有限购则对比限购跟库存,取最小值
* 2、没限购取库存
*/
maxBuyNum(){
const singleBuyLimit = this.goodsInfo.singleBuyLimit;
const stock = this.curSku.stock;
return singleBuyLimit ? Math.min(singleBuyLimit, stock || 1) : stock;
}
},
methods: {
/**
* 设置默认选中规格
*/
setDefaultAttr(){
const curSku = this.skuInfo.find(i => i.stock > 0);
if(!curSku){
return false
}
// this.attributeGroupList.forEach((item, index) => {
// for(let i of item.attributes){
// if(curSku.attributeSymbolList.includes(i.symbol)){
// this.$set(i,'active', true);
// this.setDisabledItem(i, index, true);
// break;
// }
// }
// });
// this.$emit('input',this.curSku);
},
/**
* 点击属性项,设置选中和禁用项
*/
handleAttrItem(item, groupIndex){
// 禁用选项
if(item.disabled){
return false;
}
// 每次重选规格,购买数量都置为1
this.curBuyNum = 1;
// 把当前选项组的装先置为未选状态
this.attributeGroupList[groupIndex].attributes.forEach(item =>{
this.$set(item,'active', false);
});
// 设置当前点击选项选中
this.$set(item,'active', true);
this.setDisabledItem(item, groupIndex);
},
setDisabledItem(item, groupIndex){
// 找到有效SKU的symbol 有效定义:包含当前已选选项组合(不能包含最后一项),且库存大于0的所有SKU;
const symbolCombination = this.selectedSymbol.filter((item, idx) => idx < this.attributeGroupList.length -1 );
console.log(symbolCombination);
const symbols = this.skuInfo.filter(i => i.attributeSymbolList.includes(symbolCombination.join(',')) && i.stock > 0)
.map(i => i.attributeSymbolList).join(',');
console.log(item.symbol, this.skuInfo.map(i => i.attributeSymbolList) , symbols);
console.log(this.selectedSymbol);
this.attributeGroupList.forEach((group, index) => {
if(groupIndex === index){
return false;
}
// 遍历其他选项组的所有属性项,对比是否在有效SKU的symbos中,在则启用,不再则禁用
group.attributes.forEach(item =>{
console.log(symbols,item.symbol)
if(!symbols.includes(item.symbol)){
this.$set(item,'disabled', true);
}else{
this.$set(item,'disabled', false);
}
})
})
},
/**
* 加入购物车
*/
async addCart(){
if(!this.curSku.skuId){
uni.$u.toast('请选择规格~');
return false;
}
const {error, result} = await ApiPutAddCart({
productSkuId : this.curSku.skuId,
productId : this.goodsInfo.id,
number : this.curBuyNum
});
if(error){
uni.$u.toast(error.message);
return false;
}
uni.$u.toast('加入购物车成功~');
this.close();
// this.$Router.push('/cart');
},
/**
* 立即购买
*/
buyNow(){
if(!this.curSku.skuId){
uni.$u.toast('请选择规格~');
return false;
}
let query = {
mode : 'buyNow',
skuId : this.curSku.skuId,
num : this.curBuyNum,
activityType : 1
}
const {productActivityVO} = this.goodsInfo;
if(this.activityStatus === 'startActivity'){
query.activityType = 2;
query.activityId = productActivityVO.activityId;
query.activityTimeId = productActivityVO.activityTimeId;
}
this.$Router.push({
path : '/orderSubmit',
query
})
},
confirm(){
if(this.mode == 2){
this.addCart();
}
if(this.mode == 3){
this.buyNow();
}
},
close(){
this.$emit('update:visible', false);
}
}
};
</script>
<style lang="scss" scoped>
.sku-popup{
padding: 30rpx;
}
.product-info{
display: flex;
font-size: $font-size-base;
color: $color-grey4;
line-height: 42rpx;
&--img{
width: 200rpx;
height: 200rpx;
margin-right: 40rpx;
}
&--price{
font-size: 40rpx;
color: $color-yellow4;
line-height: 48rpx;
margin-bottom: 20rpx;
}
}
.attr-group{
margin-top: 40rpx;
font-size: 30rpx;
}
.attr-items{
display: flex;
flex-wrap: wrap;
padding: 10rpx 0;
}
.attr-item{
background: $color-grey1;
line-height: 70rpx;
border-radius: 100rpx;
border: 1px solid $color-grey1;
color: $color-grey5;
display: block;
min-width: 158rpx;
max-width: 630rpx;
text-align: center;
margin: 20rpx 28rpx 0 0;
padding: 0 20rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&__active{
background: #FFF3EE;
border-color: $color-yellow4;
color: $color-yellow3;
}
&__disabled{
color: $color-grey3;
}
}
.sku-num{
display: flex;
justify-content: space-between;
margin: 40rpx 0;
line-height: 40rpx;
&--single-box{
display: flex;
align-items: center;
}
&--single{
color: $color-grey4;
margin-left: 10rpx;
font-size: $font-size-base;
display: block;
height: 30rpx;
}
}
.footer{
display: flex;
justify-content: space-between;
.btn-bg{
background: #FFE6D9;
border-radius: 50rpx;
height: 80rpx;
}
.btn{
border: 0;
padding: 0;
border-radius: 0;
width: 340rpx;
font-size: $font-size-base;
color: $color-yellow3;
&::after{
border: 0;
}
&__buy{
width: 350rpx;
background: url('@/static/goods/buy_max.png');
background-size: 350rpx;
color: $color-grey0;
}
}
.btn__confirm{
margin: 0;
width: 670rpx;
}
}
</style>

@ -2,14 +2,15 @@
* @Author: ch
* @Date: 2022-03-24 11:30:55
* @LastEditors: ch
* @LastEditTime: 2022-04-25 14:16:35
* @LastEditTime: 2022-04-29 00:13:38
* @Description: file content
-->
<template>
<u-popup :show="visible" round="24rpx" closeable @close="close">
<view class="sku-popup">
<view class="product-info">
<image class="product-info--img" src="https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/test/1.png"/>
<!-- <image class="product-info--img" src="https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/test/1.png"/> -->
<image class="product-info--img" :src="goodsInfo.pictureList[0]"/>
<view>
<view v-if="curSku.sellPrice" class="product-info--price">¥{{curSku.sellPrice}}</view>
<view v-else class="product-info--price">

@ -1,668 +0,0 @@
<!--
* @Author: ch
* @Date: 2022-03-24 11:30:55
* @LastEditors: ch
* @LastEditTime: 2022-04-24 21:13:30
* @Description: file content
-->
<template>
<u-popup :show="visible" round="24rpx" closeable @close="close">
<div class="content fix-header fix-bottom">
<!-- 弹出层 选择商品规格-->
<div class="mask">
<div class="mask-content">
<div class="mask-title">
<div class="mask-close iconfont-shop icon-close"></div>
选择规格参数
</div>
<div class="spec-items">
<div class="spec-menu-item js-spec-menu" v-for="(item, index) in goodsTypeList" :key="item.id">
<div class="spec-note">{{item.name}}</div>
<div class="spec-choices">
<span v-for="(el, i) in item.propertyList"
:key="el.id"
:class="{'active' : el.selected, 'disabled': el.disabled}"
@click="handleClickSpecs1(item.id, el.id, el, index, i)"
>{{el.name}}</span>
</div>
</div>
<div class="spec-menu-item">
<div class="spec-note">数量</div>
<div class="spec-num">
<span class="minus">-</span>
<input type="number" v-model="buyNumber" maxlength="3"/>
<span class="add">+</span>
</div>
</div>
</div>
</div>
</div>
</div>
</u-popup>
</template>
<script>
import UiButton from '@/components/UiButton.vue';
import {ApiPutAddCart} from '@/common/api/cart';
let orgdata = {
    "skus": [
      {
        "id": "f5eee18b8d5b4fc2b46a56e92abdb525",
        "stockAmmount": 7,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "74fe546803e44a7c95bebfe56a29952d",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "f40c3884e5e9422c973d31631a65ae64",
            "propertyName": "小",
            "property": 1
          },
          {
            "id": "78f98ee53ae549ceb2c18629152ff849",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "02808ac287e8410f936a90167d82ee2b",
            "propertyName": "two",
            "property": 2
          },
          {
            "id": "91cefe600f40498bb5013deebb9c27be",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "c80cbe4c6cbf49f5b2822331768cd422",
            "propertyName": "绿色",
            "property": 2
          }
        ]
      },
      {
        "id": "383feb7947f14ce5b832bc8700e65c9e",
        "stockAmmount": 2,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "1beed60c2eb244f89ad82806d343d468",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "02808ac287e8410f936a90167d82ee2b",
            "propertyName": "two",
            "property": 2
          },
          {
            "id": "357fd7db1f5244e5b64f48a34bb581fa",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "edac997ed2c54e41b1f3076fbd6e19f9",
            "propertyName": "中",
            "property": 2
          },
          {
            "id": "5c29a251e55a4b678fc4f8287cc560b5",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "c80cbe4c6cbf49f5b2822331768cd422",
            "propertyName": "绿色",
            "property": 2
          }
        ]
      },
      {
        "id": "905b10e1740e4be992d14cfc23a887a2",
        "stockAmmount": 4,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "0a5f93d9ef1c486ba369dcb1fbd3aed9",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "c76dc797eaae4d8eb360de8811a9ec7a",
            "propertyName": "one",
            "property": 1
          },
          {
            "id": "d920730c34644218b3d0bbc5fca5edf4",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "f40c3884e5e9422c973d31631a65ae64",
            "propertyName": "小",
            "property": 1
          },
          {
            "id": "2afbe8a77d034de0a1655f9ad1a25b95",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "c80cbe4c6cbf49f5b2822331768cd422",
            "propertyName": "绿色",
            "property": 2
          }
        ]
      },
      {
        "id": "a440b0084e564d3e9d7c8b445bb7645e",
        "stockAmmount": 10,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "12a4715b6730438888e88f302871245a",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "f40c3884e5e9422c973d31631a65ae64",
            "propertyName": "小",
            "property": 1
          },
          {
            "id": "9063e1f1586f4a74b2f614039e8743c4",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "c80cbe4c6cbf49f5b2822331768cd422",
            "propertyName": "绿色",
            "property": 2
          },
          {
            "id": "ae38b9cf56d5408a809d6fbd1b902ee5",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "d5660085ff8743d999f6ed3a497ec8b7",
            "propertyName": "three",
            "property": 3
          }
        ]
      },
      {
        "id": "9961364cc3494823aaf7699733393335",
        "stockAmmount": 15,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "3335920f79914cfb8a39ae22b0802bc0",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "c76dc797eaae4d8eb360de8811a9ec7a",
            "propertyName": "one",
            "property": 1
          },
          {
            "id": "34950de7059d4fffac485abb59a79381",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "edac997ed2c54e41b1f3076fbd6e19f9",
            "propertyName": "中",
            "property": 2
          },
          {
            "id": "a82ff8d74d3d4a1ea454e4870cc68b64",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "c80cbe4c6cbf49f5b2822331768cd422",
            "propertyName": "绿色",
            "property": 2
          }
        ]
      },
      {
        "id": "bd3aeb3c7c854a80b88e7f82a5a78a1e",
        "stockAmmount": 8,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "4fc8e61aa192463085578de92974b18b",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "edac997ed2c54e41b1f3076fbd6e19f9",
            "propertyName": "中",
            "property": 2
          },
          {
            "id": "884f32b64a4b478bb01f93b40dfeb6fc",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "c80cbe4c6cbf49f5b2822331768cd422",
            "propertyName": "绿色",
            "property": 2
          },
          {
            "id": "f66109eccd934529a18026376fccfa7b",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "d5660085ff8743d999f6ed3a497ec8b7",
            "propertyName": "three",
            "property": 3
          }
        ]
      },
      {
        "id": "5e094973bbaf41ce81b7b626174b0bbf",
        "stockAmmount": 8,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "23d688678aaa42eebd3c04cceaa61bac",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "8ed34030c93c4dc29e43edb95e6cfca2",
            "propertyName": "橙色",
            "property": 1
          },
          {
            "id": "55649f0753464921b68b0017ce0010d7",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "408fb530344a4a41b33932431638dcbb",
            "propertyName": "大",
            "property": 3
          },
          {
            "id": "d7248b12b7e847ca9be024ed3bb6d101",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "d5660085ff8743d999f6ed3a497ec8b7",
            "propertyName": "three",
            "property": 3
          }
        ]
      },
      {
        "id": "60ce0a1f99e940dc82d041d36681111b",
        "stockAmmount": 9,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "91faddf91e944cabadbda5c342430139",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "c80cbe4c6cbf49f5b2822331768cd422",
            "propertyName": "绿色",
            "property": 2
          },
          {
            "id": "207698d97e4247bb9747843d16e25750",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "408fb530344a4a41b33932431638dcbb",
            "propertyName": "大",
            "property": 3
          },
          {
            "id": "3c69d3c73aa24cccbacaf805d71117fd",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "d5660085ff8743d999f6ed3a497ec8b7",
            "propertyName": "three",
            "property": 3
          }
        ]
      },
      {
        "id": "f3c805d1959d413a86679955ae047ec5",
        "stockAmmount": 10,
        "isPaymentAccpoints": 1,
        "isPaymentCurrency": 0,
        "isPaymentMixed": 0,
        "priceAccpoints": 1,
        "priceCurrency": 0,
        "mixedPriceAccpoints": 0,
        "mixedPriceCurrency": 0,
        "rebate": 100,
        "skusTypes": [
          {
            "id": "00113d4b6046411cb8ff935b2743904b",
            "typeId": "fe7f49a798794670be622e6b9d2f386a",
            "typeName": "tester",
            "type": 3,
            "propertyId": "02808ac287e8410f936a90167d82ee2b",
            "propertyName": "two",
            "property": 2
          },
          {
            "id": "c13d8a4c7a18477fbe7027044d0393a0",
            "typeId": "547f76222d4d4f92a49de2e0bf6bd7ef",
            "typeName": "颜色",
            "type": 1,
            "propertyId": "c80cbe4c6cbf49f5b2822331768cd422",
            "propertyName": "绿色",
            "property": 2
          },
          {
            "id": "653d0e243bab45eaa5c83dc8206ee33e",
            "typeId": "21967fba6b574b479974e50720ad25fe",
            "typeName": "测试类别",
            "type": 2,
            "propertyId": "408fb530344a4a41b33932431638dcbb",
            "propertyName": "大",
            "property": 3
          }
        ]
      }
    ]
  };
  let goodType = [
    {
      "id": "547f76222d4d4f92a49de2e0bf6bd7ef",
      "type": 1,
      "name": "颜色",
      "propertyList": [
        {
          "id": "8ed34030c93c4dc29e43edb95e6cfca2",
          "property": 1,
          "name": "橙色"
        },
        {
          "id": "c80cbe4c6cbf49f5b2822331768cd422",
          "property": 2,
          "name": "绿色"
        }
      ]
    },
    {
      "id": "21967fba6b574b479974e50720ad25fe",
      "type": 2,
      "name": "测试类别",
      "propertyList": [
        {
          "id": "f40c3884e5e9422c973d31631a65ae64",
          "property": 1,
          "name": "小"
        },
        {
          "id": "edac997ed2c54e41b1f3076fbd6e19f9",
          "property": 2,
          "name": "中"
        },
        {
          "id": "408fb530344a4a41b33932431638dcbb",
          "property": 3,
          "name": "大"
        }
      ]
    },
    {
      "id": "fe7f49a798794670be622e6b9d2f386a",
      "type": 3,
      "name": "tester",
      "propertyList": [
        {
          "id": "c76dc797eaae4d8eb360de8811a9ec7a",
          "property": 1,
          "name": "one"
        },
        {
          "id": "02808ac287e8410f936a90167d82ee2b",
          "property": 2,
          "name": "two"
        },
        {
          "id": "d5660085ff8743d999f6ed3a497ec8b7",
          "property": 3,
          "name": "three"
        }
      ]
    }
  ]
export default {
props:['visible'],
data() {
return {
maskVisible: true,
skuList: [],
lastCheckedSku: {}, // 选中的sku信息
buyNumber: 1, // 购买数量
sku: null,
currentSkuList: [],
valueIdSortAndIndex: [],
goodsTypeList: [],
selectItemList: []
}
},
mounted() {
this.init();
// 获取所有的规格
this.getShopGoodsType()
this.initGoodType()
},
methods: {
init() {
let valueIdSortAndIndex = [];
let currentSkuList = orgdata.skus.map((item,index) => {
let valueIdSort = [];
item.skusTypes.map(skusTypesItem=>{
valueIdSort.push(skusTypesItem.propertyId)
});
/*
将sku规格值的ID,即 propertyId,组成一个数组并且字典排序,以及将该sku所对应的index存入数组,供点击后查询sku*/
valueIdSortAndIndex.push({valueIdSort: valueIdSort.sort()})
return item.skusTypes
});
this.$set(this.$data, 'currentSkuList', currentSkuList);
this.$set(this.$data, 'valueIdSortAndIndex', valueIdSortAndIndex);
},
isContained(aa, bb) {
//判断aa数组是否 全 包含bb数组
if(!(aa instanceof Array)
||!(bb instanceof Array)
||(aa.length<bb.length)
){
return false;
}
let aaStr = aa.toString();
for(var i=0;i<bb.length;i++){
if(aaStr.indexOf(bb[i])<0){
return false;
}
}
return true;
},
// 获取所有的规格
getShopGoodsType() {
// goodType 为接口返回数据
goodType.forEach(items=>{
items.propertyList.forEach(item=>{
item.selected = false;
item.disabled = true;
})
})
this.goodsTypeList = goodType;
},
// 初始化 判断 是否有库存
initGoodType(){
let currentSkuList = this.currentSkuList.flat(Infinity);
this.goodsTypeList.forEach(items=>{
items.propertyList.forEach(item=>{
for(var i=0; i<currentSkuList.length; i++){
if (item.id == currentSkuList[i].propertyId) {
item.disabled = false;
break;
}
}
})
})
},
// 选择每个规格,判断对应的库存
handleClickSpecs1(grounpId, id, el, index, i){
let selectItemList = this.selectItemList; // 已选规格
console.log(selectItemList);
if (el.disabled) {
return;
}
console.log(this.goodsTypeList);
// 处理selected的逻辑
if (!el.selected) {
this.goodsTypeList[index].propertyList.forEach(item=>{
item.selected = false;
})
this.goodsTypeList[index].propertyList[i].selected = true;
// 选中项中有同组元素,替换
selectItemList.forEach((item, x_selected_index) => {
if (item.index === index) {
selectItemList.splice(x_selected_index, 1)
}
});
selectItemList.push({grounpId, id, index, i});
} else {
// 取消选中并删除选中项中数据
this.goodsTypeList[index].propertyList[i].selected = false;
selectItemList.forEach((item, x_selected_index) => {
if (item.id === id && item.grounpId === grounpId) {
selectItemList.splice(x_selected_index, 1);
}
});
}
this.$set(this.$data, 'selectItemList', selectItemList)
// 取出组ID
let x_selected_grounpIds = [];
selectItemList.forEach(item=>{
x_selected_grounpIds.push(item.grounpId);
});
// 处理disabled的逻辑
if (selectItemList.length == 0) {
// 选中属性为空,重新初始化数据
this.initGoodType();
} else {
//拿所有规格属性(即goodsTypeList)的每一项分别与已选中的数据(即selectItemList)的每一项,组成一个比较项,与现有库存比较,找到存在的可点项
this.goodsTypeList.forEach((goodsType,goodsTypeIndex)=>{
goodsType.propertyList.forEach((prop, propIndex)=>{
if (!prop.selected) {
prop.disabled = true;
}
// 本次循环数据
let push_data = {grounpId: goodsType.id, id: prop.id, index: goodsTypeIndex, i: propIndex}
if (x_selected_grounpIds.indexOf(goodsType.id) > -1 ){
// 当前循环的规格的组ID在已选规格中,删除同组规格,用当前规格替换后去与库存比较
let sel = selectItemList.slice(); // 用一个新变量接受数据,防止修改源数据
let index_splice = x_selected_grounpIds.indexOf(goodsType.id);
sel.splice(index_splice, 1, push_data);
this.optionsHandle(sel, push_data)
} else {
// 当前循环规格组ID不在已选规格中,添加当前规格到复制出来的已选数组中,循环比较
let sel = selectItemList.slice();
sel.push(push_data);
this.optionsHandle(sel, push_data)
}
})
})
}
},
optionsHandle(selArr, push_data){
let propertyIds = []
// 将当前比较项的属性ID提取
selArr.map(item=>{
propertyIds.push(item.id)
});
// 在现有库存中查找是否有可选项,可选的置为可点击
this.valueIdSortAndIndex.map(item=>{
if (this.isContained(item.valueIdSort, propertyIds)){
this.goodsTypeList[push_data.index].propertyList[push_data.i].disabled = false;
}
});
}
}
};
</script>
<style lang="scss" scoped>
.spec-choices{
margin: 5px 0;
span{
background: #ccc;
padding: 5px 10px;
margin: 0 5px;
&.active{
background: $color-yellow4;
color: #fff;
}
&.disabled{
background: #eee;
color: #999;
}
}
}
</style>

@ -2,12 +2,12 @@
* @Author: ch
* @Date: 2022-03-23 10:31:12
* @LastEditors: ch
* @LastEditTime: 2022-04-22 18:02:47
* @LastEditTime: 2022-04-29 00:23:50
* @Description: file content
-->
<template>
<view class="banner">
<u-swiper bgColor="none" radius="18rpx" keyName="img" :list="data" height="240rpx" indicator indicatorMode="dot"></u-swiper>
<u-swiper bgColor="none" radius="18rpx" keyName="img" :list="data" height="240rpx" circular indicator indicatorMode="dot"></u-swiper>
<view class="desc">
<view class="desc--item">
<image class="desc--icon" src='@/static/index/bz.png'></image>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2019-08-22 19:41:20
* @LastEditors: ch
* @LastEditTime: 2022-04-27 16:56:16
* @LastEditTime: 2022-04-29 00:24:36
* @Description: file content
-->
<template>
@ -55,6 +55,7 @@ export default {
scrollTop : 0,
bannerList: [
'https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/uc/account-avatar/banner.png',
'https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/uc/account-avatar/banner.png',
'https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/uc/account-avatar/banner.png'
],
categoryList : [

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-22 15:36:46
* @LastEditors: ch
* @LastEditTime: 2022-04-27 18:46:42
* @LastEditTime: 2022-04-29 00:11:21
* @Description: file content
-->
<template>
@ -78,7 +78,6 @@ export default {
if(this.loginStatus){
return false;
}
this.loginStatus = true;
if(!IsPhone(this.phone)){
uni.$u.toast('请输入正确手机号');
return false;
@ -91,12 +90,14 @@ export default {
uni.$u.toast('请勾选同意《用户协议》和《隐私协议》');
return false;
}
this.loginStatus = true;
const {error, result} = await ApiPostLogin({
phone : this.phone,
verificationCode : this.code,
clientId : 1,
systemId : 1
});
this.loginStatus = false;
if(error){
uni.$u.toast(error.message);
return false;

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-22 10:58:24
* @LastEditors: ch
* @LastEditTime: 2022-04-22 18:07:49
* @LastEditTime: 2022-04-29 15:17:04
* @Description: file content
-->
<template>
@ -38,14 +38,7 @@
<UiButton size="min" v-if="item.orderStatus >= 4"
@click="$Router.push(`/logisitcsInfo?orderId=${item.orderId}`)">查看物流</UiButton>
<UiButton size="min" type="gradual" v-if="item.orderStatus === 4" @click="receive(item)">确认收货</UiButton>
<!-- <button class="orders--footer-btn orders--footer-btn__red"
>去支付</button>
<button class="orders--footer-btn" v-if="item.orderStatus === 2"
@click="$Router.push(`/orderDetail?id=${item.orderId}`)">查看详情</button>
<button class="orders--footer-btn" v-if="item.orderStatus >= 4"
@click="$Router.push(`/logisitcsInfo?orderId=${item.orderId}`)">查看物流</button>
<button class="orders--footer-btn orders--footer-btn__red"
v-if="item.orderStatus == 4" @click="receive(item)">确认收货</button> -->
</view>
</view>
<u-loadmore :status="loadingStatus" v-if="loadingStatus === 'loading'"/>

@ -1,44 +0,0 @@
<!--
* @Author: ch
* @Date: 2022-03-28 17:16:44
* @LastEditors: ch
* @LastEditTime: 2022-04-28 15:34:43
* @Description: file content
-->
<template>
<view>
<image class="icon" src="@/static/order/payFail.png"/>
<view class="title">支付失败</view>
<view class="desc">请重新试试</view>
<UiButton class="btn">返回商品详情</UiButton>
</view>
</template>
<script>
import UiButton from '@/components/UiButton.vue'
export default {
components: { UiButton }
}
</script>
<style lang="scss" scoped>
page{
text-align: center;
}
.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;
}
.btn{
margin-top: 74rpx;
}
</style>

@ -2,15 +2,15 @@
* @Author: ch
* @Date: 2022-04-28 15:01:41
* @LastEditors: ch
* @LastEditTime: 2022-04-28 15:46:19
* @LastEditTime: 2022-04-29 14:46:23
* @Description: file content
-->
<template>
<view>
<view class="main">
<template v-if="!orderInfo">
<view class="title">交易中</view>
<view class="desc">正在交易中,请您耐心等待...</view>
<view class="title title--await">结果查询中</view>
<view class="desc">正在与支付渠道确认支付结果,请您耐心等待...</view>
</template>
<template v-else>
<template v-if="orderInfo.isSuccess">
@ -28,16 +28,19 @@
<image class="icon" src="@/static/order/payFail.png"/>
<view class="title">支付失败</view>
<view class="desc">请重新试试</view>
<view class="btns">
<UiButton class="btn">返回商品详情</UiButton>
</view>
</template>
</template>
</view>
</template>
<script>
import UiButton from '@/components/UiButton.vue';
import BsChoiceGoods from '@/components/BsChoiceGoods.vue';
import {ApiGetOrderPaySatus} from '@/common/api/order';
export default {
components: { UiButton },
components: { UiButton, BsChoiceGoods },
data(){
return {
orderInfo : '',
@ -72,6 +75,9 @@ export default {
page{
text-align: center;
}
.main{
text-align: center;
}
.icon{
width: 400rpx;
height: 256rpx;
@ -81,6 +87,10 @@ page{
font-size: $font-size-lg;
line-height: 44rpx;
color: $color-grey6;
&--await{
margin: 100rpx 0 20rpx;
color: $color-grey5;
}
}
.desc{
font-size: $font-size-sm;

@ -1,75 +0,0 @@
<!--
* @Author: ch
* @Date: 2022-03-28 17:16:44
* @LastEditors: ch
* @LastEditTime: 2022-04-19 18:06:43
* @Description: file content
-->
<template>
<view>
<image class="icon" src="@/static/order/paySuccess.png"/>
<view class="title">支付成功</view>
<view class="desc">您的包裹整装待发</view>
<view class="btns">
<UiButton class="btn" type="primaryLine" @click="$Router.replaceAll('/')">返回首页</UiButton>
<UiButton class="btn" type="solid" @click="$Router.replace(`/orderDetail?id=${$Route.query.ordId}`)">查看订单</UiButton>
</view>
<view class="recommend-title">为您推荐</view>
<BsChoiceGoods></BsChoiceGoods>
</view>
</template>
<script>
import UiButton from '@/components/UiButton.vue'
export default {
components: { UiButton },
}
</script>
<style lang="scss" scoped>
page{
text-align: center;
}
.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: 2022-03-20 14:14:53
* @LastEditors: ch
* @LastEditTime: 2022-04-28 19:07:16
* @LastEditTime: 2022-04-29 14:56:02
* @Description: file content
-->
<template>
@ -22,21 +22,10 @@
</UiWhiteBox>
<view class="goods-group">
<view class="goods-group--item" v-for="item in orderInfo.products" :key="item.productId">
<image class="goods-group--item-image" mode="widthFix" :src="item.productImageUrl" />
<view >
<view class="goods-group--item-con">
<text class="goods-group--item-title">{{item.productName}}</text>
<text class="goods-group--item-pirce">¥{{item.productPrice}}</text>
</view>
<view class="goods-group--item-desc">
<text>{{item.skuDescribe}}</text>
<text class="goods-group--item-num">x{{item.quantity}}</text>
</view>
</view>
</view>
</view>
<UiWhiteBox >
<ui-goods-info v-for="item in orderInfo.products"
:key="item.productId" :data="item" ></ui-goods-info>
</UiWhiteBox>
<UiWhiteBox>
<UiCell class="service--cell" title="配送方式" value="快递配送" :rightIcon="false"></UiCell>
@ -81,11 +70,12 @@
<script>
import UiCell from '@/components/UiCell';
import {ApiPostSubmitOrder, ApiGetBeforeOrder, ApiGetBeforeCartOrder} from '@/common/api/order';
import { ApiPostWxH5Pay, ApiPostWxJsApiPay } from '@/common/api/wx';
import {Wxpay} from '@/common/utils';
import UiButton from '@/components/UiButton.vue';
import UiWhiteBox from '../../components/UiWhiteBox.vue';
import UiGoodsInfo from '../../components/UiGoodsInfo.vue';
export default {
components : {UiCell, UiButton, UiWhiteBox },
components : {UiCell, UiButton, UiWhiteBox, UiGoodsInfo },
data(){
return {
address : {},
@ -174,58 +164,10 @@ export default {
return false;
}
if(this.payType === 'wxpay'){
this.wxpay(result.orderId);
Wxpay(result.orderId, this.$store.state.openId);
}else{
uni.$u.toast('暂不支持支付宝支付');
}
},
async wxpay(orderId){
const openId = this.$store.state.openId;
if(openId) {
// 微信JSAPI
const {error, result} = await ApiPostWxJsApiPay({orderId,openId});
if(error){
uni.$u.toast(error.message);
return false;
}
/*
* 公众号id appId 是 String(16) wx8888888888888888
时间戳 timeStamp 是 String(32) 1414561699 当前的时间
随机字符串 nonceStr 是 String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 随机字符串,不长于32位。推荐随机数生成算法
订单详情扩展字符串 package 是 String(128) prepay_id=123456789 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
签名方式 signType 是 String(32) MD5 签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致
签名 paySign 是 String(64) C380BEC2BFD727A4B6845133519F3AD6 签名
*/
const par = result.dataInfo;
console.log(result);
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":"wx2421b1c4370ec43b",
timeStamp : par.timeStamp,
nonceStr : par.nonceStr,
package : par.packageValue,
signType : par.signType,
paySign : par.paySign
}, res => {
if(res.err_msg === 'get_brand_wcpay_request:cancel'){
this.$$Router.replace(`/payResult?orderId=${orderId}`);
}else{
this.$$Router.replace(`/orderDetail?id=${orderId}`);
}
})
}else{
// h5支付
const {error, result} = await ApiPostWxH5Pay({orderId});
if(error){
uni.$u.toast(error.message);
return false;
}
const redirect_url = decodeURIComponent(`https://like-app.mashibing.com/payResult?orderId=${orderId}`);
window.location.href = `${result.dataInfo.payUrl}&redirect_url=${redirect_url}`;
}
}
}
}

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-21 18:08:07
* @LastEditors: ch
* @LastEditTime: 2022-04-25 10:43:11
* @LastEditTime: 2022-04-27 10:47:46
* @Description: file content
-->
<template>
@ -42,7 +42,6 @@
</view>
</view>
<u-loadmore :status="loadingStatus" color="#FF8384" iconColor="#FF8384" nomoreText="我也是有底线的啦~"/>
</view>
</template>
<script>

Loading…
Cancel
Save