Commit 9b217226 authored by Junling Bu's avatar Junling Bu
Browse files

Merge branch 'litemall-vue' of https://github.com/pkwenda/litemall into pkwenda-litemall-vue

parents 3cb559bb ce4ef458
@mixin one-border($direction: bottom){
position: relative;
&::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 200%;
height: 200%;
transform: scale(.5);
transform-origin: 0 0;
pointer-events: none;
box-sizing: border-box;
border-#{$direction}: 1px solid $border-color;
}
}
\ No newline at end of file
@keyframes lds-ball {
0%, 100% {
animation-timing-function: cubic-bezier(0.45, 0, 0.9, 0.55);
}
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
50% {
-webkit-transform: translate(0, 108px);
transform: translate(0, 108px);
animation-timing-function: cubic-bezier(0, 0.45, 0.55, 0.9);
}
100% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
}
@-webkit-keyframes lds-ball {
0%, 100% {
animation-timing-function: cubic-bezier(0.45, 0, 0.9, 0.55);
}
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
50% {
-webkit-transform: translate(0, 108px);
transform: translate(0, 108px);
animation-timing-function: cubic-bezier(0, 0.45, 0.55, 0.9);
}
100% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
}
.lds-ball {
position: relative;
}
.lds-ball div {
width: 52px;
height: 52px;
border-radius: 50%;
background: #e15b64;
-webkit-animation: lds-ball 1s linear infinite;
animation: lds-ball 1s linear infinite;
}
.lds-ball {
position: fixed;
left: 50%;
top: 30%;
transform: translateX(-50%);
}
\ No newline at end of file
// 使用这个会导致组件内部的 router 导航守卫无法使用, 慎用
/**
* @param { string } chunkPath views 文件夹下的页面路径
* @return { function } 返回 promise<component> 的匿名函数
*/
import spinner from '@/vue/components/spinner';
export default chunkPath => {
const AsyncHandler = () => ({
component: new Promise(resolve => {
setTimeout(() => {
resolve(
import(/* webpackChunkName: "[request]" */ `@/views/${chunkPath}`)
);
}, 1000);
}),
loading: spinner,
error: {
render(h) {
return h('div', {}, ['异步组件加载失败']);
}
},
timeout: 10000
});
return () =>
Promise.resolve({
functional: true,
render(h, { data, children }) {
return h(AsyncHandler, data, children);
}
});
};
export const idCard = /^[1-9]{1}[0-9]{14}$|^[1-9]{1}[0-9]{16}([0-9]|[xX])$/;
export const mobileReg = /^1[0-9]{10}$/;
export const address = val => {
const value = val.trim();
return value.length >= 5 && value.length <= 100;
};
export const userName = /^[a-zA-Z0-9_\u4e00-\u9fa5]{3,20}$/;
export const emailReg = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;
import docCookie from '@/core/utils/cookies'
import { setLocalStorage, getLocalStorage } from '@/core/utils/local-storage';
export function procJumpToken() {
if (docCookie.getItem('litetoken')) {
let litetoken = docCookie.getItem('litetoken')
if (!PSMU.isEmtVal(litetoken)) {
let jsonStr = PSMU.DU(litetoken)
console.log("jsonStr is : ", jsonStr);
if (!PSMU.isEmt(jsonStr) && PSMU.isString(jsonStr)) {
let tokenInfo = JSON.parse(jsonStr)
console.log("tokenInfo is : ", tokenInfo);
if (tokenInfo && tokenInfo.token) {
setLocalStorage({
Authorization: tokenInfo.token
});
}
const infoData = getLocalStorage(
'Authorization'
)
console.log("procJumpToken getLocalStorage ", infoData);
if (tokenInfo && tokenInfo.userInfo) {
// debugger
setLocalStorage({
avatar: tokenInfo.userInfo.avatarUrl,
// user_id: data.user_id,
// background_image: data.background_image,
nickName: tokenInfo.userInfo.nickName
});
}
const infoData2 = getLocalStorage(
'avatarUrl',
'nickName'
)
console.log("procJumpToken getLocalStorage 2 ", infoData2);
}
}
docCookie.removeItem('litetoken')
}
}
/*\
|*|
|*| :: cookies.js ::
|*|
|*| A complete cookies reader/writer framework with full unicode support.
|*|
|*| https://developer.mozilla.org/en-US/docs/DOM/document.cookie
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntaxes:
|*|
|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
|*| * docCookies.getItem(name)
|*| * docCookies.removeItem(name[, path], domain)
|*| * docCookies.hasItem(name)
|*| * docCookies.keys()
|*|
\*/
const docCookies = {
getItem: function (sKey) {
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
},
setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
var sExpires = "";
if (vEnd) {
switch (vEnd.constructor) {
case Number:
sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
break;
case String:
sExpires = "; expires=" + vEnd;
break;
case Date:
sExpires = "; expires=" + vEnd.toUTCString();
break;
}
}
document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
return true;
},
removeItem: function (sKey, sPath, sDomain) {
if (!sKey || !this.hasItem(sKey)) { return false; }
document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + ( sDomain ? "; domain=" + sDomain : "") + ( sPath ? "; path=" + sPath : "");
return true;
},
hasItem: function (sKey) {
return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
},
keys: /* optional method: you can safely remove it! */ function () {
var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
return aKeys;
}
};
export default docCookies
export const getLocalStorage = (...args) => {
const storage = {};
args.forEach(arg => {
storage[arg] = window.localStorage.getItem(arg) || null;
});
return storage;
};
export const setLocalStorage = data => {
Object.keys(data).forEach(prop => {
const el = data[prop];
window.localStorage.setItem(prop, el);
});
};
export const removeLocalStorage = (...args) => {
args.forEach(arg => {
window.localStorage.removeItem(arg);
});
};
export default name => {
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`);
const r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURIComponent(r[2]);
return '';
};
const protobuf = require("protobufjs");
/*尽量保持业务无关 业务相关放chatinfo.js中*/
if (!window.PSMU) {
var PSMU = {
validChars: /^[\],:{}\s]*$/,
validEscape: /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
validTokens: /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
validBraces: /(?:^|:|,)(?:\s*\[)+/g,
htmlRegArr: [],
SERV_LOG_INTERVAL: 30 * 1000,
servLogId: false,
servLogMap: {},
tokenName: 'Authorization',
tuid: 'false',
tuidCounter: 0,
isUptuid: false,
uptuidDefaultVal: 9960,
maxtuidval: 9999,
// Base64 encoding table
b64: new Array(64),
// Base64 decoding table
s64: new Array(123),
/*目前全局变量及状态保存到 psm中 组件数据通信频繁的可以放vuex中
* 尽量不依赖vue 增加额外复杂性 */
REV_MSG: 'REV_MSG',
/*接收消息*/
REV_ROOM_MSG: 'REV_ROOM_MSG',
/*接收房态消息*/
REV_HIS_MSG: 'REV_HIS_MSG',
/*接收历史消息*/
LOAD_HIS_MSG_END: 'LOAD_HIS_MSG_END',
/*加载历史消息结束*/
SELF_MSG: 'SELF_MSG',
/*发出消息*/
RESEND_MSG: 'RESEND_MSG',
/*重发消息*/
CHAT_NET_ERR_MSG: 'CHAT_NET_ERR_MSG',
/*网络异常消息发送失败*/
OUT_CHAT_PAGE_MSG: 'OUT_CHAT_PAGE_MSG',
/*离开聊天页面*/
IN_CHAT_PAGE_MSG: 'IN_CHAT_PAGE_MSG',
/*进入聊天页面*/
LOGIN_SUCC: 'LOGIN_SUCC',
/*登录成功*/
LOGIN_FAILED: 'LOGIN_FAILED',
/*登录失败*/
CODE_ZU: 'ZU',
CODE_ZP: 'ZP',
codeType: false,
setup: function () {
PSMU.codeType = PSMU.CODE_ZP;
// 65..90, 97..122, 48..57, 43, 47
for (var i = 0; i < 64;)
PSMU.s64[PSMU.b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;
},
isEmt: function (value, allowBlank) {
if (PSMU.isNotDef(value)) {
return true;
}
return value === null || value === undefined || /*((PSMU.isArr(value) && !value.length)) ||*/ (!allowBlank ? value === '' : false) || value === "undefined";
},
isEmtVal: function (value) {
if (PSMU.isNotDef(value)) {
return true;
}
return value === null || value === 'null' || (typeof (value) === 'string' && (value === "undefined" || value === '' || PSMU.trim(value) === '')) || (typeof (value) === 'boolean' && value === false);
},
isNotDef: function (value) {
return typeof (value) === "undefined";
},
isArr: function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
},
isString: function (obj) {
return Object.prototype.toString.call(obj) === '[object String]';
},
isDate: function (obj) {
return Object.prototype.toString.call(obj) === '[object Date]';
},
isNum: function (num) {
return (typeof (num) === "number") && (num !== Infinity) && !isNaN(num);
},
isNotEmtArr: function (o) {
return PSMU.isArr(o) && typeof (o.length) && o.length > 0;
},
trim: function (value) {
return value.replace(/^\s*/, "").replace(/\s*$/, "");
},
setBuffer: function (ret, val) {
if (PSMU.isEmt(ret[ret.len])) {
ret[ret.len] = protobuf.util.newBuffer(100);
}
if (ret.offset + 1 >= ret.len * 100 + 100) {
ret[++ret.len] = protobuf.util.newBuffer(100);
}
var len = parseInt(ret.offset / 100);
var pos = ret.offset % 100;
ret[len][pos] = val;
return ++ret.offset;
},
base64Decode: function (string, /*buffer,*/ offset) {
var ret = {
len: 0,
offset: offset
};
// var start = offset;
var j = 0, // goto index
t; // temporary
for (var i = 0; i < string.length;) {
var c = string.charCodeAt(i++);
if (c === 61 && j > 1)
break;
if ((c = PSMU.s64[c]) === undefined)
throw Error("invalid encoding");
switch (j) {
case 0:
t = c;
j = 1;
break;
case 1:
PSMU.setBuffer(ret, t << 2 | (c & 48) >> 4);
// buffer[offset++] = t << 2 | (c & 48) >> 4;
t = c;
j = 2;
break;
case 2:
PSMU.setBuffer(ret, (t & 15) << 4 | (c & 60) >> 2);
// buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
t = c;
j = 3;
break;
case 3:
PSMU.setBuffer(ret, (t & 3) << 6 | c);
// buffer[offset++] = (t & 3) << 6 | c;
j = 0;
break;
}
}
if (j === 1)
throw Error("invalid encoding");
if (ret.offset > 0) {
var buf = protobuf.util.newBuffer(ret.offset);
for (var i = 0; i < ret.offset; i++) {
var len = parseInt(i / 100);
var pos = i % 100;
buf[i] = ret[len][pos];
}
return buf;
}
return null;
// return offset - start;
},
base64Encode: function (buffer, start, end) {
var parts = null,
chunk = [];
var i = 0, // output index
j = 0, // goto index
t; // temporary
while (start < end) {
var b = buffer[start++];
switch (j) {
case 0:
chunk[i++] = PSMU.b64[b >> 2];
t = (b & 3) << 4;
j = 1;
break;
case 1:
chunk[i++] = PSMU.b64[t | b >> 4];
t = (b & 15) << 2;
j = 2;
break;
case 2:
chunk[i++] = PSMU.b64[t | b >> 6];
chunk[i++] = PSMU.b64[b & 63];
j = 0;
break;
}
if (i > 8191) {
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
i = 0;
}
}
if (j) {
chunk[i++] = PSMU.b64[t];
chunk[i++] = 61;
if (j === 1)
chunk[i++] = 61;
}
if (parts) {
if (i)
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
return parts.join("");
}
return String.fromCharCode.apply(String, chunk.slice(0, i));
},
/*TODO*/
DU: function (str) {
if (!PSMU.IS_DU(str)) {
return PSMU.DP(str)
}
str = str.replace(/(2_3)(\w{4}|\w{2})/gi, function ($0, $1, $2) {
return String.fromCharCode(parseInt($2, 16));
});
return str;
},
EU: function (str) {
return str.replace(/([\u0000-\uFFFF])/g, function ($0) {
try {
var char16tmp = parseInt($0.charCodeAt().toString(16), 16);
if (char16tmp >= 0x2002 && char16tmp <= 0x200d) {
return "";
}
} catch (e) {
return "";
}
if ($0.charCodeAt() <= 16) {
return '2_3000' + $0.charCodeAt().toString(16);
} else if ($0.charCodeAt() < 256) {
return '2_300' + $0.charCodeAt().toString(16);
} else {
return '2_3' + $0.charCodeAt().toString(16);
}
});
},
IS_DU: function (str) {
return str.indexOf('2_3') == 0
},
EP: function (json) {
if (PSMU.isEmtVal(json)) {
return "";
}
var root = protobuf.Root.fromJSON(protobuf.common.get('google/protobuf/struct.proto'));
var StructMessage = root.lookupType("google.protobuf.Struct");
var postDataConverted = PSMU.json2Struct(json);
var message = StructMessage.fromObject(postDataConverted);
var buf = StructMessage.encode(message).finish();
// this.bufLen=buf.length;
return PSMU.base64Encode(buf, 0, buf.length);
},
DP: function (str) {
if (PSMU.isEmtVal(str)) {
return "";
}
if (PSMU.IS_DU(str)) {
return PSMU.DU(str);
}
// var buf = protobuf.util.newBuffer(protobuf.util.base64.length(str));
// var buf = protobuf.util.newBuffer(this.bufLen);
var buf = PSMU.base64Decode(str, /*buf,*/ 0);
var root = protobuf.Root.fromJSON(protobuf.common.get('google/protobuf/struct.proto'));
var StructMessage = root.lookupType("google.protobuf.Struct");
var message2 = StructMessage.decode(buf);
var struct = StructMessage.toObject(message2, protobuf.util.toJSONOptions);
return PSMU.struct2Json(struct);
},
struct2Json: function (structObj) {
var jsonObj = {};
var jsonObjTmp = {};
if (typeof structObj.fields === 'object') {
jsonObjTmp = structObj.fields;
}
Object.keys(jsonObjTmp).forEach(function (field) {
var fieldObj = jsonObjTmp[field];
var fieldType = Object.keys(fieldObj)[0];
switch (fieldType) {
case 'nullValue':
// do nothing
break;
case 'numberValue':
case 'stringValue':
case 'boolValue':
jsonObj[field] = fieldObj[fieldType];
break;
case 'structValue':
jsonObj[field] = PSMU.struct2Json(fieldObj[fieldType]);
break;
case 'listValue':
jsonObj[field] = PSMU.list2Json(fieldObj[fieldType]);
break;
}
});
return jsonObj;
},
list2Json: function (listObj) {
var jsonArray = [];
var jsonArrayTmp = [];
if (PSMU.isArr(listObj.values)) {
jsonArrayTmp = listObj.values;
}
jsonArrayTmp.forEach(function (itemObj) {
var fieldType = Object.keys(itemObj)[0];
switch (fieldType) {
case 'nullValue':
// do nothing
break;
case 'numberValue':
case 'stringValue':
case 'boolValue':
jsonArray.push(itemObj[fieldType]);
break;
case 'structValue':
jsonArray.push(PSMU.struct2Json(itemObj[fieldType]));
break;
case 'listValue':
jsonArray.push(PSMU.list2Json(itemObj[fieldType]));
break;
}
});
return jsonArray;
},
json2Struct: function (jsonObj) {
var structObj = {};
var structObjTmp = {};
if (typeof jsonObj === 'object') {
structObjTmp = jsonObj;
}
Object.keys(structObjTmp).forEach(function (field) {
var value = structObjTmp[field];
switch (typeof (value)) {
case 'number':
structObj[field] = {
numberValue: value
};
break;
case 'string':
structObj[field] = {
stringValue: value
};
break;
case 'boolean':
structObj[field] = {
boolValue: value
};
break;
case 'object':
// null
if (!value) break;
if (value.constructor === Object) {
structObj[field] = {
structValue: PSMU.json2Struct(value)
};
} else if (value.constructor === Array) {
structObj[field] = {
listValue: PSMU.json2List(value)
};
}
break;
}
});
return {
fields: structObj
};
},
json2List: function (jsonArray) {
var listObj = [];
var listObjTmp = [];
if (PSMU.isArr(jsonArray)) {
listObjTmp = jsonArray;
}
listObjTmp.forEach(function (jsonObj) {
switch (typeof (jsonObj)) {
case 'number':
listObj.push({
numberValue: jsonObj
});
break;
case 'string':
listObj.push({
stringValue: jsonObj
});
break;
case 'boolean':
listObj.push({
boolValue: jsonObj
});
break;
case 'object':
// null
if (!jsonObj) break;
if (jsonObj.constructor === Object) {
listObj.push({
structValue: PSMU.json2Struct(jsonObj)
});
} else if (jsonObj.constructor === Array) {
listObj.push({
listValue: PSMU.json2List(jsonObj)
});
}
break;
}
});
return {
values: listObj
};
},
escapeText: function (text) {
return (text) ? window.escape(text) : '';
},
unescapeText: function (text) {
return (text) ? window.unescape(text) : '';
}
}
window.PSMU = PSMU;
}
var psmu = window.PSMU;
export default {
psmu
}
// import axios from 'axios'
// import { Message, MessageBox } from 'element-ui'
// import store from '@/store'
// import { getToken } from '@/utils/auth'
// // create an axios instance
// const service = axios.create({
// baseURL: process.env.BASE_API, // api 的 base_url
// timeout: 5000 // request timeout
// })
// // request interceptor
// service.interceptors.request.use(
// config => {
// // Do something before request is sent
// if (store.getters.token) {
// // 让每个请求携带token-- ['X-Litemall-Admin-Token']为自定义key 请根据实际情况自行修改
// config.headers['X-Litemall-Admin-Token'] = getToken()
// }
// return config
// },
// error => {
// // Do something with request error
// console.log(error) // for debug
// Promise.reject(error)
// }
// )
// // response interceptor
// service.interceptors.response.use(
// response => {
// const res = response.data
// if (res.errno === 501) {
// MessageBox.alert('系统未登录,请重新登录', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// }).then(() => {
// store.dispatch('FedLogOut').then(() => {
// location.reload()
// })
// })
// return Promise.reject('error')
// } else if (res.errno === 502) {
// MessageBox.alert('系统内部错误,请联系管理员维护', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 503) {
// MessageBox.alert('请求业务目前未支持', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 504) {
// MessageBox.alert('更新数据已经失效,请刷新页面重新操作', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 505) {
// MessageBox.alert('更新失败,请再尝试一次', '警告', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno === 506) {
// MessageBox.alert('没有操作权限,请联系管理员授权', '错误', {
// confirmButtonText: '确定',
// type: 'error'
// })
// return Promise.reject('error')
// } else if (res.errno !== 0) {
// // 非5xx的错误属于业务错误,留给具体页面处理
// return Promise.reject(response)
// } else {
// return response
// }
// }, error => {
// console.log('err' + error)// for debug
// Message({
// message: '登录连接超时(后台不能连接,请联系系统管理员)',
// type: 'error',
// duration: 5 * 1000
// })
// return Promise.reject(error)
// })
// export default service
export default {
isAttached(element) {
let currentNode = element.parentNode;
while (currentNode) {
if (currentNode.tagName === 'HTML') {
return true;
}
if (currentNode.nodeType === 11) {
return false;
}
currentNode = currentNode.parentNode;
}
return false;
},
getScrollLeft(element) {
return 'scrollLeft' in element ? element.scrollLeft : element.pageXOffset;
},
getVisibleHeight(element) {
return element === window
? element.innerHeight
: element.getBoundingClientRect().height;
},
getVisibleWidth(element) {
return element === window
? element.innerWidth
: element.getBoundingClientRect().width;
}
};
import Vue from 'vue';
import App from './App.vue';
import router from './vue/router';
import './assets/scss/global.scss';
import '@/assets/scss/iconfont/iconfont.css';
import VeeValidate, { Validator } from 'vee-validate';
import VueCountdown from '@/vue/plugins/vue-countdown';
import zhCN from 'vee-validate/dist/locale/zh_CN';
import axios from '@/vue/plugins/axios';
import filters from '@/vue/filter';
import psm from '@/core/utils/psm'
import {
procJumpToken
} from "@/core/utils/auth";
Vue.use(VueCountdown);
Vue.use(axios);
Vue.use(filters);
Validator.localize('zh-CN', zhCN);
Vue.use(VeeValidate, {
locale: 'zh-CN'
});
import { Lazyload, Icon, Cell, CellGroup, loading, Button, Toast } from 'vant';
Vue.use(Icon);
Vue.use(Cell);
Vue.use(CellGroup);
Vue.use(loading);
Vue.use(Button);
Vue.use(Toast);
Vue.use(Lazyload, {
preLoad: 1.3,
error: require('@/assets/images/goods_default.png'),
loading: require('@/assets/images/goods_default.png'),
attempt: 1,
listenEvents: ['scroll'],
lazyComponent: true
});
Vue.prototype.PSMU = psm.psmu
PSMU.setup()
procJumpToken()
Vue.config.productionTip = false;
new Vue({
router,
render: h => h(App)
}).$mount('#app');
<template>
<van-cell-group>
<van-cell>
<van-notice-bar
:text="notice"
background="white"
:leftIcon="trumpet"
style="padding-left: 0"
/>
</van-cell>
<van-cell :title="address" icon="dingwei" isLink :url="mapSrc"></van-cell>
<van-cell icon="phone" isLink>
<template slot="title">
<a :href="'tel:' + mobile" class="store_mobile">{{mobile}}</a>
</template>
</van-cell>
</van-cell-group>
</template>
<script>
import { NoticeBar } from 'vant';
import trumpet from '@/assets/images/trumpet.png';
export default {
name: 'shop-info-group',
props: {
address: {
type: String,
required: true
},
mobile: {
type: String,
required: true
},
notice: {
type: String,
default: ''
},
location: Object
},
data() {
const { location } = this;
const MAP_PATH = `http://m.amap.com/navi/?dest=${location.lat},${
location.lng
}&key=ab67b14d58d47912a9feb63ba862450c&destName=${location.name}`;
return {
trumpet,
mapSrc: location ? MAP_PATH : '#'
};
},
created() {},
components: {
[NoticeBar.name]: NoticeBar
}
};
</script>
<style lang="scss" scoped>
.store_mobile {
color: #0000a0;
text-decoration: underline;
}
</style>
<template>
<div class="signboard">
<img :src="boardUrl" :height="signboardHeight" width="100%">
<div class="store_opacity clearfix">
<div class="float-l">{{storeName}}</div>
<div class="float-r store_collect isCollect" @click="showCollect = true">
<van-icon name="shoucang-full" />
<span>收藏</span>
</div>
</div>
<van-popup v-model="showCollect" position="top" style="background-color: transparent">
<img :src="showCollect && collectImg" @click="showCollect = false" width="100%" alt="右上角收藏">
</van-popup>
</div>
</template>
<script>
import { Popup } from 'vant';
import collectImg from '@/assets/images/index_collect.png';
export default {
name: 'sign-board',
props: {
boardUrl: {
type: String,
required: true
},
storeName: {
type: String,
required: true
}
},
data() {
const clientW =
document.body.clientWidth || document.documentElement.clientWidth;
const signboardHeight = clientW ? (clientW * 2) / 3 : 250;
return {
signboardHeight,
showCollect: false,
collectImg
};
},
components: {
[Popup.name]: Popup
}
};
</script>
<style lang="scss" scoped>
.signboard {
position: relative;
min-height: 250px;
}
.store_opacity {
position: absolute;
bottom: 0;
color: #fff;
width: 100%;
background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 1));
padding: 15px 10px;
box-sizing: border-box;
}
.isCollect i {
color: $red;
}
</style>
<template>
<div class="tab_home">
<div class="tal_class_searchBox">
<van-search placeholder="点击前往搜索" @click="$router.push({ name: 'search' })"/>
<div class="tal_class_searchMask"></div>
</div>
<van-swipe :autoplay="3000" indicator-color="white">
<van-swipe-item v-for="(image, index) in brandList" :key="index">
<img :src="image" style="height:230px">
</van-swipe-item>
</van-swipe>
<van-tabbar active-color="#7d7e80" v-model="active" class="goods-channel">
<van-tabbar-item
@click="changeTabbar(iconJson)"
style="font-size:14px"
v-if="index < 5"
v-for="(iconJson, index) in shopInfos.channel"
:key="index"
:icon="iconJson.iconUrl"
>{{iconJson.name}}</van-tabbar-item>
</van-tabbar>
<van-tabbar active-color="#7d7e80" v-model="active" class="goods-channel">
<van-tabbar-item
@click="changeTabbar(iconJson)"
style="font-size:14px"
v-if="index >= 5"
v-for="(iconJson, index) in shopInfos.channel"
:key="index"
:icon="iconJson.iconUrl"
>{{iconJson.name}}</van-tabbar-item>
<van-tabbar-item></van-tabbar-item>
</van-tabbar>
<!-- <van-panel title="优惠券" style=" padding-bottom: 10px;">
<div
class="van-coupon-item"
v-for="(coupon,index) in shopInfos.couponList"
:key="index"
@click="getCoupon(coupon.id)"
>
<div class="van-coupon-item__content">
<div class="van-coupon-item__head">
<h2>
<span>¥</span>
{{coupon.discount}}
</h2>
<p>{{coupon.desc }} - {{coupon.tag}}</p>
</div>
<div class="van-coupon-item__body">
<h2>{{coupon.name}}</h2>
<p>有效期:{{coupon.days}}</p>
</div>
</div>
</div>
</van-panel>-->
<van-panel title="团购专区">
<!-- {{shopInfos.grouponList}} -->
<van-card
:thumb-link="goDetail(groupGood.goods.id)"
v-for="(groupGood ,index) in shopInfos.grouponList"
:key="index"
:title="groupGood.goods.name"
:desc="groupGood.goods.brief"
:num="groupGood.groupon_member"
:origin-price="groupGood.goods.counterPrice"
:price="groupGood.goods.retailPrice +'.00'"
:thumb="groupGood.goods.picUrl"
@native-click="goDetail(groupGood.goods.id)"
>
<!-- <div slot="footer">添加日期 {{item.addTime}}</div> -->
</van-card>
</van-panel>
<van-panel title="新品首发">
<!-- {{shopInfos.grouponList}} -->
<van-row gutter>
<van-col span="12" v-for="(newGood ,index) in shopInfos.newGoodsList" :key="index">
<router-link :to="{ path: `/items/detail/${newGood.id}`}">
<img :src="newGood.picUrl" style="width:180px;height:180px;">
</router-link>
<span
style="padding-left: 20px;position: relative;bottom: 10px; color: rgb(123, 116, 116);white-space: nowrap;"
>{{newGood.name}}</span>
<span
style="padding-left: 80px;position: relative;bottom: 10px; color:#ab956d"
>{{newGood.retailPrice}}</span>
</van-col>
</van-row>
</van-panel>
<van-panel title="人气推荐">
<!-- {{shopInfos.grouponList}} -->
<van-card
:thumb-link="goDetail(groupGood.id)"
v-for="(groupGood ,index) in shopInfos.hotGoodsList"
:key="index"
:title="groupGood.name"
:desc="groupGood.brief"
:origin-price="groupGood.counterPrice"
:price="groupGood.retailPrice +'.00'"
:thumb="groupGood.picUrl"
@native-click="goDetail(groupGood.id)"
>
<!-- <div slot="footer">添加日期 {{item.addTime}}</div> -->
</van-card>
</van-panel>
<!-- <van-list
v-model="loading"
class="scroll-load"
:finished="finished"
:immediate-check="false"
:offset="100"
@load="loadMore"
>
<item-group
v-for="( group, key ) in itemGroup"
v-if="group"
:key="key"
class="interval_bot"
:setting="group.setting"
>
<component
v-for="item in group.items"
:goods="item"
:key="item.id"
:is="getStyle(group.setting.style)"
@click="toGoods(item)"
>
<div slot="mask" v-if="lootAll(item)">
<img src="../../assets/images/not_enough.png" alt="已抢光">
</div>
<div slot="leftTopIcon" v-if="item.as_status < 2">
<img :src="mxStatus(item.as_status)" alt="秒杀">
</div>
</component>
</item-group>
</van-list>-->
</div>
</template>
<script>
import { HOME_module, ALL_GOODS } from '@/api/shop';
import getLocationParam from 'core/utils/location-param';
import mx_be_to from '@/assets/images/mx_be_to.png';
import mx_start from '@/assets/images/mx_start.png';
import SignBoard from './tabbar-home-sign-board';
import ShopInfoGroup from './tabbar-home-shop-info';
import ItemGroup from '@/vue/components/item-group/';
import ItemCardVert from '@/vue/components/item-card-vert/';
import ItemCardHori from '@/vue/components/item-card-hori/';
import loadMore from '@/vue/mixin/list-load-more';
import scrollFixed from '@/vue/mixin/scroll-fixed';
import _ from 'lodash';
const coupon = {
available: 1,
discount: 0,
denominations: 150,
originCondition: 0,
reason: '',
value: 150,
name: '优惠券名称',
startAt: 1489104000,
endAt: 1514592000
};
import {
List,
Swipe,
SwipeItem,
Tabbar,
TabbarItem,
Search,
Panel,
CouponCell,
CouponList,
Toast,
Card,
Row,
Col
} from 'vant';
export default {
mixins: [loadMore, scrollFixed],
data() {
const shop_id = getLocationParam('shop_id');
return {
shop_id,
brandList: [],
shopInfos: [],
shopInfo: null,
coupons: [coupon],
itemGroup: {
mx_goods: null,
activity_seckill: null,
shop_recommend: null,
goods: null
},
mx_be_to,
mx_start,
isLoading: false
};
},
computed: {
location() {
const shopInfo = this.shopInfo;
const local = {
name: shopInfo.shop_name,
lat: shopInfo.lat,
lng: shopInfo.lng
};
return local.lat && local.lng ? local : null;
}
},
created() {
// this.initViews();
this.initNewViews();
},
methods: {
goDetail(id) {
return `#/items/detail/${id}`;
},
async getCoupon(id) {
let errmsg = await this.$reqPost('/wx/coupon/receive', {
couponId: id
});
Toast.success('领取成功');
},
async changeTabbar(o) {
let { data } = await this.$reqGet(
`/wx/goods/category?id=${o.id}`
);
let categoryId = data.data.currentCategory.id;
this.$router.push({
path: `items/list?keyword=&itemClass=${categoryId}`
});
},
initViews() {
this.$reqGet(HOME_module, {
shop_id: this.shop_id,
'per-page': this.pages.perPage,
page: 1
}).then(res => {
const { shop_info, page } = res.data.data;
const {
mx_goods,
shop_recommend,
activity_seckill,
goods
} = this.decorate(res.data.data);
this.shopInfo = shop_info;
this.itemGroup.mx_goods = mx_goods;
this.itemGroup.shop_recommend = shop_recommend;
this.itemGroup.activity_seckill = activity_seckill;
this.itemGroup.goods = goods;
this.setPages(page);
});
},
initNewViews() {
this.$reqGet('/wx/home/index').then(res => {
this.shopInfos = res.data.data;
this.brandList = [];
_.each(res.data.data.brandList, v => {
this.brandList.push(v.picUrl);
});
});
},
initData() {
// return this.$reqGet(ALL_GOODS, {
// shop_id: this.shop_id,
// 'per-page': this.pages.perPage,
// page: this.pages.currPage
// }).then(res => {
// const { items, page } = res.data.data;
// this.itemGroup.goods && this.itemGroup.goods.items.push(...items);
// return page;
// });
},
toGoods(item) {
// 如果是秒杀商品, 并且已经抢光
if (this.lootAll(item)) {
this.$dialog.alert({ message: '该秒杀商品已抢光,看看别的吧!' });
return;
}
this.$router.push({ path: `/items/detail/${item.id}` });
},
groupIcon(key) {
const iconGroup = {
activity_seckill: 'naozhong',
goods: 'list',
mx_goods: 'n4',
shop_recommend: 'good'
};
return iconGroup[key] || '';
},
getStyle(style) {
return style ? 'item-card-vert' : 'item-card-hori';
},
decorate({ mx_goods, shop_recommend, activity_seckill, goods }) {
if (mx_goods) {
mx_goods.setting.icon = 'n4';
mx_goods.setting.title_desc = '分享得金豆';
mx_goods.setting.title_color = '#db3d3c';
mx_goods.setting.item_len = mx_goods.items.length;
}
if (shop_recommend) {
shop_recommend.setting.icon = 'good';
shop_recommend.setting.item_len = shop_recommend.items.length;
}
if (activity_seckill) {
activity_seckill.setting.icon = 'naozhong';
activity_seckill.setting.title_color = '#db3d3c';
activity_seckill.setting.item_len = activity_seckill.items.length;
}
if (goods) {
goods.setting.icon = 'list';
goods.setting.item_len = goods.items.length;
}
return {
mx_goods,
shop_recommend,
activity_seckill,
goods
};
},
lootAll(item) {
return (
typeof item.as_status !== 'undefined' && item.sold_num == item.total
);
},
mxStatus(as_status) {
return as_status ? this.mx_start : this.mx_be_to;
}
},
components: {
// Vue.use(Tabbar).use(TabbarItem);,
[Row.name]: Row,
[Col.name]: Col,
[Card.name]: Card,
[Toast.name]: Toast,
[CouponCell.name]: CouponCell,
[CouponList.name]: CouponList,
[Search.name]: Search,
[Panel.name]: Panel,
[List.name]: List,
[Swipe.name]: Swipe,
[SwipeItem.name]: SwipeItem,
[Tabbar.name]: Tabbar,
[TabbarItem.name]: TabbarItem,
[SignBoard.name]: SignBoard,
[ShopInfoGroup.name]: ShopInfoGroup,
[ItemGroup.name]: ItemGroup,
[ItemCardVert.name]: ItemCardVert,
[ItemCardHori.name]: ItemCardHori
}
};
</script>
<style lang="scss" scoped>
.interval_bot {
margin-bottom: 10px;
}
.goods-channel {
position: sticky;
border-bottom-width: 0px;
}
.van-coupon-cell--selected {
color: #323233;
}
.van-coupon-list {
height: 100%;
position: relative;
background-color: #f8f8f8;
}
.van-coupon-list__field {
padding: 7px 15px;
}
.van-coupon-list__exchange {
height: 32px;
line-height: 30px;
}
.van-coupon-list__list {
overflow-y: auto;
padding: 15px 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
}
.van-coupon-list__close {
left: 0;
bottom: 0;
position: absolute;
font-weight: 500;
}
.van-coupon-list__empty {
padding-top: 100px;
text-align: center;
}
.van-coupon-list__empty p {
color: #969799;
margin: 15px 0;
font-size: 14px;
line-height: 20px;
}
.van-coupon-list__empty img {
width: 80px;
height: 84px;
}
.van-coupon-item {
overflow: hidden;
border-radius: 4px;
margin: 0 15px 15px;
background-color: #fff;
-webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
}
.van-coupon-item:active {
background-color: #e8e8e8;
}
.van-coupon-item__content {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
height: 100px;
padding: 24px 0 0 15px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.van-coupon-item h2,
.van-coupon-item p {
margin: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.van-coupon-item h2 {
height: 34px;
font-weight: 500;
line-height: 34px;
}
.van-coupon-item p {
font-size: 12px;
line-height: 16px;
color: #969799;
}
.van-coupon-item__head {
min-width: 90px;
}
.van-coupon-item__head h2 {
color: #f44;
font-size: 24px;
}
.van-coupon-item__head h2 span {
font-size: 50%;
}
.van-coupon-item__body {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
position: relative;
border-radius: 0 4px 4px 0;
}
.van-coupon-item__body h2 {
font-size: 16px;
}
.van-coupon-item__corner {
top: 16px;
right: 15px;
position: absolute;
}
.van-coupon-item__corner .van-icon {
border-color: #f44;
background-color: #f44;
}
.van-coupon-item__reason {
padding: 7px 15px;
border-top: 1px dashed #ebedf0;
background-color: #fafafa;
}
.van-coupon-item--disabled:active {
background-color: #fff;
}
.van-coupon-item--disabled .van-coupon-item__content {
height: 90px;
}
.van-coupon-item--disabled h2,
.van-coupon-item--disabled p,
.van-coupon-item--disabled span {
color: #969799;
}
</style>
This diff is collapsed.
<template>
<div class="item_cell_group">
<van-cell-group>
<van-cell
title="选择规格"
isLink
:value="selectSku.selectedSkuComb.sku_str"
@click.native="skuClick"
/>
<van-cell title="商品属性" isLink @click.native="propsPopup = true"/>
<!-- <van-cell
title="配送至"
isLink
:value="addressVal.area_name"
@click.native="addressPopup = true"
/>-->
<!-- <van-cell title="运费" :value="postFee | yuan"/> -->
</van-cell-group>
<van-sku
v-model="showSku"
:showAddCartBtn="showAddCartBtn"
:buyText="buyText"
:sku="skus.sku"
:goods="skus.goods_info"
:goodsId="goodsInfo.id"
:disableStepperInput="true"
@buy-clicked="buyGoods"
@add-cart="onAddCartClicked"
/>
<van-popup v-model="propsPopup" position="bottom">
<popup-props :propsStr="props_str"></popup-props>
</van-popup>
<van-popup v-model="areaPopup" position="bottom">
<popup-area v-if="areaPopup" @confirm="emitAddressVal" @cancel="areaPopup = false"/>
</van-popup>
<van-popup v-model="addressPopup" position="bottom">
<popup-address
:is-show="addressPopup"
:addressVal="addressVal"
:default-id="defaultId"
@confirm="emitAddressVal"
@area-click="areaClick"
/>
</van-popup>
</div>
</template>
<script>
const popupArea = () =>
import(/* webpackChunkName: "popup-area" */ './popup-area');
import popupAddress from './popup-address';
import popupProps from './popup-props';
import actionMixin from '../mix';
import { ADDRESS_DEFAULT } from '@/api/user';
import _ from 'lodash';
import { debug } from 'util';
// import { POST_FEE } from '@/api/shop';
function getGoodInfoFromSpecification(productLists, compareS1, compareS2) {
if (productLists.length === 0) {
return productLists;
}
_.each(productLists, v => {
if (_.without(v, compareS1, compareS2).length > 0) {
return v;
}
});
console.error(
compareS1 +
',' +
compareS2 +
' getGoodInfoFromSpecification no match !!!'
);
return {};
}
export default {
name: 'entity-group',
props: {
goodsInfo: {
type: Object,
default: () => ({})
},
specification_list: {
type: Array,
default: () => []
},
selectSku: {
type: Object,
default: () => ({})
},
addressVal: {
type: Object,
default: () => ({})
}
},
mixins: [actionMixin],
data() {
const sku = this.skuAdapter(this.goodsInfo.skus, this.goodsInfo.prop_imgs);
const goods_info = this.setSkuGoodsInfo(this.goodsInfo);
const postFee = this.goodsInfo.is_fenxiao ? '免邮费' : '';
return {
postFee,
cartOrBuy: '',
propsPopup: false,
addressPopup: false,
areaPopup: false,
skus: {
sku,
goods_info
},
defaultId: -1
};
},
computed: {
props_str() {
// this.goodsInfo.props_str = '品牌:GOON大王天使;纸尿裤尺码:S58;';
// if (this.goodsInfo.props_str) {
// return this.goodsInfo.props_str
// .split(';')
// .filter(str => str != '')
// .map(str => str.split(':'));
// }
let props_arr = [];
_.each(this.goodsInfo.attribute, json => {
props_arr.push([json['attribute'], json['value']]);
});
return props_arr || [];
},
weight() {
return parseFloat(this.goodsInfo.weight) * this.selectSku.selectedNum;
}
},
created() {
// this.getAddressDefault();
},
methods: {
skuClick(status) {
this.cartOrBuy = status;
this.showSku = true;
},
buyGoods(data) {
switch (this.cartOrBuy) {
case 'cart':
this.addCart(data);
break;
case 'buy':
this.bug(data);
break;
default:
break;
}
// this.$toast(JSON.stringify(data));
this.showSku = false;
},
getProductId(s1, s2) {
var productId;
let s1_name = _.find(this.specification_list, v => {
return v.id === s1;
}).value;
let s2_name = _.find(this.specification_list, v => {
return v.id === s2;
}).value;
_.each(this.goodsInfo.productList, v => {
let result = _.without(v.specifications, s1_name, s2_name);
if (result.length === 0) {
productId = v.id;
}
});
return productId;
},
getProductIdByOne(s1) {
var productId;
let s1_name = _.find(this.specification_list, v => {
return v.id === s1;
}).value;
_.each(this.goodsInfo.productList, v => {
let result = _.without(v.specifications, s1_name);
if (result.length === 0) {
productId = v.id;
}
});
return productId;
},
async bug(data) {
console.log(data);
// debugger;
let params = {
goodsId: data.goodsId,
number: data.selectedNum,
productId: this.getProductIdByOne(data.selectedSkuComb.s1)
};
// 如果包含s2说明多种规格,目前支持两个规格
if (_.has(data.selectedSkuComb, 's2')) {
params.productId = this.getProductId(
data.selectedSkuComb.s1,
data.selectedSkuComb.s2
);
}
this.$reqPost('/wx/cart/fastadd', params).then(req => {
let cartId = req.data.data;
// this.$reqGet(
// `/wx/cart/checkout?cartId=${cartId}&addressId=0&couponId=0&grouponRulesId=0`
// ).then(() => {cartId=${cartId}
this.$router.push({
name: `placeOrderEntity`,
params: { cartId: cartId }
});
// });
});
},
addCart(data) {
console.log(data);
// debugger;
let params = {
goodsId: data.goodsId,
number: data.selectedNum,
productId: this.getProductIdByOne(data.selectedSkuComb.s1)
};
// 如果包含s2说明多种规格,目前支持两个规格
if (_.has(data.selectedSkuComb, 's2')) {
params.productId = this.getProductId(
data.selectedSkuComb.s1,
data.selectedSkuComb.s2
);
}
this.$reqPost('/wx/cart/add', params).then(() => {
this.$emit('cart-count', data.selectedNum);
this.$toast({
message: '已添加至购物车',
duration: 1500
});
// this.cartInfo = String(parseInt(this.cartInfo) + 1);
});
},
onAddCartClicked(data) {
this.$toast(JSON.stringify(data));
},
areaClick() {
this.areaPopup = true;
this.addressPopup = false;
},
emitAddressVal(data) {
this.$emit('update:addressVal', data);
},
setSkuGoodsInfo({ name, pic_url, sales_price }) {
return {
title: name,
picture: pic_url,
price: sales_price
};
},
getAddressDefault() {
localStorage.getItem('Authorization') &&
this.$reqGet(ADDRESS_DEFAULT).then(res => {
const data = res.data.data;
this.defaultId = data.id;
this.emitAddressVal(data);
});
},
skuAdapter(skus = [], prop_imgs = []) {
// debugger;
const tree = this.setSkuTree(skus, prop_imgs);
const list = this.setSkuList(skus);
const skuInfo = {
price: parseInt(this.goodsInfo.retailPrice), // 未选择规格时的价格
stock_num: this.goodsInfo.productList[0].number || 1024, // 总库存
collection_id: '', // 无规格商品skuId取collection_id,否则取所选sku组合对应的id
none_sku: false, // 是否无规格商品
hide_stock: false
};
return {
tree,
list,
...skuInfo
};
},
setSkuList(skus) {
// debugger;
// return [
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s1: this.goodsInfo.specificationList[0].valueList[0].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s1: this.goodsInfo.specificationList[0].valueList[1].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s2: this.goodsInfo.specificationList[1].valueList[0].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// // {
// // id: 2259,
// // price: this.goodsInfo.retailPrice * 100,
// // discount: 100,
// // code: '',
// // s2: this.goodsInfo.specificationList[1].valueList[1].id,
// // // s1: this.goodsInfo.productList[0].id,
// // kdt_id: 55,
// // discount_price: 0,
// // stock_num: this.goodsInfo.productList[0].number || 1024,
// // stock_mode: 0,
// // is_sell: null,
// // combin_sku: false,
// // goods_id: 946755
// // },
// {
// id: 2259, // skuId,下单时后端需要
// price: 30, // 价格(单位分)
// s1: 270, // 规格类目 k_s 为 s1 的对应规格值 id
// s2: 272, // 规格类目 k_s 为 s2 的对应规格值 id
// s3: '0', // 最多包含3个规格值,为0表示不存在该规格
// stock_num: 30 // 当前 sku 组合对应的库存
// }
// ];
var sku_list = [];
// 如果是多种规格则需要特殊处理
if (this.goodsInfo.specificationList.length > 1) {
_.each(this.goodsInfo.productList, v => {
if (v.specifications.length > 1) {
var sku_list_obj = {};
_.each(v.specifications, (specificationName, index) => {
sku_list_obj[
's' + (~~index + 1)
] = this.findSpecificationInfoByName(specificationName).id;
});
}
sku_list_obj.price = v.price * 100;
sku_list_obj.stock_num = v.number;
sku_list.push(sku_list_obj);
});
// debugger;
} else {
sku_list = [
{
id: 2259,
price: this.goodsInfo.retailPrice * 100,
discount: 100,
code: '',
s1: this.goodsInfo.specificationList[0].valueList[0].id,
// s1: this.goodsInfo.productList[0].id,
kdt_id: 55,
discount_price: 0,
stock_num: this.goodsInfo.productList[0].number || 1024,
stock_mode: 0,
is_sell: null,
combin_sku: false,
goods_id: 946755
}
];
}
return sku_list;
},
findSpecificationInfoByName(name) {
let info = {};
_.each(this.specification_list, specification => {
if (specification.value === name) {
info = specification;
}
});
return info;
},
setSkuTree(skus, prop_imgs) {
// const skulist = [];
// skus.forEach(el => {
// const propImg = prop_imgs.find(img => img.props == el.props);
// el.props_str_arr = el.props_str.split(';').filter(str => str != '');
// el.props_arr = el.props.split(';').filter(str => str != '');
// el.imgUrl = propImg ? propImg.url : '';
// });
// debugger;
// skus.forEach(el => {
// el.props_str_arr.forEach((sku, i) => {
// const prop = el.props_arr[i];
// // 大规格
// const pName = sku.substr(0, sku.indexOf(':'));
// const k_id = prop.substr(0, prop.indexOf(':'));
// // 规格值 prop_values
// const vName = sku.substr(sku.indexOf(':') + 1);
// const vid = prop.substr(prop.indexOf(':') + 1);
// debugger;
// if (!skulist[i]) {
// skulist[i] = {
// k_id,
// k: pName,
// v: [
// {
// id: vid,
// name: vName,
// imgUrl: el.imgUrl
// }
// ],
// k_s: `s${i + 1}`
// };
// } else {
// const isPass = skulist[i].v.some(val => val.id == vid);
// !isPass &&
// skulist[i].v.push({
// id: vid,
// name: vName,
// imgUrl: el.imgUrl
// });
// }
// });
// });
// return skulist;
let that = this;
let specifications = [];
_.each(this.goodsInfo.specificationList, (v, k) => {
_.each(v.valueList, vv => {
vv.name = vv.value;
_.each(this.goodsInfo.productList, p => {
if (p.id === vv.id) {
vv.imgUrl = p.url;
vv.number = p.number;
// vv.id = getGoodInfoFromSpecification(
// this.goodsInfo.productList,
// v.name,
// vv.value
// ).id;
//todo id
}
});
_.isEmpty(vv.imgUrl)
? (vv.imgUrl = this.goodsInfo.productList[0].url)
: vv.imgUrl;
});
_.each(v.valueList, v => {
that.specification_list.push(v);
});
specifications.push({
k: v.name,
v: v.valueList,
k_s: 's' + (~~k + 1)
});
});
// _.each(this.goodsInfo.productList, v => {
// v.imgUrl = v.url;
// v.specification = v.specifications[0];
// });
// specifications.push({
// k: '规格',
// v: this.goodsInfo.productList,
// k_s: 's1'
// });
// debugger;
return specifications;
}
},
components: {
popupArea,
[popupAddress.name]: popupAddress,
[popupProps.name]: popupProps
}
};
</script>
<style lang="scss" scoped>
</style>
<template>
<div class="popup_wrap address_wrap">
<van-icon name="clear" class="cancel_popup" @click.native="hide"></van-icon>
<!-- <div class="popup_header">配送至</div> -->
<div class="popup_content">
<van-loading v-if="!addressReady" class="address_popup_load" type="circle" color="black"/>
<div v-for="(li, i) in address_list" :key="i" @click="listChoose(li)">
<van-tag plain type="danger" style="margin-right: 5px;" v-if="li.isDefault">默认</van-tag>
{{li.area_name + li.address}}
<van-icon name="success" class="address_active" v-show="addressVal.id == li.id"></van-icon>
</div>
</div>
<div class="popup_footer">
<van-cell-group>
<van-cell is-link title="其他区域" @click.native="areaChoose"></van-cell>
</van-cell-group>
</div>
</div>
</template>
<script>
import { ADDRESS } from '@/api/user';
import { Tag } from 'vant';
export default {
name: 'popup-address',
props: {
isShow: Boolean,
defaultId: [Number, String],
addressVal: {
type: Object,
default: () => ({})
}
},
data() {
return {
addressReady: false,
address_list: [],
address_default: {}
};
},
watch: {
isShow(val) {
val && !this.address_list.length && this.getAddress();
}
},
created() {
!this.address_list.length && this.getAddress();
},
methods: {
hide() {
this.$parent.$emit('input', false);
},
getAddress() {
if (localStorage.getItem('Authorization')) {
this.$reqGet(ADDRESS).then(res => {
const data = res.data.data.map(data => {
data.isDefault = data.id == this.defaultId;
return data;
});
this.address_list = data;
this.addressReady = true;
});
} else {
this.address_list = [];
this.addressReady = true;
}
},
listChoose(li) {
this.$emit('confirm', li);
this.hide();
},
areaChoose() {
this.$emit('area-click', true);
}
},
components: {
[Tag.name]: Tag
}
};
</script>
<style lang="scss" scoped>
@import '../../../../assets/scss/var';
@import '../../../../assets/scss/mixin';
.popup_wrap {
position: relative;
padding-bottom: 30px;
box-sizing: border-box;
.popup_header {
padding: 15px 0 30px 0;
text-align: center;
}
.popup_content {
min-height: 150px;
max-height: 400px;
box-sizing: border-box;
overflow-x: hidden;
overflow-y: scroll;
padding: 0 10px;
line-height: 30px;
&::-webkit-scrollbar {
background-color: #fff;
width: 5px;
}
&::-webkit-scrollbar-thumb {
border-radius: 3px;
background-color: #bebebe;
}
ol {
padding-left: 15px;
list-style: decimal;
}
}
.cancel_popup {
position: absolute;
right: 15px;
top: 15px;
z-index: 9;
font-size: 18px;
}
}
.address_wrap {
.popup_header {
@include one-border;
text-align: left;
padding-bottom: 15px;
padding-left: 10px;
margin-bottom: 15px;
}
.popup_content {
@include one-border;
line-height: 22px;
max-height: 300px;
overflow-x: hidden;
overflow-y: auto;
> div {
position: relative;
margin-bottom: 10px;
padding-right: 30px;
}
> div.address_popup_load {
margin: 0 auto;
padding: 0;
}
> div i {
position: absolute;
right: 0;
top: 50%;
transform: translate(0, -50%);
color: #fff;
&.address_active {
color: $red;
}
}
}
}
</style>
<template>
<van-area v-once :areaList="areaList" @confirm="areaConfirm" @cancel="areaCanccel" />
</template>
<script>
import areaList from './area.json';
import { Area } from 'vant';
export default {
name: 'popup-area',
data() {
return {
areaList
};
},
methods: {
areaCanccel() {
this.$emit('cancel');
},
areaConfirm(areaData) {
if (areaData.every(area => area.code != -1)) {
this.$emit('confirm', this.analyArea(areaData));
this.$emit('cancel');
} else {
this.$toast('请选择完整地区');
}
},
analyArea(areaData) {
const province = areaData[0] || {};
const city = areaData[1] || {};
const district = areaData[2] || {};
return {
id: null,
area_name: `${province.name} ${city.name} ${district.name} `,
district: district.code,
city: city.code,
province: province.code
};
}
},
components: {
[Area.name]: Area
}
};
</script>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment