Commit 8fa0495e authored by 贾慧斌's avatar 贾慧斌

feat: 更新文件

parent 2ad0446d
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 100
node_modules/*
build/*
config/*
dist/*
lib/*
src/pages/product/goodDetail.vue
static/*
src/lib/*
src/libs/*
src/utils/mpConfig/sensorsdata.min.js
\ No newline at end of file
module.exports = {
root: true,
globals: {
uni: true,
wx: true,
getApp: true,
getCurrentPages: true,
__wxConfig: true,
Page: true
},
env: {
node: true,
browser: true
},
extends: [
"plugin:vue/essential",
"plugin:vue/recommended",
"eslint:recommended",
"@vue/prettier"
],
parserOptions: {
parser: "babel-eslint"
},
rules: {
"prettier/prettier": "error",
"vue/max-attributes-per-line": "off",
"vue/html-self-closing": [
"error",
{
html: {
void: "always",
normal: "always",
component: "always"
},
svg: "always",
math: "always"
}
],
"no-empty": ["error", { allowEmptyCatch: true }],
"vue/no-v-html": "off",
"vue/require-default-prop": "off",
"arrow-parens": "off", // allow paren-less arrow functions
"generator-star-spacing": "off", // allow async-await
"no-unused-vars": "error", // disabled no ununsed var
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off", // no use debugger in production
indent: [2, 2, { SwitchCase: 1 }], // 2 space for tab for perttier
"space-before-function-paren": ["error", "never"] // no space in function name for perttier
}
};
// prettier.config.js or .prettierrc.js
module.exports = {
// printWidth: 100, // 设置prettier单行输出(不折行)的(最大)长度
// tabWidth: 2, // 设置工具每一个水平缩进的空格数
// semi: true, // 在语句末尾添加分号
singleQuote: false, // 使用单引号而非双引号
// arrowParens: 'avoid', // 为单行箭头函数的参数添加圆括号,参数个数为1时可以省略圆括号
// rangeStart: 0, // 只格式化某个文件的一部分
// rangeEnd: Infinity, // 只格式化某个文件的一部分
};
# my-project2 # wu-ui
## Project setup ## Project setup
``` ```
yarn install npm install
``` ```
### Compiles and hot-reloads for development ### Compiles and hot-reloads for development
``` ```
yarn serve npm run serve
``` ```
### Compiles and minifies for production ### Compiles and minifies for production
``` ```
yarn build npm run build
```
### 注:api中须上报设备id的,请在接口配置加入reportDeviceId: true, 则会上报shumeiDeviceId,例:
```
// 领取优惠券
const pickupCoupon = params => {
return request.post(`${yxmGateway}/api/kdsp/coupon/pickup-batch`, params, {
reportDeviceId: true
});
};
``` ```
### Customize configuration ### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/). See [Configuration Reference](https://cli.vuejs.org/config/).
const webpack = require('webpack') const plugins = [
const plugins = [] "@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining"
];
if (process.env.UNI_OPT_TREESHAKINGNG) { if (process.env.UNI_OPT_TREESHAKINGNG) {
plugins.push(require('@dcloudio/vue-cli-plugin-uni-optimize/packages/babel-plugin-uni-api/index.js')) plugins.push(
require("@dcloudio/vue-cli-plugin-uni-optimize/packages/babel-plugin-uni-api/index.js")
);
} }
if ( if (
( (process.env.UNI_PLATFORM === "app-plus" && process.env.UNI_USING_V8) ||
process.env.UNI_PLATFORM === 'app-plus' && (process.env.UNI_PLATFORM === "h5" && process.env.UNI_H5_BROWSER === "builtin")
process.env.UNI_USING_V8
) ||
(
process.env.UNI_PLATFORM === 'h5' &&
process.env.UNI_H5_BROWSER === 'builtin'
)
) { ) {
const path = require('path') const path = require("path");
const isWin = /^win/.test(process.platform) const isWin = /^win/.test(process.platform);
const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path) const normalizePath = path => (isWin ? path.replace(/\\/g, "/") : path);
const input = normalizePath(process.env.UNI_INPUT_DIR) const input = normalizePath(process.env.UNI_INPUT_DIR);
try { try {
plugins.push([ plugins.push([
require('@dcloudio/vue-cli-plugin-hbuilderx/packages/babel-plugin-console'), require("@dcloudio/vue-cli-plugin-hbuilderx/packages/babel-plugin-console"),
{ {
file (file) { file(file) {
file = normalizePath(file) file = normalizePath(file);
if (file.indexOf(input) === 0) { if (file.indexOf(input) === 0) {
return path.relative(input, file) return path.relative(input, file);
} }
return false return false;
} }
} }
]) ]);
} catch (e) { } } catch (e) {}
} }
process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui'] process.UNI_LIBRARIES = process.UNI_LIBRARIES || ["@dcloudio/uni-ui"];
process.UNI_LIBRARIES.forEach(libraryName => { process.UNI_LIBRARIES.forEach(libraryName => {
plugins.push([ plugins.push([
'import', "import",
{ {
'libraryName': libraryName, libraryName: libraryName,
'customName': (name) => { customName: name => {
return `${libraryName}/lib/${name}/${name}` return `${libraryName}/lib/${name}/${name}`;
} }
} }
]) ]);
}) });
module.exports = {
if (process.env.UNI_PLATFORM !== 'h5') {
plugins.push('@babel/plugin-transform-runtime')
}
const config = {
presets: [ presets: [
[ [
'@vue/app', "@vue/app",
{ {
modules: webpack.version[0] > 4 ? 'auto' : 'commonjs', modules: "commonjs",
useBuiltIns: process.env.UNI_PLATFORM === 'h5' ? 'usage' : 'entry' useBuiltIns: process.env.UNI_PLATFORM === "h5" ? "usage" : "entry"
} }
] ]
], ],
plugins plugins
} };
const UNI_H5_TEST = '**/@dcloudio/uni-h5/dist/index.umd.min.js'
if (process.env.NODE_ENV === 'production') {
config.overrides = [{
test: UNI_H5_TEST,
compact: true,
}]
} else {
config.ignore = [UNI_H5_TEST]
}
module.exports = config
// 这里是测试
@font-face {
font-family: "iconfont"; /* Project id 2314957 */
src:
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAACSIAAsAAAAARwwAACQ3AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACKLArxRNtfATYCJAOCEAuBCgAEIAWEZweGKxvaOjXjmKXAxgGYm83EiGpRLvv/Pyc3hoiaoFVt+w0NVer25rTLcO+JJtS2wHJZOOai2szH6OL1eIZ/CcUsB2vRUmExXAWNorM5XowW6C/cKCE5OsrSgR/df8Z2Ou9QSni+X/ude99b+S4JMWk7He+ePCSTxHRCo5LY6ZT050e0kWg7PGyzf0RJlIBJGogYCFNKpYyaKKDiCgtQt2mjK5kLY6Fbu+3+n+v697UX5VyGLl27qjtFjM5eUyCegI0/AFCAMTRDoqNRvg0QsGa8zf8HkPaAUVjaZaqVUu3rw8Sw4CvjrXf/v9ddEcImwYgIkTb0Xfo7uceZoFgErQ9BAT5xETyl0aPvZ/d35leHoLhzUEQqvYDI3e3WAsqhzE7kIQKiXVudfiCHbv/XtEBp849zSAXi5zchZ2ytHjGCG4zxUCEjgAC4nPCDPx4A/GhOCmjZ2qKZZ6VjkYURYVeqZguI/2/qnXL3CQ6lx0VlF5XHXXWBCnsgIQJQAqkEivII5CeQn0AnfKbglPiycxVDaQZJHuIj8ZFURTqmSm5jKpqU+lC5clW5KF20rt031llDCvHhD4o0eiPZMaaWg66hNZZYQxFXwI0KTtr//QkCxBkTBRqUbASEw1XOBB7gOMcC4awc3pYD0LdtbEIg+DU360W7cK1BgD72EoAn8nv5BROhoTiGc9XKF5MP+kagL1PmfAWYFriQdwCnFXAAAwzVrCv/yb0/wXAIjDjvmfEOIImPYj+gIzo9Tr9MKUCFFMf1553vE5IkOU19I6BgH/VGs9XudHv9wXA0nkxn88Vytd5sQ/e7/eF4Ol+ut/vj+Xp/vr9/XKnWyon6/oG3mDWfTxo1ZtyESVOmzZi1bGAUpqdh6BlG/5XzsCQJG5KxKQVbImxLxY407ErHngzsy8SBLBzKxpEcHMvFiTycyseZApwrxIUiXCrGlRJcK8WN6rhVA3dqYpBauFcbD+rgUV08qYdn9fGiAV41xJtGeNcYH5rgU1N8aYZvzfGjBX5pid9a4Y/W+KsN/mmb6kVlB1jVHms6YF1HrOiEYTpjiC4YoEcs6glz9Ix5vWBBrxihN4zSO8boA+P0iQn6wiT9Yor+ME3/mKGITkMaPlPWKAJA4J95ALQB+YHKgdPRLjKGQwZdxosC4y6GJN6CXlR3KBgcVBa/bIPktmz4VcPL0GWXLdunvsXB8yJUjVtWVFam7GbIbB9vLWdxR0aVKiywZIXjkCAUCj0tZgHEBaFchuusiOAZgEQHgRALkFgMcS1qNehb94jn1bDKjIQ4ksQhXXDoMY6rJ7PbgyjDKpCbBCD3Mb8L5pcs9pA0JocFgDJ5soDIAJeZdcFEpuQGJAI5nRhdrzCWQwahIp7NukukEwo9n8gkXUCpZJtEFGhV1nTfltEe8onpNYlikwQtMDnOEoWb5B7ABbuIVpOyU/qflAFwyqjqzAusxPcuS9jF7ypxCQBewoXrziv3E8RfAAopyIV6FXl47SJ/6XtWTE9ldF59kFBDH5mpq7CHw5V4tr7dGYt1kqxi2IlMTi0HjDOfdAYTc5PnKiuqTFGRAoSl40qN+SV2DMxHzqSN4NReWvZKmg+BLhb6PKefRTvVYLcuXHK0PkGKttxNO6s54quKYcVGG6/UhJxyas7H6SIL9jxedJaqTq5/E6YYK0lSbqVUrjZqzmWpwMBc/QoeiwNHoP+q22ripChtSbBCLv/6zn5rNXWJDF5dUWEZHW2/P9YlTo+l6oG95fKRichMLT0zbt7ZN37G3XeHnjqc37+4axTUFqohKq9PrR/anV6f3r3ezww+Dojx2PD0tZ73lbUDtYmOipoQqimDjfAY6qtAhMk6papqcqFZoT9wQepHmZTvmNm/ZNie4FYcze3TLf/UDeBYQYCI9+lzIwex7rpSa2mnYYYzcgZi0/edwEoqdfK61InLf+Npe0ZA9m8Sh+LE8OoIW3dxagQsDUExMM1sLiPAHChujGw4v2V4z3g914T29tSDfEP6ajQXzsxLeHa/6+6b9P31Qy3lYCuTqRwer01cuR+b2gz8zEvB+1Ne35AosLKVpFfdJARBZEECQmAFxIsRpiVkkGxSW45QcSkbhYlzUEIZw0seHb+Wsq5X0FNCnqfOFLmbYHZVWM0/VE5IZWOxfGwqMtFUXJOoBVSaSDZSvGJrB3a4LSfNrekz3wTO+munW8a2Lx1+mhQcLbZdPLbou+6JZVst+KbBwbm7B2e2jriNw+5bd97L1acASDVc2r5kyJlhe2ZqyZkNWzyXSSSzIv3DRLqarnM8Y0KmKod41GnQgozRQ6V9uWhOpmHw4OaUNSmigDy6bZZWZ5itgHT9YHPpDC85eRTL1y+jbiCur70VO5knjLqE3eY940YmnMmgKjUiwhTwjWeRt+/uz8cEBIWwwagsU4jVc99QrnWYvP+8oa4OIRBR2jqZwmgfazKMe2dUM3Peirbbkhejcs2L27j6y+Ujicb5d6hsEtRO5e6rm0AKOJsb4lc2JqU21FYKq/3+0WzTwk6m6A5oJ2cjFab58O28bmBYeW270LSl98UPS4F3VB/1G/XhC5633zL0sHs7T2FpfbHgVgN0WZ93/WPWiNdilS/6/h7djLNEAULJnoeVeBEAxFIGP1ldz/84l3LSebRyZOwJXBEvSpOQC4369IFpefpOPTACREXnZicCXbYGBmHIHHp69PZLLzZ1kSY2YPcXxvFkadAZKk+hTjJRZOBrydtJyGv0/tr+aVhtVBHJPM2lQdX0TVg+lronZYSIkq2rY0rd2h+qRNkpqcuq1Ln0YiZbD5XvERwJYUbtgjyi+7AayFfDqw8tiRp+tBxlvv4Y1ZCnN2+HbzyB8eknQqNk0nWx64bCsiSvaYG2dco32NC3FRDPs1033kqx2s6H5kRjIN7O8XwnDtRAHYq3qvg3eL72FXshUkOWGkJd+UxklQp7+dGeavzkxrpXnZtP9/+kGCwp6zSTS2kWxO5y7fxeNgjeRiZPaZrIx5Ue1CfIptIQKYqMQgmJVmFFShbqpHhaQ4CAladIOq/EhVAitxNEF5UTFxZux0RWUa5sHD5sLqZa6Y9ElOiSted30Iyq5m7Nn687bP2ejuZUNTV7a7qWUjV6J7H0RPri4p3wS7Grm3ha0/JjF0ejh5INl3aLvKJk7y5dqj8oD+PEz0vO3J3TKwrLyoB7QJ7ep8qJWlmZ8dbI/buAkqxTtClvqzJiBZRsRNHGgr3KhBXQ8jFNHQwOa3P2lGvpBk0tXa1XgXOzRVNT9ao87m9TR9drai6qysPuPnVym0E8b62U6+6RB6MRn+Lp+WGpK4/3oqmHNxvA4I0ncZFSezku2EpPN7WLZFRDRx1btjOjh9kFnOTUMcrXP0sPtXJOs/FMMXSaZFnNMhgRjmpawilhWe8gjz89ypTifURi+eMt5TIihiE5hwv67BHPlkYBWGpZ+oPMFEckb7vg6cZG7m7gY+oxXz57BusycMbKc+gnyCBzzuw/PCNXlpuQe9gLrmCJOC5IOuchDK1LPZKEzuX0g4zhpipMq1a1xrMaDZd+3s1gZhOtQAldwgK4WfzaAQI/fLci7tzcf/HUuP/CX/8ktv8RfrLuVvKA+8zdt8yeuG4v77lwcsp77q15HDP0lDxeezd1MHgZ7L3Jm7wxVbr6KtUsV4V8rOp+SbzC5coKhBOKgB8IUojSw5IRMayar2xCcfCqTi0RVXTZHhjwzYa0hGzMtRvXjZEmaRAgmhUAx/d1MjNiD0/j2VFnbO4XmlMnnnu6lZ7dTTjO4WZyDiGmNkPIaGOs66YhHA4rzZ+I0DpE68/tNb/ieXuBLDmLeuGkGhfRxVz19ysrFWpbhKBCPL6W2PKD+4qZV+RmEw1NrJUwaQeTaVMIcc7JI8Nfyh2BrJU7ICdVyj3SwxJaPs68C7toQtvzSBA4vh9HXjaR1TgHQj+NzMc7JpJESBVTIyGAJQRCjEnQEDq6qb0GYdKhFJqcA5C4gcIKtUE3WX5klKmimNGZ1zSxoCS3LR56YJKIL58NEx1w/NHyiG5GU2Qqx37xDs6Ye0GIfeAcnrO23rpp//V6JPiNOP5bX7WV6euvpoPEvcFV01f9tbRispOsTjEsoY01DN2sazO6+DuHwd/jN+7IsHdwwWBMKUaYVloHuNBAED227uI5HHb1y8YFY2YvIExOuF5kyjSUj5VbBCJCvbp7LLBIrNT8wtRvpLeGLcISJ8lk2uD8/xDFQKQoLfuYf3VyZKVRZ6UOK1aGoD6hApMrchLfUxQ2/hTnxoMuwjaGewnzlND0Sfpi3CQ7CJOuVj0MHLRzgfb38baqjkpLflj7hRR3+oQOteOLrWmUnpF1+qYnFIO9m5MICc0SZ3pZNZ3ghJRq8kQbYopiTZnmoZpr5oNIbOHHFFNQMTJxXOymFYWZt5xTbzAiZdy10LoEuzj9S5xJ2MmsYa7YATGVXlqe2SF4vJtKJKcv1cnFpKyFHFNgTmqioxDilEgPqr0l3zV64JJsXT8PIXAWo3AfIEpL9aOJlyDsK5PKX86UODkGkjJeDGuEmjiXv6G0qcQMgAFk582Io/5QUXu/hoyFmPS5FiczOjYyDU1o18vIeklFxg9EAc+FK5/QsRRLa/LL+sBnWrU1oRNFVRY82z1CKecm8OgqB47fzJ1hWU43LCFY6lTWDR8hg6umTnM8ZcHcZGlBFkPzu/ePjuxkiVWDnWvVl6LdjF46/NCED0wfKezovNq8eGi2fbK4HMXTw/bIDJkbc0Zn40sA3pjt2zX+nmwtT6G28U8kZ9F2i5UbLNUatRYaG+fDGYgfjEY4thx5qMaFWn2JHJwxjioLiMy1tKzj6cQIOaWoPlHwapPVWUN7L9pubDfsj1VPLmTWpmD3Zge96obynpH12H5k37epupX8mEFmaOBxHlmn4akSmYxqcpazNFVHtRE1zRJvWn4t5mGT7MLUGgXGARLKAvQChhiHJjefTVV4X5k0reId8IcK9oDaqYkujuVvRmQnaJcvFvHVEGhj97c9CLtemoNg9xAAF9vnwqSW7+EHNwDPZ6WWvj1pAEK04w/uuXpmuC45g2IgsD3emRIRsgSc0ah/+70ny1KJL2GmMFCMIVH+kc9YSK3YDmVKk2wj5KoSWodQVetgXM571q4rsQi9ppNa+2Q7nVTFrCSN50pmlSq0hWQi/p9oIqJIRpaRhGJGXmM+uFsKUUQj8RjRyDSSjjGvKZlxBtM04x8S4EgdSTQx/VGm8hrzGORpJTQRACw8xLwWydxYTgGw28xg0gMZn3J6iIkCgrecZXAXluAC9mE/ljGx+3EGEbhoFfZjDhMLKnDkfdLDckrcRwvTc4bAnWH/PF/VIA7gFDiIpwPcmoXJbH968MwNq69YZeqwC5BMWkOJWLk478jaFwxWwXNZSDUH+ol7oroRibxXLnyF235+/n7JJdg8lYLHEp6eDNQN47ke64eHmzzeU64P9+G5eAyWSDTDKqdTdcLnaWBNMrNN4Up7UMWRnzFv3Vzr4LgvnlMb3S46p+CSIrGjLpCWWzO4RnFzBvY95f7BRQoG7knTJoJorYZ2icZGoYWkTNPed9obN9auncHOM7PP20Tnz/9IP0eaY3DXid0qQPjmgsPe318CYXLZtoBkaKt55RMdpJ9K7Z/Xw5OV5lZocsC2smThD8/H4U4V20eTwPjvzcUxz6A2T723qVcd1qMS9XibvNKg9u9+lkeMBI0PG/yvLr41fqqD2kkdxfVz3NweX4nKpm0b5LVyyVsGJAp9NYgHXU58BhFvxLuuxpPWNBygNQj8uX/Ff1VSy7m1ILFO7VMSIwqcmpARGh8Ssy0tJ7NNLU0iJMDIplh/nV/qoom+61f8muc2eVrE2TXXDRRDrI+Oq5+1gkj1j+UZ9EviNu5PUEg/9/jT0Hx0wPqAdRw0IZaI1xGoC/GkRYAN08yyKwsUigKl/SsQ7rxAYVd+ZQrWmnMNofqQEH2o4bQjR2d8Q+hp/Dps2XGTQrr9+lXsxUS5f6Ox4CW4svlWTHP8jS8ItgxMY1FD1Am+aU6twD+ZSO7akOFLKUmU/o9BOH5uQP97GIGEZEPMCFEseTjfHRy20R7RwryQmListqqsXp4mz/p3U1LCmNdARx+weYyw9I7XnWVXaY8Ejw68pj7c/mLkRdn2q5UCBwWDB/KltOLsMamE9PaaX6R14PnIi5HIbVfnivDPIRiBDx9fXRb6lv7rA2MUwkOLwvpYa+8ft19P143WhbcDHQq3jVd81X+Zb8paboIxPEVkZeTQJyFzUcl0C3ORNtrFQuBdiHo45eTHwd4abh577e67S9BdbSsDD6BWRra2V5mmxbkluu9HJfLiOBnFBVtGTuRFwBDpicdMfKDy7O22kKA8eXl/i2+tfv4XoeyrSKjYUu7qz/EKc3L+0a6U3N879l7cgoljpJMqNP1lCHI9vwJG1rDiCwJOJ/59KK18pBxQGikEut39HxlGBloeyJbCXfAMgINOIHPZO6cfAm5EHCdHeyalvfcWiCZfHx10ttZf3XptZTqUdqbh+aqPm/vKVnKpJyu0OsR6+CSUGn7iKQS4nilCmkHKc6r12IRvULCmWfqJGkFhc2AINqGd2F75mx8n/jgocoPxXRQes3nUShiWX8tWuLfyqYHA4UnZUzpz3Zr86qckacpO9g54arz/tWBg7S1KHiOrJ14H2uAdx27eQKRuCgV76AxNITSIKL05S1TqqrUHk+TXZwXnOxwRLbBv3iTJ0+X+N64jJu6wyyLXCZctXbtGsvjpvoAb1+GpCTtHskY36oJegVK8tZBq9y1KS/uoQi/6+nUwqNGoiNEmk9E4aRI20afFY84c+rKAuP3//IPPvrnq7995ji5O0y/4tr+sUT+jRqMBRIrQm1K2Ui9cc5vvxfEuc7t2nro6Zd+u/g9hV1f1T/h0g7DspefLZQQReUMCrfqfLHfcjnULV/S0zp0TcOddiHUnslhPT6HPyxPoQieyTRplCMmbVcMr5OTHpGlTezKrAHoFCrKWf7SvYUZWXGb8iWawtMa/48E1v2u7mHzCrsMaeNo2CDVo/ZNbXx/sz4T6PFnv3R3hNXoGzT8WVHc47dw8pivBPC4KcBV6U10Pe20OYW713lD1SCZOPB2Ldd3tZnU9Y7apGN6RJsBkneyjeJD7TuK5ntzLdeI4DH8W5eB6WQpb5yaBdtcufqdrO3uv/94j0ZzY5fAcD5NnXjd7LPTneYqcnKU43C0CXh5XsIW3IGjO5T2HIPzJy+IQU3B6WoghpDDPKEoXhRpEGQUx0umBJn3JcHphbdMcrzlNS9Ltw6klQlNE8YyiMENoqCGPRxhE+QEoEApEzk8/1cu+PU/5LrKV8plcTQaieuJPRrdft9XSRXKQP1NsJMA0eOGIyCeb6YD9hhXI7v4kIFoA9tMWWcDfN/KMSOj7dLKrTyvybKjZg1NR6aDZq6sbLES6Xav7v7+KVc16h1sRK34rkqRli9L6NWoH0kZx6AHuGZ1DICCIU5r9al6+XIsDJZiuV1/GEVGETVhVIx6yy+WK7Ryc8JtaG3jx3IG4pl0DfGF86a9WeIlXpcWNv+6Iwb+2widj+ZE77paKiqwdDBfUTrO6vhWj+n4tgj6/oiZwQvm6CE3Bq8C5K5ARETs7Ofsb8t792k7q/Zq7X1APhf2qm+O61NdQdVy/6Aj0RHWqyMwydSpe8iuh9u0zVRcMfpnZCLsnu9j2lbrGxOo8Oq8+jr04eyT7J+K4I1Xj/BSJxPPwpzRQ247rSsq7Q9KEopQofIhQnxz2uU9kCCWXj9QApPszcbA792c5BAspQbJwEP9WEN5eHWhrrK9/xO/kP7I49HQ/9fPbwJqqyLNMs0yboiQDK9hC3yLAskkZwDbIa+3KfLk8X2n/zAcvz8+X25WfmSJknO7Gsz2RE3VNjqkGMa53NJ8SDsY4owY1poEBGI6mZnBzHvsXbF9j579zvf2Gujic6ifkJPU0sZpAR486fx4xgXMUTT8yaVtrW8jHnpdnLbR7377IebTGk7ljrCdSXbMXaHXJGUNpR7HbGePBxRETAFN6pLoxuf6dpa3czfomEHZdQBATOrxs3roxAs9bTBhrJBzPrPO2eXUQxPd71uEb+dx3ne/zSN8OAk/S8JbI8+IR/WiQ1vBMoQxgwybUWBV5cnmewvqRp5Tn5cmsyo9INqac3KpwBE6fPMEsEZvDJ9915KNm8eTwu0CwMUUlkyekHurvj+g/KT3p/8DtB+ONM+RKEN7v9NsXNObGSsDr8Amf5n84eT/54vUP8z/hE3QJeJbbmHB/8n5hUoGgfcV1QUnCwKRsIrVno1348cIRcDvD1pu9Nht2InTBltO6mCrBP7shEEBsI5Ot4nKsC6HtwYMMgthLTDDeu9fmBUsbhSy5NWcxQQ0q4Y2Pu+PM5Lcttyo+MjU6NioLlAprpCTMqFTEf++GmDAAk6FLbdpjjlRYo62zPN8ciDjwNvwtbn+DYMtAng2y0+JRkV6chT3utZ7xN9qCGaBcwkz0XJ/RR1WHxHRSujBfcRoPKHoPXW8IqFWTgdR3JfUtayCquE6DWUTgeiy0qHVLEauTwZx+VhH+JgLGqzv/ttkwSc1QOn8cbi8ORQie4k7BE71YmLvLyMvvYObN1lYunqXAc3F/uc7hwPduEGDnSTpClqdEDMrAFFFoFmeIwW++fkpxZkaYWXL9lJlhYZkS83UtLCMzqoCdihvH0ryw4wwVKcESGUSs1y8CjnLD8ZvIDdxGbg3XATyo8h6vIDFQkCBMzpb5FilwuBoUxK3BVzo+w19uTo5uP0rk6KC9RpYiYXZ83KxVgaJjZUAG9AvHVEHylTlyaa68wIGBVCnz5Tm50gK5gyd9aE6N65b8yXlERhVYMKkAityNsluaUWANchdqvmUDas0nvtAKMZSmmmho7qlvGQYU89Bl2VdSetqkJdXsuICdBB0z+otM0JK51H3kURiYR505b8KLa0XfCjEOmMgqYOh3mK3OyxgY5i0mdQ+Ss9UrXnnTB8nZ5vnUBZrYD7adjCFtOsDlJ8qXsSxrt+qiuD2bdKSsPVofYVpoDaWZvew04foTaUPjalN8QCw/ICYgzjBJlGTvoDSefwGu4lH52syy2vLZFF6hjyhlhyCOHxPLTwgwSmOrtLqKGLUt/OqV/huHLjcfWND5zS9GV1GljamlTRsaCRwZmiYoufw98PvlEi3jQ8iHoPGQccDOMyCbjmCYAQtb4oOyibG45SehRuKjGNThH3bF+2ObuUcBg1IGNETli6TqlddcuVOwM77jNL0qQcRrAONCa6YsHARkCgmqSd1aZ8aiKX55Ys8spQqJpPgSjz9LuoF+QB6gdlAGZsOsOGSAfIn8cLACO0Yfp3vqPHhQdpw2DtZ9pB0Uxe0mWUleZBh+JCvZ67nyXaGxm2kB4VxF5vF/kf8eH0wJ1QeH6C0haQIL5tI4vfU7pw6lQZVqSv3T1lHTsWOIq62h8nB7z1/i6LWlYE1EUbYkSyzOkmTfJNKdZ4mzJTeZpDWcZGW7hYT74SY4qgxhQgS8HIKDpYCmEjdyCCiQRvCHQp4IEI2+6998YX1uxHvsvxi4y3ArA+Bhwspy/wulZzDnw5su5PBuUuzQCg39401j/6zDk6MXmjevYJwqbisusHnQlns8xsJUovmxK1ct0JxOD/Joxdrs9lm7r62gbElQO5X+MIuJHE40mlYFb/506nUbOZyl4+R/ioFQqgcWm+bZK4QXLhtXmpm5kFDmq8l/n1jFeJ0sxKqqblwoxkl6JP2amXFhfWE+L7R9xdQyy4lTHHU7qsBR2nzaCC80iAwEuh1hRQSrCk6vM7gVeBioE03jDLjrv3ShO899C28unoylINajDPoaFA5PJSyAlKO57kLy4cv6Tn1mjZqoJpdqNIlyPBevdNd4TB1l/fU0k30x+OvUr6aVKjxJOLk6nhcO2DB+Ra5sWkTENFnuCJHQGT9XNsIULLdlJgbGBQTEBSYeCBQo0HY+cO+SU2wzJwoTBIL4wKSDgnsvsYEJwgwI2laVJ7NIIyzyvJdSYY+SqdIceRmkW8xON22f1udhZ9YwU6c5rOsR48SN86pVVhlPh5OAywcQDkS8N/NcBhA2ZBjShvD9D376WY+z0/Gul/iXAPsUiYEk/SQhGUM7TpMXE/cRF5FPP8h9sOFEw4kHbV7tOAcY1W49xk3npD6qwWHu6UMLIFZ5y1/e8d4xJlNoyd3p1fhmrinWL3d6QIE15ubnPZFRMWCMk2bm32jcxhifcC5fbzY3NzXrnj3dEBVlbHJMpsioPdefWYFpzU0O/Thi9xd3IMfpHbelMk+29jl/ZFp2T0dIzBMQRcleyfkuditel9CMnPv0Vxa8XeDyBraTqZKWJaTO+hqrEyiOOKmXXwzBblzxXXlDPsVP5eOrSo4jVL7JgcCTT7bHhU0TNl6QXNg4YdMFIDlyn95ia/bcpu1BZdpt+/L36Ba6T3Cr7xBtWL2R/i8cGIF6ihaGID+2stn7hny9p/+7u23j5593P9bS/0GAQ9en7rEpVV2j25keix6yO255J6o1wfQh9fIZDBAEgj8GfQRBJ+Y1tofrV3FgbJBJ24oKeTt2NMkcGP3JTMlRmVQmayss4u5ct579J1q/dge3qLBN6dWXTMdPzlY7IdAWSn9IQ1ZjgZUEdV8mXBe1YrtTRSLV6dSwiWu9aMuhkMLcxix79OHldBIkqj4x5Q4MGlmfgGtfToe5ku15i/M9Upg1pHkxq+mrfwT4v1AYzGOZh9FRUEBGwFoom70S1HXQWnv4r0Gn1NFQDkmFJ1b+luwgWz1txawVPhSAt7dyrGeFxJH9qsGtAfZbgRnAjOW08qAOHi2tOWOYTozS+N3OuUhmELLUAhthhibTJgifO43hWwBaGJNHP4gZxLDE7+Pfi1m4GTPwntKkcBcEasDmGf/xSmopWrd90ByT7AbJB2rtzIropgp9ppZoLRCvak/6qXy0LrX0yseV6IA+tcJBFrkawD/GkeDEyjdwEA+hXpqZ3dHs0n1gAC0UTKX/jYrVr6fF4tEZkALMWhcD6m8pDdba7QJDP3R5tKIbA8M8cLlnwQ7dR1p7MKSvjcD5c+Z+jClyzmo+hLtVRlgAmAu8ZM/cqNGR/jTzz6gmX3DfDn4HLz3a41TS/CuOkMz/e4swI51+yuqK7mWNrvU1S7LbEEwrMzfJRNmtMuZvM9Pk4gN8ThoApkv4gR8Wvesg8tH807ooo4NmlNk32No/39dNeHsg2uV0XZP/6ugh3pGvrTr6rNVcP5FJsqptRr6OVnK7PmuIgF7qq8jtwrqE7xUl2Ne/5bDjMloheY1aCB3qlxUN+7kO0V7RdWw6s26wEbE7yx1u2CWoTifqeLtuf0EPkixbnXPDPoC7/007rzIICvwDzmRM/k/HNKLy32D/T+cW7dgfJVhvmhbRP+UmD0zu37JXJu8hAOztv9ecF4IBsAf/90M9fjv7jM5+CfnW7E1+jm86PWf9y8bBkrpSCQ4iw5WhQNwdhAgN5g2pMFTITHzwqcCNoHg0BINPB29nDwgOCSYEF59lIc6gmB0nKCgNDLEToMeCgyBk7RaUNG+CIescb2ffERzKXgouWf8KcbYOX1mCnh6DsRAoObO7moCcPCUlD/Y39TWCRI3+JykB55j34NDPS39RIhHhUk79h6o3Xng0P6/3jWJkk4X3hNoNqvnzNcTK89whj5MvIVByZnf1Tx+Qk3dW+t33m/oaQTLy/zUpmKAHb967twz8LzFlWmdNrOXUfygyvPE3K/Nofl6mUXSTbDJ/oj2hdsMFRv58RU4+q9iVHxqNVxx363W2zfKSE1Jpw7T+pO5NvB3X80VJVkjVdMO0bMf1/CCM4iStN5qtdqfb6w+Go/FkOpsvlqv1ZrvbH46n80WDH5NMAb6G4zdrdRRkRwtyQRcIoo95YGUbQyK74+hmx+OL43OKDI6zV6szhUtI7RhSsJBzsdxKoXH80n3Hy+ONE61HHilpWeR8Eg6bHeDBKueNp3QJkPpNz/VccaCGxZGIX34TGUEDUh4Li9qi061wTe6e7qz5Jq0pAwhlnnhxrZDuCqmG1DPpSxDhc+ObbCSvy3pur5YWIxeyOUKitpk0DG5S7bjmpQqUYa0B0j7AujDpXixNucoix1rum0GLkh6qG0hsKZPUmm0VCvbY47YtGWlC8oWK2w+Sf8pVIRAcmoFHuo/XQoI67mWTdLBWLUuqT0MYSYBdencGSS0PFEgCpfXdFBBwwXWpiFTKfbpAS0hhbD20+DOsB2H7eCC38BDi6sSxjtSoi6qY1CarGR/nWmEQjLRMDDbF0LJpAwiENwjQM1Wa6tDSlAkAAA==') format('woff2'),
url('//at.alicdn.com/t/font_2314957_i2934lpwxv.woff?t=1646303283345') format('woff'),
url('//at.alicdn.com/t/font_2314957_i2934lpwxv.ttf?t=1646303283345') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-saoyisao:before {
content: "\e644";
}
.icon-qrcode:before {
content: "\e629";
}
.icon-edit:before {
content: "\e643";
}
.icon-cart:before {
content: "\e642";
}
.icon-photo-line-bold:before {
content: "\e6b9";
}
.icon-qq:before {
content: "\e6ba";
}
.icon-download-line-bold:before {
content: "\e6bb";
}
.icon-weixin:before {
content: "\e6bc";
}
.icon-mini-apps-o:before {
content: "\e6bd";
}
.icon-qrcode-bold:before {
content: "\e6be";
}
.icon-weibo:before {
content: "\e6c1";
}
.icon-qzone:before {
content: "\e6c2";
}
.icon-moments:before {
content: "\e6c3";
}
.icon-link:before {
content: "\e6c4";
}
.icon-back-top:before {
content: "\e6b6";
}
.icon-fenxiang:before {
content: "\e6b7";
}
.icon-gouwuche:before {
content: "\e6b8";
}
.icon-order-line:before {
content: "\e6b5";
}
.icon-location:before {
content: "\e602";
}
.icon-sort-down-round:before {
content: "\e74d";
}
.icon-sort-up-round:before {
content: "\e641";
}
.icon-share-line:before {
content: "\e63e";
}
.icon-yuan:before {
content: "\e63f";
}
.icon-setting-line:before {
content: "\e640";
}
.icon-arrow:before {
content: "\e612";
}
.icon-arrow-left:before {
content: "\e613";
}
.icon-minus:before {
content: "\e614";
}
.icon-close-plane:before {
content: "\e615";
}
.icon-photo-plane:before {
content: "\e616";
}
.icon-arrow-up:before {
content: "\e617";
}
.icon-trash:before {
content: "\e618";
}
.icon-tianjia:before {
content: "\e619";
}
.icon-sort-up:before {
content: "\e61a";
}
.icon-setting-plane:before {
content: "\e61b";
}
.icon-plus:before {
content: "\e61c";
}
.icon-back-top-line:before {
content: "\e61d";
}
.icon-location-plane:before {
content: "\e61e";
}
.icon-arrow-down:before {
content: "\e61f";
}
.icon-cart-card:before {
content: "\e620";
}
.icon-sort-down:before {
content: "\e621";
}
.icon-info-plane:before {
content: "\e622";
}
.icon-info-line:before {
content: "\e623";
}
.icon-search:before {
content: "\e624";
}
.icon-home-plane:before {
content: "\e625";
}
.icon-user-plane:before {
content: "\e626";
}
.icon-location-line:before {
content: "\e627";
}
.icon-weinxin:before {
content: "\e628";
}
.icon-camera-line:before {
content: "\e62a";
}
.icon-warning-line:before {
content: "\e62b";
}
.icon-cart-line:before {
content: "\e62c";
}
.icon-found-plane:before {
content: "\e62d";
}
.icon-success:before {
content: "\e62e";
}
.icon-warning-plane:before {
content: "\e62f";
}
.icon-home:before {
content: "\e630";
}
.icon-loading:before {
content: "\e631";
}
.icon-checked:before {
content: "\e632";
}
.icon-fail:before {
content: "\e633";
}
.icon-volume:before {
content: "\e634";
}
.icon-close-line:before {
content: "\e635";
}
.icon-user:before {
content: "\e636";
}
.icon-photo-line:before {
content: "\e637";
}
.icon-circle:before {
content: "\e638";
}
.icon-close:before {
content: "\e639";
}
.icon-found-line:before {
content: "\e63a";
}
.icon-home-line:before {
content: "\e63b";
}
.icon-customer:before {
content: "\e63c";
}
.icon-cart-plane:before {
content: "\e63d";
}
.good-del{
::v-deep .cancel .uni-dialog-button-text {
color: $font-color-search !important;
}
::v-deep .confirm .uni-dialog-button-text {
color: $font-color-base !important;
}
}
.shopping{
::v-deep .uni-swipe{
box-sizing: border-box;
// border-right: 1px solid #fff;
border-radius: $border-radius-base;
}
}
.good {
.good-footer-num{
::v-deep .uni-numbox{
width: 96px;
height: 24px;
}
::v-deep .uni-numbox__value{
font-size: 14px;
height: 24px;;
line-height: 24px;
width: 45px;
}
::v-deep .uni-numbox__minus, ::v-deep .uni-numbox__plus{
height: 24px;;
line-height: 24px;
width: 24px;
}
}
}
// 全局设置复选框样式
.global-radio {
.wx-checkbox-input {
width: 28rpx;
height: 28rpx;
}
}
.global-checkbox {
.wx-checkbox-input {
margin-top: 0;
width: 28rpx;
height: 28rpx;
border-radius: 50%;
&.wx-checkbox-input-checked {
background: #ec1500;
border-color: #ec1500;
&::before {
width: 28rpx;
height: 28rpx;
line-height: 28rpx;
text-align: center;
font-size: 20rpx;
color: #fff;
background: transparent;
transform: translate(-50%, -50%) scale(1);
-webkit-transform: translate(-50%, -50%) scale(1);
}
}
}
}
.one-hide{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
\ No newline at end of file
// Color Palette
$black: #333333;
$white: #fff;
$gray-1: #f7f8fa;
$gray-2: #dcdcdc;
$gray-3: #c8c9cc;
$gray-4: #999999;
$gray-5: #666666;
$gray-6: #D8D8D8;
$red: #ec1500;
$red-light: #ec3333;
$red-dark: #ee0a24;
$orange: #faab0c;
$pink: #FFECE6;
$grey-border: #f2f3f5;
// Gradient Colors
$gradient-red: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
$gradient-red-reverse: linear-gradient(270deg, #FF4B00 0%, #FF7705 100%);;
$gradient-pink: linear-gradient(180deg, #fff7f0 0%, #ffe4dc 100%);
// Component Colors
$text-color: $black;
$text-grey: $gray-4;
$active-opacity: 0.8;
$disabled-opacity: 0.7;
$background-color: $gray-1;
$line-height-sm: 32rpx;
$line-height-md: 44rpx;
$line-height-lg: 48rpx;
// Border
$border-width-base: 1rpx;
$border-radius-sm: 12rpx;
$border-radius-md: 16rpx;
$border-radius-lg: 32rpx;
$border-radius-lx: 40rpx;
$border-radius-max: 999rpx;
// Padding
$padding-unit: 8rpx;
$padding-xs: $padding-unit * 2;
$padding-sm: $padding-unit * 3;
$padding-md: $padding-unit * 4;
$padding-lg: $padding-unit * 5;
$padding-xl: $padding-unit * 8;
// Font
$font-size-list: 10, 11, 12, 13, 14, 16, 17, 18, 20, 26, 28, 30, 52;
@mixin text-size($f) {
$font: $f;
font-size: #{$font}rpx;
line-height: #{($font + 12)}rpx;
};
$font-weight-bold: 600;
$font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
// 页面内边距
$page-padding: $padding-sm;
$page-padding-lg: $padding-lg;
// ios底部防遮挡高度
$ios-bottom-height: 120rpx;
// 页面顶部header高度
$nav-bar-height: 96rpx;
// 多行...
@mixin mx_multline_overwrite($line: 2) {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
word-wrap: break-word;
white-space: normal !important;
-webkit-line-clamp: $line;
-webkit-box-orient: vertical;
}
module.exports = {
extends: ['@commitlint/config-angular'],
};
{ {
"compilerOptions": { "compilerOptions": {
"types": [ "target": "es2017",
"@dcloudio/types", "allowSyntheticDefaultImports": true,
"miniprogram-api-typings", "baseUrl": "./",
"mini-types" "paths": {
] "@/*": ["src/*"],
} "~@/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist"],
"include": ["src"]
} }
This source diff could not be displayed because it is too large. You can view the blob instead.
{ {
"name": "my-project", "name": "wu-ui",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "npm run dev:h5", "serve": "npm run dev:mp-weixin",
"build": "npm run build:h5", "build": "npm run build:mp-weixin",
"build:pre": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin VUE_APP_PRE_ENV=pre vue-cli-service uni-build",
"build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build", "build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",
"build:custom": "cross-env NODE_ENV=production uniapp-cli custom", "build:custom": "cross-env NODE_ENV=production uniapp-cli custom",
"build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 UNI_OUTPUT_DIR=dist/ vue-cli-service uni-build", "build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
"build:mp-360": "cross-env NODE_ENV=production UNI_PLATFORM=mp-360 vue-cli-service uni-build", "build:mp-360": "cross-env NODE_ENV=production UNI_PLATFORM=mp-360 vue-cli-service uni-build",
"build:mp-alipay": "cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build", "build:mp-alipay": "cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build",
"build:mp-baidu": "cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build", "build:mp-baidu": "cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build",
"build:mp-jd": "cross-env NODE_ENV=production UNI_PLATFORM=mp-jd vue-cli-service uni-build",
"build:mp-kuaishou": "cross-env NODE_ENV=production UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build", "build:mp-kuaishou": "cross-env NODE_ENV=production UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build",
"build:mp-lark": "cross-env NODE_ENV=production UNI_PLATFORM=mp-lark vue-cli-service uni-build",
"build:mp-qq": "cross-env NODE_ENV=production UNI_PLATFORM=mp-qq vue-cli-service uni-build", "build:mp-qq": "cross-env NODE_ENV=production UNI_PLATFORM=mp-qq vue-cli-service uni-build",
"build:mp-toutiao": "cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build", "build:mp-toutiao": "cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build",
"build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build", "build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build",
"build:mp-xhs": "cross-env NODE_ENV=production UNI_PLATFORM=mp-xhs vue-cli-service uni-build", "build:mp-weixin:dev": "cross-env NODE_ENV=production VUE_APP_API_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build",
"build:quickapp-native": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build", "build:quickapp-native": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build",
"build:quickapp-webview": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build", "build:quickapp-webview": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build",
"build:quickapp-webview-huawei": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build", "build:quickapp-webview-huawei": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build",
"build:quickapp-webview-union": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build", "build:quickapp-webview-union": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build",
"dev:app-plus": "cross-env NODE_ENV=development UNI_PLATFORM=app-plus vue-cli-service uni-build --watch", "dev:app-plus": "cross-env NODE_ENV=development UNI_PLATFORM=app-plus vue-cli-service uni-build --watch",
"dev:custom": "cross-env NODE_ENV=development uniapp-cli custom", "dev:custom": "cross-env NODE_ENV=development uniapp-cli custom",
"dev:h5": "cross-env VUE_APP_API_ENV=development VUE_APP_Module=all UNI_PLATFORM=h5 vue-cli-service uni-serve", "dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve",
"dev:mp-360": "cross-env NODE_ENV=development UNI_PLATFORM=mp-360 vue-cli-service uni-build --watch", "dev:mp-360": "cross-env NODE_ENV=development UNI_PLATFORM=mp-360 vue-cli-service uni-build --watch",
"dev:mp-alipay": "cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch", "dev:mp-alipay": "cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch --minimize",
"dev:mp-baidu": "cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch", "dev:mp-baidu": "cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch --minimize",
"dev:mp-jd": "cross-env NODE_ENV=development UNI_PLATFORM=mp-jd vue-cli-service uni-build --watch",
"dev:mp-kuaishou": "cross-env NODE_ENV=development UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build --watch", "dev:mp-kuaishou": "cross-env NODE_ENV=development UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build --watch",
"dev:mp-lark": "cross-env NODE_ENV=development UNI_PLATFORM=mp-lark vue-cli-service uni-build --watch",
"dev:mp-qq": "cross-env NODE_ENV=development UNI_PLATFORM=mp-qq vue-cli-service uni-build --watch", "dev:mp-qq": "cross-env NODE_ENV=development UNI_PLATFORM=mp-qq vue-cli-service uni-build --watch",
"dev:mp-toutiao": "cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch", "dev:mp-toutiao": "cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch",
"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch", "dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize",
"dev:mp-xhs": "cross-env NODE_ENV=development UNI_PLATFORM=mp-xhs vue-cli-service uni-build --watch",
"dev:quickapp-native": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-native vue-cli-service uni-build --watch", "dev:quickapp-native": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-native vue-cli-service uni-build --watch",
"dev:quickapp-webview": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview vue-cli-service uni-build --watch", "dev:quickapp-webview": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview vue-cli-service uni-build --watch",
"dev:quickapp-webview-huawei": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch", "dev:quickapp-webview-huawei": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch",
...@@ -46,72 +42,92 @@ ...@@ -46,72 +42,92 @@
"test:ios": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=ios jest -i", "test:ios": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=ios jest -i",
"test:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu jest -i", "test:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu jest -i",
"test:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin jest -i", "test:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin jest -i",
"start": "node build/index.js" "start": "node build/index.js",
"init": "node build/init.js",
"wxci": "npm run build:mp-weixin && node ./wxCI.js"
}, },
"dependencies": { "dependencies": {
"@dcloudio/uni-app": "^2.0.2-3061820230117002", "@dcloudio/uni-app-plus": "2.0.0-28920200923001",
"@dcloudio/uni-app-plus": "^2.0.2-3061820230117002", "@dcloudio/uni-h5": "2.0.0-28920200923001",
"@dcloudio/uni-h5": "^2.0.2-3061820230117002", "@dcloudio/uni-helper-json": "*",
"@dcloudio/uni-i18n": "^2.0.2-3061820230117002", "@dcloudio/uni-i18n": "^2.0.2-3061320221209001",
"@dcloudio/uni-mp-360": "^2.0.2-3061820230117002", "@dcloudio/uni-mp-360": "2.0.0-28920200923001",
"@dcloudio/uni-mp-alipay": "^2.0.2-3061820230117002", "@dcloudio/uni-mp-alipay": "2.0.0-28920200923001",
"@dcloudio/uni-mp-baidu": "^2.0.2-3061820230117002", "@dcloudio/uni-mp-baidu": "2.0.0-28920200923001",
"@dcloudio/uni-mp-jd": "^2.0.2-3061820230117002", "@dcloudio/uni-mp-qq": "2.0.0-28920200923001",
"@dcloudio/uni-mp-kuaishou": "^2.0.2-3061820230117002", "@dcloudio/uni-mp-toutiao": "2.0.0-28920200923001",
"@dcloudio/uni-mp-lark": "^2.0.2-3061820230117002", "@dcloudio/uni-mp-vue": "2.0.0-28920200923001",
"@dcloudio/uni-mp-qq": "^2.0.2-3061820230117002", "@dcloudio/uni-mp-weixin": "2.0.0-28920200923001",
"@dcloudio/uni-mp-toutiao": "^2.0.2-3061820230117002", "@dcloudio/uni-quickapp-native": "2.0.0-28920200923001",
"@dcloudio/uni-mp-vue": "^2.0.2-3061820230117002", "@dcloudio/uni-quickapp-webview": "2.0.0-28920200923001",
"@dcloudio/uni-mp-weixin": "^2.0.2-3061820230117002", "@dcloudio/uni-stat": "2.0.0-28920200923001",
"@dcloudio/uni-mp-xhs": "^2.0.2-3061820230117002", "@vue/babel-preset-app": "^5.0.8",
"@dcloudio/uni-quickapp-native": "^2.0.2-3061820230117002", "@vue/shared": "^3.0.0-rc.4",
"@dcloudio/uni-quickapp-webview": "^2.0.2-3061820230117002", "core-js": "^3.6.5",
"@dcloudio/uni-stacktracey": "^2.0.2-3061820230117002", "miniprogram-ci": "^1.8.35",
"@dcloudio/uni-stat": "^2.0.2-3061820230117002", "regenerator-runtime": "^0.12.1",
"@dcloudio/uni-ui": "^1.4.26",
"@vue/shared": "^3.0.0",
"core-js": "^3.8.3",
"flyio": "^0.6.2",
"sa-sdk-alipaymini": "^1.2.0", "sa-sdk-alipaymini": "^1.2.0",
"sa-sdk-javascript": "^1.14.5",
"sa-sdk-miniprogram": "^1.14.5", "sa-sdk-miniprogram": "^1.14.5",
"sa-sdk-smartprogram": "0.4.0-rc", "sa-sdk-smartprogram": "0.4.0-rc",
"uuid": "3.4.0", "uuid": "3.4.0",
"vue": ">= 2.6.14 < 2.7", "vue": "^2.6.11",
"vuex": "^3.2.0" "vuex": "^3.2.0"
}, },
"devDependencies": { "devDependencies": {
"@dcloudio/types": "^3.3.2", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1",
"@dcloudio/uni-automator": "^2.0.2-3061820230117002", "@babel/plugin-proposal-optional-chaining": "^7.12.7",
"@dcloudio/uni-cli-i18n": "^2.0.2-3061820230117002", "@commitlint/cli": "^13.2.1",
"@dcloudio/uni-cli-shared": "^2.0.2-3061820230117002", "@commitlint/config-angular": "^13.2.0",
"@dcloudio/uni-helper-json": "*", "@dcloudio/types": "*",
"@dcloudio/uni-migration": "^2.0.2-3061820230117002", "@dcloudio/uni-automator": "2.0.0-28920200923001",
"@dcloudio/uni-template-compiler": "^2.0.2-3061820230117002", "@dcloudio/uni-cli-shared": "2.0.0-28920200923001",
"@dcloudio/vue-cli-plugin-hbuilderx": "^2.0.2-3061820230117002", "@dcloudio/uni-migration": "2.0.0-28920200923001",
"@dcloudio/vue-cli-plugin-uni": "^2.0.2-3061820230117002", "@dcloudio/uni-template-compiler": "2.0.0-28920200923001",
"@dcloudio/vue-cli-plugin-uni-optimize": "^2.0.2-3061820230117002", "@dcloudio/uni-ui": "^1.2.10",
"@dcloudio/webpack-uni-mp-loader": "^2.0.2-3061820230117002", "@dcloudio/vue-cli-plugin-hbuilderx": "2.0.0-28920200923001",
"@dcloudio/webpack-uni-pages-loader": "^2.0.2-3061820230117002", "@dcloudio/vue-cli-plugin-uni": "2.0.0-28920200923001",
"@vue/cli-plugin-babel": "~5.0.0", "@dcloudio/vue-cli-plugin-uni-optimize": "2.0.0-28920200923001",
"@vue/cli-service": "~5.0.0", "@dcloudio/webpack-uni-mp-loader": "2.0.0-28920200923001",
"@dcloudio/webpack-uni-pages-loader": "2.0.0-28920200923001",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.11.0", "babel-plugin-import": "^1.11.0",
"cross-env": "^7.0.2", "cross-env": "^7.0.3",
"eslint": "^7.17.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.4.1",
"husky": "^4.2.5",
"inquirer": "^8.2.0", "inquirer": "^8.2.0",
"jest": "^25.4.0", "jest": "^25.4.0",
"lint-staged": "^10.2.11",
"mini-types": "*", "mini-types": "*",
"miniprogram-api-typings": "*", "miniprogram-api-typings": "*",
"npm": "^8.1.4",
"postcss-comment": "^2.0.0", "postcss-comment": "^2.0.0",
"sass": "^1.49.8", "sass": "^1.26.11",
"sass-loader": "^8.0.2", "sass-loader": "^10.0.2",
"uni-read-pages": "^1.0.5", "less": "^3.0.4",
"uni-simple-router": "^2.0.8-beta.4", "less-loader": "^5.0.0",
"vue-template-compiler": ">= 2.6.14 < 2.7" "vue-template-compiler": "^2.6.11"
}, },
"browserslist": [ "browserslist": [
"Android >= 4.4", "Android >= 4",
"ios >= 9" "ios >= 8"
], ],
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -e $HUSKY_GIT_PARAMS"
}
},
"uni-app": { "uni-app": {
"scripts": {} "scripts": {}
} }
......
const path = require('path') const path = require("path");
const webpack = require('webpack') module.exports = {
const config = { parser: require("postcss-comment"),
parser: require('postcss-comment'),
plugins: [ plugins: [
require('postcss-import')({ require("postcss-import")({
resolve (id, basedir, importOptions) { resolve(id, basedir, importOptions) {
if (id.startsWith('~@/')) { if (id.startsWith("~@/")) {
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3)) return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3));
} else if (id.startsWith('@/')) { } else if (id.startsWith("@/")) {
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2)) return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2));
} else if (id.startsWith('/') && !id.startsWith('//')) { } else if (id.startsWith("/") && !id.startsWith("//")) {
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1)) return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1));
} }
return id return id;
} }
}), }),
require('autoprefixer')({ require("autoprefixer")({
remove: process.env.UNI_PLATFORM !== 'h5' remove: process.env.UNI_PLATFORM !== "h5"
}), }),
require('@dcloudio/vue-cli-plugin-uni/packages/postcss') require("@dcloudio/vue-cli-plugin-uni/packages/postcss")
] ]
} };
if (webpack.version[0] > 4) {
delete config.parser
}
module.exports = config
import request from "../utils/request";
import config from "@/config";
const { kdspApi } = config;
export default {
saveGDTVID(data) {
return request.post(`${kdspApi}/api/kdsp/minipro/setRedisClick`, data);
},
getGDTVID(data) {
return request.get(`${kdspApi}/api/kdsp/minipro/getRedisClick?wechatOpenId=${data}`);
},
uploadAdData(data) {
return request.post(`${kdspApi}/api/kdsp/minipro/addUserAction`, data);
},
createOrderRecord(data) {
return request.post(`${kdspApi}/api/kdsp/minipro/addClickRequest`, data);
}
};
import request from "../utils/request";
import config from "@/config";
const { yxmGateway } = config;
export default {
addProduct(data) {
return request.post(`${yxmGateway}/api/kdsp/shop-cart/add-update`, data);
}
};
import config from '@/config'; import request from "../utils/request";
import http from '@/service/httpDecorator'; import config from "@/config";
const { yxmGwHost } = config; import { mpConfig } from "@/utils/mpConfig/types";
const { talosApi, yxmGateway } = config;
export default { export default {
// 提现
cashOut(data) {
return request.get(`${talosApi}/vcc/xyqb/mineMini`, data);
},
// 物流信息
orderLogistics(data) {
// return request.get("http://yapi.quantgroups.com/mock/351/api/kdsp/logistics/packages-list");
return request.get(`${yxmGateway}/api/kdsp/logistics/packages-list`, data);
},
// 用户订单确认收货接口
orderConfirm(data) {
return request.post(`${yxmGateway}/api/kdsp/order-info/receipt/confirm`, data);
},
// 用户订单取消接口【未付款】
orderCancel(data) {
return request.post(`${yxmGateway}/api/kdsp/order-info/cancel`, data);
},
// 用户订单取消接口【已付款】
orderUnfilledCancel(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/unfilled/cancel`, data);
},
// 用户订单取消接口【已付款】
orderUnfilledCancelV2(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/unfilled/cancel/v2`, data);
},
// 订单取消原因查询接口
orderCancelList(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/cancel-reason/query`, data);
},
// 订单取消原因查询接口
orderCancelListV2(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/paid-cancel-props/query`, data, {
hideToast: true
});
},
// 已发货申请退款催办接口
orderRemindCancel(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/remindCancel`, data);
},
// 撤销取消订单申请
cancelRevoke(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/unfilled/cancel-revoke`, data);
},
// 取消/售后,获取是否需要签订合同
orderQueryNote(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/queryNote`, data);
},
// 订单详情查询接口
orderDetail(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/detail/query`, data);
},
// 用户订单列表查询接口
orderList(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/list/query`, data, {
hideLoading: true
});
},
// 获取信用钱包用户信息
xhkInfo(data) {
return request.get(`${yxmGateway}/api/kdsp/profile/vcc/user-account`, data);
},
// 我的 查询各状态订单数量
orderInfo(data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/status-number`, data);
},
// 微信小程序登录
login(data) {
return request.post(`${yxmGateway}${mpConfig.loginUrl}`, data, {
emulateFormData: true
});
},
// 注册
register(data) {
// 登录接口添加utm_source
getCurrentPages().forEach(item => {
if (item.options?.utm_source) {
data.utm_source = item.options?.utm_source;
}
});
return request.post(`${yxmGateway}${mpConfig.registerUrl}`, data);
},
getAvatar(data) {
return request.post(`${yxmGateway}/api/kdsp/wx/mini-app/avatar`, data);
},
loadArea(id = "") {
return request.get(`${yxmGateway}/api/kdsp/addr/query?addrId=${id}`);
},
saveAddress(data) { saveAddress(data) {
return http.post(`${yxmGwHost}/api/kdsp/addr/receiver/add_edit`, data); return request.post(`${yxmGateway}/api/kdsp/addr/receiver/add_edit`, data);
}, },
getAddressList() { getAddressList() {
return http.get(`${yxmGwHost}/api/kdsp/addr/receiver/list`); return request.get(`${yxmGateway}/api/kdsp/addr/receiver/list`);
}, },
deleteAddress(addrReceiverId) { deleteAddress(addrReceiverId) {
return http.post(`${yxmGwHost}/api/kdsp/addr/receiver/delete`, { return request.post(`${yxmGateway}/api/kdsp/addr/receiver/delete`, {
addrReceiverId addrReceiverId
}); });
}, },
// 地址级联查询 apiTest(data) {
zoneList: params => { return request.get(`${talosApi}/activity/commonly/free-goods/list`, data);
return http.get(`${yxmGwHost}/api/kdsp/addr/query?addrId=${params}`); },
// 获取首页活动弹窗
getUserPopup() {
return request.get(
`${yxmGateway}/api/kdsp/app-config-push/profile/popup`,
{
page: "profile"
},
{
hideLoading: true
}
);
},
// 注销登录
logout(data) {
return request.post(`${yxmGateway}/api/kdsp/user/user-logged-off`, data);
},
// 退出登录
logoutUser(data) {
return request.post(`${yxmGateway}/api/kdsp/logout/user`, data);
} }
}; };
import request from "../utils/request";
import config from "@/config";
const { yxmGateway } = config;
const submit = function(data) {
return request.post(`${yxmGateway}/api/kdsp/order-info/apply-refund`, data);
};
export { submit };
import config from '@/config'; import request from "../utils/request";
import http from '@/service/httpDecorator'; import config from "@/config";
import uiTrack from '@/service/sa.service'; const { yxmGateway } = config;
import { dealSmDeviceId } from '@/service/shumei.service';
const { yxmGwHost } = config;
export const getCouponList = async params => { export const getCouponList = params => {
const scDeviceId = await uiTrack.run('saDeviceId'); return request.get(`${yxmGateway}/api/kdsp/coupon/user-coupons`, params, {
return http.get(`${yxmGwHost}/api/kdsp/coupon/user-coupons`, { hideLoading: true
params,
customHeader: {
scDeviceId
}
}); });
}; };
export const getGiftCardList = data => { // // 我的礼品卡
return http.post(`${yxmGwHost}/api/kdsp/card/list`, data); export const getGiftCardList = function(data) {
}; return request.post(`${yxmGateway}/api/kdsp/card/list`, data, {
hideLoading: true
export const getGiftCardDetail = data => { });
console.log(data);
return http.post(`${yxmGwHost}/api/kdsp/card/io`, data);
}; };
export const exchange = params => {
export const pickupCoupon = async data => { return request.post(`${yxmGateway}/api/kdsp/coupon/pickup-code`, params, {
const smDeviceId = (await dealSmDeviceId()) || ''; reportDeviceId: true
data.shumeiDeviceId = smDeviceId; });
return http.post(`${yxmGwHost}/api/kdsp/coupon/pickup-batch`, data);
}; };
export const getCouponDesc = () => {
export const pickupCouponBySkuNo = async data => { return request.get(`${yxmGateway}/api/kdsp/coupon/getDescriptionOfExchangeCode`);
const smDeviceId = (await dealSmDeviceId()) || '';
data.tongdunDeviceId = smDeviceId;
return http.post(`${yxmGwHost}/api/kdsp/coupon/skuInfoPickup`, data);
}; };
import request from "../utils/request";
import config from "@/config";
const { vccHost, yxmGateway } = config;
// 查询活体认证url
const getFaceUrl = function(token, from, orderNo) {
const callBackUrl = orderNo
? vccHost + token + "&fromXcxPage=" + from + "&orderNo=" + orderNo
: vccHost + token + "&fromXcxPage=" + from;
return request.get(`${yxmGateway}/api/kdsp/face/h5/face-url`, {
callBackUrl: callBackUrl
});
};
// const getNextUrl = function() {
// return request.get(`${talosApi}/vcc/xyqb_mall/credit_url`);
// };
// const getNextUrlKa = function(data) {
// return request.get(`${yxmGateway}/api/kdsp/ka/process/get-next-url`, data);
// };
export { getFaceUrl };
import config from '@/config'; /* eslint-disable space-before-function-paren */
import http from '@/service/httpDecorator'; /* eslint-disable prettier/prettier */
import uiTrack from '@/service/sa.service'; import request from "../utils/request";
const { yxmGwHost } = config; import config from "@/config";
const PAGE = 'home'; const { yxmGateway } = config;
export const getBanner = () => { // 获取banner
return http.get(`${yxmGwHost}/api/kdsp/appconfig/${PAGE}/topinfo`); const getBanner = function (data) {
///appconfig/home/topinfo
const page = "home";
return request.get(`${yxmGateway}/api/kdsp/appconfig/${page}/topinfo`, data, {
hideLoading: true
});
}; };
//获取动态内容【金刚区、运营专区等】【金刚区、运营专区-横向,运营专区-竖向, 通栏】 //获取动态内容【金刚区、运营专区等】【金刚区、运营专区-横向,运营专区-竖向, 通栏】
export const getContent = () => { const getContent = function (data) {
//页面:home-精选,discovery-发现,profile-我的 //页面:home-精选,discovery-发现,profile-我的
return http.get(`${yxmGwHost}/api/kdsp/appconfig/${PAGE}/content`); const page = "home";
return request.get(`${yxmGateway}/api/kdsp/appconfig/${page}/content`, data, {
hideLoading: true
});
}; };
export const getGoodsList = async data => { // 主页底纹词
const scDeviceId = await uiTrack.run('saDeviceId'); const getSearchBorderTxt = function (data) {
return http.get(`${yxmGwHost}/api/kdsp/recommend/goods-list`, { const page = "home";
params: data, return request.get(`${yxmGateway}/api/kdsp/appconfig/${page}/border`, data, {
customHeader: { hideLoading: true
scDeviceId
}
}); });
}; };
export const apiCategoryGoodsList = async data => { // 主页猜你喜欢列表
const scDeviceId = await uiTrack.run('saDeviceId'); const getGoodsList = function (data) {
return http.post(`${yxmGwHost}/api/kdsp/search/simple-result`, data, { const tenantId = +uni.getStorageSync("tenantId");
customHeader: { if (tenantId === 560867) {
scDeviceId, // 青海移动
'x-user-terminal': 'H5' return request.get(`${yxmGateway}/api/kdsp/recommend/goods-list`, data, {
} needScDeviceId: true,
hideLoading: true
});
} else {
// 羊小咩
// return request.get(`${talosApi}/vcc/xyqb/recommend/goods-list`, data, {
return request.get(`${yxmGateway}/api/kdsp/recommend/goods-list`, data, {
needScDeviceId: true,
hideLoading: true
});
}
};
const homeSearch = function (data, loading = true) {
return request.post(`${yxmGateway}/api/kdsp/search/result`, data, {
needScDeviceId: true,
hideLoading: loading
}); });
}; };
export const homeSearch = async data => { const getActivityInfo = function (data) {
const scDeviceId = await uiTrack.run('saDeviceId'); return request.post(`${yxmGateway}/api/kdsp/search/result/fee/calc`, data, {
// return http.post(`http://yapi.quantgroups.com/mock/305/vcc/xyqb/search/result`, data, { needScDeviceId: true,
// customHeader: { hideLoading: true
// scDeviceId
// }
// });
return http.post(`${yxmGwHost}/api/kdsp/search/result`, data, {
customHeader: {
scDeviceId
}
}); });
}; };
export const getActivityInfo = data => { const landingSearch = function (data) {
return http.post(`${yxmGwHost}/api/kdsp/search/result/fee/calc`, data, { return request.post(`${yxmGateway}/api/kdsp/search/result`, data, {
needScDeviceId: true, needScDeviceId: true,
hideLoading: true hideLoading: true
}); });
}; };
// 搜索--大家都在搜的关键词 // 搜索--大家都在搜的关键词
export const getTerms = data => { const getTerms = function (data) {
return http.get(`${yxmGwHost}/vcc/app/mall/search/page`, data); // return request.get(`${talosApi}/vcc/app/mall/search/page`, data);
return request.get(`${yxmGateway}/api/kdsp/search/page`, data);
};
// 商品详情页是否放开立即购买
///api/kdsp/order-info/miniOrder/hasOrder
const hasOrder = function (data) {
return request.get(`${yxmGateway}/api/kdsp/order-info/miniOrder/hasOrder`, data);
};
// 详情页基本信息--/api/kdsp/sku-info/detail/query
const detailInfo = function (data) {
// return request.get('http://yapi.quantgroups.com/mock/351/api/kdsp/sku-info/detail/query')
return request.get(`${yxmGateway}/api/kdsp/sku-info/detail/query`, data);
}; };
// 查询用户优惠券选择查询接口 http://yapi.quantgroups.com/project/645/interface/api/63019
export const getCouponChooseList = data => { // 详情页-猜你喜欢 /vcc/xyqb/recommend/like
return http.post(`${yxmGwHost}/api/kdsp/coupon/activity/choose-list/v3`, data); const goodsLike = function (data) {
// return request.get(`${talosApi}/vcc/xyqb/jd/recommend/like`, data, {
return request.get(`${yxmGateway}/api/kdsp/recommend/goods-detail/similarity`, data, {
needScDeviceId: true,
hideLoading: true
});
}; };
export const getLoginPopup = page => { const shopCartLike = function (data) {
return http.get(`${yxmGwHost}/api/kdsp/app-config-push/${page}/popup`); // return request.get(`${talosApi}/vcc/xyqb/jd/recommend/like`, data, {
return request.get(`${yxmGateway}/api/kdsp/recommend/goods-list`, data, {
needScDeviceId: true,
hideLoading: true
});
}; };
//.瓷片区一组四双列混排(新增,轮播)商品专题(新增,横板)商品专题(新增,竖板)
export const getLayout = async () => { // 商品详情地址列表
const scDeviceId = await uiTrack.run('saDeviceId'); const addrList = function (data) {
return http.get( return request.get(`${yxmGateway}/api/kdsp/addr/receiver/list`, data, {
`${yxmGwHost}/api/kdsp/index/layout`, hideLoading: true
});
};
// 商品详情优惠券列表
const getCouponList = function (data) {
return request.get(`${yxmGateway}/api/kdsp/coupon/user-pickup`, data);
};
// 查询用户优惠券选择查询接口
const getCouponChooseList = function (data) {
return request.post(`${yxmGateway}/api/kdsp/coupon/activity/choose-list`, data);
};
// 商品详情--领取优惠券 /api/kdsp/coupon/user-pickup
const userPickupCoupon = function (data) {
return request.post(`${yxmGateway}/api/kdsp/coupon/pickup`, data, {
hideLoading: true,
reportDeviceId: true
});
};
// 获取首页活动弹窗
const getHomePopup = function () {
return request.get(
`${yxmGateway}/api/kdsp/app-config-push/home/popup`,
{ {
customHeader: { page: "home"
scDeviceId
}
}, },
{ {
'x-user-terminal': 'H5' hideLoading: true
} }
); );
}; };
//获取顶部信息 // 上报活动弹窗
export const getTopTab = () => { const uploadPopup = function (data) {
return http.get( return request.post(`${yxmGateway}/api/kdsp/app-config-push/report/notice`, data, {
`${yxmGwHost}/api/kdsp/index/top-tab`, hideLoading: true
});
};
const getVaildSubTmplIds = async tmplIds => {
const res = await wx.getSetting({
withSubscriptions: true
});
let {
subscriptionsSetting: { mainSwitch, itemSettings }
} = res;
if (mainSwitch) {
itemSettings = itemSettings || {};
const vaildTmplIds = tmplIds.filter(
item => !itemSettings[item] || itemSettings[item] !== "ban"
);
return vaildTmplIds;
}
};
const subscribe = async data => {
return request.post(`${yxmGateway}/api/kdsp/group-msg/subscribe`, data, {
hideLoading: true
});
};
const addSkuToCart = function (data) {
return request.post(`${yxmGateway}/api/kdsp/shop-cart/add-update`, data, {
hideLoading: true
});
};
// 获取购物车商品数量
const getCartCount = function () {
return request.get(
`${yxmGateway}/api/kdsp/shop-cart/count`,
{}, {},
{ {
'x-user-terminal': 'H5' hideLoading: true
} }
); );
}; };
// 获取频道信息
export const apiCategoryInfo = async id => { // 无效商品列表
const scDeviceId = await uiTrack.run('saDeviceId'); const getInvalidList = function (data) {
return http.get( return request.post(`${yxmGateway}/api/kdsp/shop-cart/list/invalid`, data, {
`${yxmGwHost}/api/kdsp/index/top-tab/category?id=${id}`, hideLoading: true
});
};
// 青海获取礼品卡余额接口
const getGiftCard = () => {
return request.get(`${yxmGateway}/api/kdsp/user/card-coupon`);
};
// 上报数据
const importOpenId = function (data) {
return request.post(`${yxmGateway}/api/kdsp/miniapp/saveWechatAppletInfo`, data, {
hideLoading: true,
hideToast: true
});
};
// 获取卡包部分信息(羊小咩)
const getWalletInfo = function () {
return request.get(`${yxmGateway}/api/kdsp/user/mine/my-wallet`, {
hideLoading: true,
hideToast: true
});
};
const getFincialData = () => {
return request.get(`${yxmGateway}/api/kdsp/miniapp/jump/vcc/mini`,
{},
{ {
customHeader: { header: {
scDeviceId appChannel: 'miniapp',
appName: "xinyongqianbao",
userId: uni.getStorageSync("userAuthInfo").userId,
uuid: uni.getStorageSync("userAuthInfo").uuid
} }
},
{
'x-user-terminal': 'H5'
} }
); );
}; };
const getSchemaCode = params => {
return request.post(`${yxmGateway}/api/kdsp/miniapp/jump/vcc/mini/schema/code`, params,
{
header: {
appName: "xinyongqianbao",
userId: uni.getStorageSync("userAuthInfo").userId,
uuid: uni.getStorageSync("userAuthInfo").uuid
}
});
};
const getContract = () => {
return request.get(`${yxmGateway}/api/kdsp/contract/view`);
}
const smEvent = data => {
return request.post(`${yxmGateway}/api/kdsp/shumei/eventDataServer/report`, data);
};
// kdsp存数美设备id
const uploadSMDeviceID = data => {
return request.post(`${yxmGateway}/api/kdsp/fraud/borderColor`, data);
};
// 不敢兴趣 export {
// http://yapi.quantgroups.com/project/645/interface/api/62774 getSearchBorderTxt,
export const getReport = data => { getBanner,
return http.post(`${yxmGwHost}/api/kdsp/data/report`, data); getContent,
getGoodsList,
homeSearch,
getActivityInfo,
getTerms,
hasOrder,
detailInfo,
addrList,
getCouponList,
getCouponChooseList,
userPickupCoupon,
goodsLike,
landingSearch,
getCartCount,
addSkuToCart,
getInvalidList,
getHomePopup,
getVaildSubTmplIds,
uploadPopup,
subscribe,
shopCartLike,
getGiftCard,
importOpenId,
getWalletInfo,
getFincialData,
getSchemaCode,
getContract,
smEvent,
uploadSMDeviceID
}; };
import request from "../utils/request";
import config from "@/config";
const { yxmGateway } = config;
// 根据id查询优惠券列表
const couponList = function(data) {
return request.get(`${yxmGateway}/api/kdsp/coupon/h5-qb/list`, data);
};
// 用户领取优惠券接口-批量
const couponPickup = function(data) {
return request.post(`${yxmGateway}/api/kdsp/coupon/pickup-batch`, data, {
reportDeviceId: true
});
};
// 搜索接口_result
const searchGoodsList = function(data) {
return request.post(`${yxmGateway}/api/kdsp/search/result`, data);
};
// 用户领取优惠券状态查询
const searchCoupon = function(data) {
return request.get(`${yxmGateway}/api/kdsp/coupon/pickup-status`, data);
};
// KA流程节点
const kaGetNextUrl = function(data) {
let options = {
sonVccChannel: true
};
return request.get(`${yxmGateway}/api/kdsp/ka/process/get-next-url`, data, options);
};
// KA流程节点_查询流程是否走完
const kaFlow = function(data) {
let options = {
sonVccChannel: true
};
return request.get(`${yxmGateway}/api/kdsp/ka/process/get-status`, data, options);
};
// 流程节点_返回商品页面临时支持1个月(高价)
const lableInfoIdsExpensive = function(data) {
return request.get(`${yxmGateway}/api/kdsp/ka/process/get-landing-page-temp`, data);
};
// 获取ka配置
const getKaData = function(data) {
return request.get(`${yxmGateway}/api/kdsp/ka/info/getDetail`, data);
};
// 验证是否是白名单
const getWhiteUser = function(data) {
return request.get(`${yxmGateway}/api/kdsp/ka/user/getWhiteUser`, data);
};
// 根据md5获取百人团url
const getGroupBuyUrl = function(m) {
return request.get(`${yxmGateway}/api/kdsp/playBill/getPlayBillUrl?m=${m}`);
};
export {
searchCoupon,
couponList,
couponPickup,
searchGoodsList,
kaGetNextUrl,
kaFlow,
lableInfoIdsExpensive,
getKaData,
getWhiteUser,
getGroupBuyUrl
};
import http from '@/service/httpDecorator'; import request from "../utils/request";
import config from '@/config'; import config from "@/config";
const { xinchengHost, yxmGwHost } = config; const { yxmGateway } = config;
// max会员 // let kdspApi = "http://yapi.quantgroups.com/mock/351";
export const maxMember = {
// max会员邀请页接口 - 基本信息接口 // 我的页面查询会员、优惠券信息
invitaionInfo: () => { // 接口存在与app显示不一致情况,该接口提升version
return http.get(`${xinchengHost}/api/kdsp/maxMember/maxMemberInvitaionInfo`); const queryMemberAndCouponInfo = () => {
}, // return request.get(
// MAX会员激活页 - 激活信息 // "http://yapi.quantgroups.com/mock/351/api/kdsp/userBenefits/getCurrentLevelInfo"
activateInfo: params => { // );
return http.post(`${xinchengHost}/api/kdsp/maxMember/addMaxMember`, params); return request.get(
}, `${yxmGateway}/api/kdsp/userBenefits/getCurrentLevelInfo`,
// max会员详情 {},
memberInfo: () => { {
return http.get(`${xinchengHost}/api/kdsp/maxMember/getMaxMemberInfo`); header: {
}, version: "8.6.00"
// 优惠券展示 }
couponList: () => { }
return http.get(`${xinchengHost}/api/kdsp/max/member/coupon`); );
}, };
// max会员-商品
goodsList: params => { // 会员中心查询
return http.get(`${xinchengHost}/api/kdsp/max/member/goods`, { params }); const queryMemberCenterInfo = () => {
}, return request.get(
// 会员商品品类 `${yxmGateway}/api/kdsp/userBenefits/center/getUserCenterInfo`,
categoryList: () => { {},
return http.get(`${xinchengHost}/api/kdsp/max/member/goods/category`); {
}, header: {
// 加购接口 version: "8.6.00"
addShopCart: params => { }
return http.post(`${xinchengHost}/api/kdsp/shop-cart/add-update`, params); }
}, );
// 获取用户max会员和普通会员信息 };
// http://yapi.quantgroups.com/project/351/interface/api/58329
getUserAndMaxInfo: () => { // 获取用户会员权益明细
return http.get(`${yxmGwHost}/api/kdsp/userBenefits/center/getUserAndMaxInfo`); const queryMemberBenefitsDetail = () => {
} return request.get(
`${yxmGateway}/api/kdsp/userBenefits/rewardDetail/getBenefitsDetail`,
{},
{
header: {
version: "8.6.00"
}
}
);
};
// 获取用户会员权益值列表
const queryBenefitsDiscountDetail = data => {
return request.get(
`${yxmGateway}/api/kdsp/userBenefitsDiscountDetail/getBenefitsDiscountDetail`,
data,
{
header: {
version: "8.6.00"
}
}
);
// return request.get(
// `http://yapi.quantgroups.com/mock/351/api/kdsp/userBenefitsDiscountDetail/getBenefitsDiscountDetail`,
// data
// );
};
// 获取成长值信息
const queryPointDetail = () => {
return request.get(`${yxmGateway}/api/kdsp/userBenefits/getPointDetail`);
};
// 成长值(积分)列表
const getBenefitsDetail = () => {
return request.get(`${yxmGateway}/api/kdsp/userBenefitsDetail/getBenefitsDetail`);
};
// 获取礼品卡消费记录
const getConsumptions = params => {
return request.post(`${yxmGateway}/api/kdsp/card/io`, params);
};
// 领取优惠券
const pickupCoupon = params => {
return request.post(`${yxmGateway}/api/kdsp/coupon/pickup-batch`, params, {
reportDeviceId: true
});
};
export {
queryMemberAndCouponInfo,
queryMemberBenefitsDetail,
queryPointDetail,
queryMemberCenterInfo,
getConsumptions,
pickupCoupon,
queryBenefitsDiscountDetail,
getBenefitsDetail
}; };
import config from '@/config'; import request from "../utils/request";
import http from '@/service/httpDecorator'; import config from "@/config";
const { yxmGwHost } = config; const { yxmGateway, SHARE_CHANNEL } = config;
export default { export const confirmOrder = data => {
// 订单列表 return request.post(`${yxmGateway}/api/kdsp/shop-cart/order-confirm/page/v2`, data);
orderList(data) { };
return http.get(`${yxmGwHost}/api/kdsp/order-info/list/query`, { params: data });
},
// 申请退款 是否签合同
queryNote(data) {
return http.get(`${yxmGwHost}/api/kdsp/order-info/queryNote`, { params: data });
},
// 用户订单确认收货接口
orderConfirm(data) {
return http.post(`${yxmGwHost}/api/kdsp/order-info/receipt/confirm`, data);
},
// 用户订单取消接口【未付款】
orderCancel(data) {
return http.post(`${yxmGwHost}/api/kdsp/order-info/cancel`, data);
},
// 用户订单取消接口【未发货】
orderUnfilledCancel(data) {
return http.get(`${yxmGwHost}/api/kdsp/order-info/unfilled/cancel`, { params: data });
},
// 用户订单取消接口【未发货】
orderUnfilledCancelV2(data) {
return http.get(`${yxmGwHost}/api/kdsp/order-info/unfilled/cancel/v2`, { params: data });
},
// 订单取消原因查询接口
orderCancelReason(params) {
return http.get(`${yxmGwHost}/api/kdsp/order-info/cancel-reason/query`, { params });
},
// 订单取消原因查询接口
orderCancelReasonV2(data) {
return http.get(`${yxmGwHost}/api/kdsp/order-info/paid-cancel-props/query`, { params: data });
},
// 订单详情查询接口
orderDetail(data) {
return http.get(`${yxmGwHost}/api/kdsp/order-info/detail/query`, { params: data });
},
// 物流详情查询接口
expressDetail(data) {
// return http.get('http://yapi.quantgroups.com/mock/351/api/kdsp/logistics/packages-list');
return http.get(`${yxmGwHost}/api/kdsp/logistics/packages-list`, { params: data });
},
// 我的 查询各状态订单数量
orderInfo() {
return http.get(`${yxmGwHost}/api/kdsp/order-info/status-number`);
},
confirmOrder(data) {
return http.post(`${yxmGwHost}/api/kdsp/shop-cart/order-confirm/page/v3`, data);
},
// todo 8.8.90 开始接口升级 export const orderSubmit = data => {
orderSubmit(data) { const options = {
return http.post(`${yxmGwHost}/api/kdsp/order-info/e/submit`, data, { encrypt: true
customHeader: { };
version: '8.8.00' // #ifdef MP-WEIXIN
} const sceneList = [1007, 1008, 1011, 1012, 1013, 1036, 1044, 1047, 1048, 1049, 1058];
}); const currentScene = wx.getEnterOptionsSync().scene;
}, if (sceneList.indexOf(currentScene) > -1) {
// 物流公司列表 options.customizeChannel = SHARE_CHANNEL;
companyList() {
return http.get(`${yxmGwHost}/api/kdsp/logistics/kd100/company-list`);
},
// 物流公司列表
getCompany(data) {
return http.get(`${yxmGwHost}/api/kdsp/logistics/kd100/`, { params: data });
},
// 售后原因查询
applyReason(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/apply-reason`, { params: data });
},
// 售后原因查询V2
applyReasonV2(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/v2/apply-reason`, { params: data });
},
// 售后退款金额试算
refundAmount(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/refund-amount`, { params: data });
},
getOrderSkuDetail(data) {
return http.get(`${yxmGwHost}/api/kdsp/order-sku/detail/query`, { params: data });
},
// 填写售后信息页面的查询接口
applyPageInfo(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/apply-page-info`, { params: data });
},
// 填写售后信息页面的查询v2接口
applyPageInfoV2(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/v2/apply-page-info`, { params: data });
},
// 提交申请售后
applySubmit(data) {
return http.post(`${yxmGwHost}/api/kdsp/after-service/apply`, data);
},
afterV2Detail(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/v2/detail`, { params: data });
},
// 订单申请退款
refundKepler(data) {
return http.post(`${yxmGwHost}/api/kdsp/order-info/apply-refund`, data);
},
// 查看售后详情
afterDetail(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/detail`, { params: data });
},
afterChangeHistory(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/change-history`, { params: data });
},
afterV2ChangeHistory(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/v2/change-history`, { params: data });
},
// 售后取消
applyCancel(data) {
return http.post(`${yxmGwHost}/api/kdsp/after-service/cancel`, data);
},
// 售后退货物流单信息填写 after-service/add-delivery-no
addDeliveryNo(data) {
return http.post(`${yxmGwHost}/api/kdsp/after-service/add-delivery-no`, data);
},
// 售后列表 after-service/list
afterList(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/service/list`, { params: data });
},
// 售后催办 after-service/reminder
afterReminder(data) {
return http.post(`${yxmGwHost}/api/kdsp/after-service/reminder`, data);
},
// 发货中催办取消订单
remindCancel(data) {
return http.get(`${yxmGwHost}/api/kdsp/order-info/remindCancel`, { params: data });
},
// 撤销取消订单申请
cancelRevoke(data) {
return http.get(`${yxmGwHost}/api/kdsp/order-info/unfilled/cancel-revoke`, {
params: data
});
},
//查询售后是否在有效期
applyExpired(data) {
return http.get(`${yxmGwHost}/api/kdsp/after-service/expired`, { params: data });
},
// 获取七牛token
getQiniuToken(data) {
return http.get(`${yxmGwHost}/api/kdsp/common/upload/token`, { params: data });
},
// 校验手机号是否为 推广员手机号
checkPromoterByMobile(phone) {
return http.get(`${yxmGwHost}/api/kdsp/self-mention/checkPromoterByMobile?phoneNo=${phone}`);
},
// 申请退运费
refundFreight(data) {
return http.post(`${yxmGwHost}/api/kdsp/after-service/apply-freight-fee`, data);
} }
// #endif
return request.post(`${yxmGateway}/api/kdsp/order-info/e/submit`, data, options);
};
// 校验手机号是否为 推广员手机号
export const checkPromoterByMobile = phone => {
return request.get(`${yxmGateway}/api/kdsp/self-mention/checkPromoterByMobile?phoneNo=${phone}`);
}; };
<template>
<view class="tip-ul">
<view class="tip-li tip-li-bottom">
感谢您选择羊小咩小程序,我们非常重视您的个人信息安全和隐私保护。依据最新法律要求,使用我们的产品前,请仔细阅读并同意
<text class="tip-li-yellow" @click="navTo($config('zhuCeUrl'))"> 《用户注册协议》</text>
<text class="tip-li-yellow" @click="navTo($config('yinSiUrl'))"> 《隐私政策》 </text>
,以便我们向您提供更优质的服务!
</view>
</view>
</template>
<script>
export default {
methods: {
navTo(jumpUrl) {
uni.navigateTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(jumpUrl))}`
});
}
}
};
</script>
<style scoped lang="scss">
.tip-ul {
.tip-li {
font-size: 28rpx;
line-height: 48rpx;
color: #141414;
}
.tip-li-bottom {
margin-bottom: 12rpx;
}
.tip-li-yellow {
color: #ec1500;
}
}
</style>
<template>
<uni-popup
ref="popup"
:z-index="9999999"
:overlay-style="{ zIndex: 9999999 }"
type="bottom"
:mask-click="false"
@close="close"
@open="open"
>
<view class="Tip" :style="tipHeight">
<view class="Tip__title">{{ title }}</view>
<view class="Tip__content">
<slot name="default" />
</view>
<view class="Tip__button">
<button class="Tip__button--cancel" @click="confirmEvent()">
{{ cancelText }}
</button>
<button class="Tip__button--confirm" @click="confirmEvent()">
{{ confirmText }}
</button>
</view>
</view>
</uni-popup>
</template>
<script>
import { uniPopup } from "@/components/uni-popup/uni-popup";
const CONFIRM_EVENT = "confirm";
export default {
components: {
uniPopup
},
props: {
title: {
type: String,
default: "欢迎使用羊小咩"
},
round: {
type: [Number, String],
default: 10
},
confirmText: {
type: String,
default: "同意"
},
cancelText: {
type: String,
default: "不同意"
},
closeAble: {
type: Boolean,
default: true
},
closeOnClickOverlay: {
type: Boolean,
default: false
}
},
data() {
return {
show: false
};
},
methods: {
open() {
this.show = true;
this.$refs.popup.open();
},
close() {
this.show = false;
this.$refs.popup.close();
},
confirmEvent() {
this.close();
const timer = setTimeout(() => {
this.$emit(CONFIRM_EVENT);
clearTimeout(timer);
}, 200);
}
}
};
</script>
<style scoped lang="scss">
::v-deep .u-popup {
z-index: 9999999999;
}
.uni-popup {
z-index: 9999999;
background: #fff;
}
.Tip {
padding: 20rpx 48rpx;
width: 100%;
height: auto;
padding-bottom: env(safe-area-inset-bottom);
border-radius: 40rpx 40rpx 0px 0px;
box-sizing: border-box;
display: flex;
flex-direction: column;
background: #fff;
&__title {
text-align: center;
line-height: 88rpx;
font-size: 32rpx;
font-weight: 500;
color: #323233;
}
&__content {
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding-top: 16rpx;
}
&__button {
display: flex;
margin-bottom: 40rpx;
button {
font-size: 28rpx;
background-color: none;
width: 332rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 200rpx;
margin-top: 50rpx;
&::after {
border: none;
}
}
&--confirm {
color: $white;
background: linear-gradient(270deg, #ff5d00 0%, #ff1900 100%);
}
&--cancel {
background-color: transparent;
color: #141414;
border-radius: 4px;
border: 2rpx solid #999999;
margin-right: 24rpx;
}
}
}
</style>
<template>
<view>
<uni-popup
ref="popup"
type="bottom"
:title="title"
:mask-click="true"
closeable
@change="onChange"
>
<view class="action-sheet">
<!-- #ifdef MP-ALIPAY -->
<slot />
<!-- #endif -->
<!-- #ifndef MP-ALIPAY -->
<slot>
<view class="content" />
</slot>
<!-- #endif -->
<slot name="footer">
<view v-if="actionText" class="footer">
<button class="action-btn" type="default" @click="onConfirm">
{{ actionText }}
</button>
</view>
</slot>
</view>
</uni-popup>
</view>
</template>
<script>
import { uniPopup } from "@/components/uni-popup/uni-popup";
export default {
name: "ActionSheet",
components: {
uniPopup
},
props: {
title: {
type: String,
default: ""
},
showClose: {
type: Boolean,
default: true
},
closeIconSize: {
type: Number,
default: 18
},
actionText: {
type: String,
default: ""
}
},
methods: {
/**
* @exposed-api
*/
open() {
this.$refs.popup.open();
},
/**
* @exposed-api
*/
close() {
this.$refs.popup.close();
},
onChange(e) {
// 点击遮罩关闭时触发
if (e.show === false) {
this.$emit("close");
}
},
onConfirm() {
this.$emit("confirm");
this.close();
},
onClose() {
this.close();
this.$emit("close");
}
}
};
</script>
<style lang="scss" scoped>
.action-sheet {
background-color: $uni-bg-color;
// border-radius: 12rpx 12rpx 0 0;
display: flex;
flex-direction: column;
.header {
padding: 36rpx 36rpx 20rpx 36rpx;
display: flex;
flex: 1;
flex-direction: row;
justify-content: center;
align-items: center;
.title {
flex: 1;
text-align: center;
font-size: 32rpx;
line-height: 44rpx;
color: #333;
}
.close {
color: #dcdcdc;
}
}
.content {
padding: 0 30rpx;
}
.footer {
padding: 20rpx 30rpx;
.action-btn {
@include primary-bg;
color: white;
font-size: $uni-font-size-base;
font-weight: bold;
border-radius: $uni-border-radius-xl;
}
}
}
</style>
<template>
<view v-if="modalData.img" class="activityModal">
<view class="content">
<image :src="modalData.img" mode="widthFix" @click="goto" />
</view>
<view class="close">
<i class="iconfont icon-close-line" @click="$emit('close')" />
</view>
</view>
</template>
<script>
import { saTrackEvent } from "@/utils/sa.js";
export default {
props: {
modalData: {
type: Object,
default() {
return {};
}
},
pageName: String
},
mounted() {
saTrackEvent("MINI_PagePopupWindowExposure", {
popupwindow_id: this.modalData.uid,
popupwindow_name: this.modalData.componentName,
page_name: this.pageName
});
},
methods: {
goto() {
this.$emit("goto", this.modalData);
}
}
};
</script>
<style scoped lang="scss">
.activityModal {
z-index: 9999;
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
.content {
max-width: 311px;
// max-height: 360px;
// background: $uni-bg-color;
border-radius: $uni-border-radius-sm * 4;
image {
max-width: 100%;
max-height: 100%;
border-radius: $uni-border-radius-sm * 4;
}
}
.close {
margin-top: $uni-spacing-col-md;
i {
font-size: 33px;
color: $white;
}
}
}
</style>
<template>
<view class="home-list">
<!-- <view class="home-list-container"> -->
<view
v-for="(item, index) in goodList"
:key="index"
class="Hl-container-item"
@click="toDetail(item, index)"
>
<view class="Hl-container-item-img">
<image lazy-load class="Hlc-item-img" mode="aspectFit" :src="item.goods.goodsImage" />
</view>
<view class="Hlc-item-title">
<text>{{ item.goods.goodsName }}</text>
</view>
<!-- 猜你喜欢商品标签 -->
<view class="Hlc-item-tag">
<view v-for="(tag, i) in item.goods.tagList" :key="i" class="Hlc-item-tag-wrap">
<span v-if="tag.type == 2" :key="i" class="Hlc-item-tag-normal">{{ tag.name }}</span>
<img
v-if="tag.type == 1"
mode="heightFix"
class="Hlc-item-tag-icon"
:src="tag.icon"
alt=""
/>
</view>
<img
v-if="item.userBenefitsLabelImgUrl"
:src="item.userBenefitsLabelImgUrl"
class="memberImg"
/>
</view>
<!-- 猜你喜欢商品标签 -->
<view class="Hlc-item-info">
<view class="Hlcu-info-left">
<text>¥</text>
<text>{{ item.goods.goodsSalePrice }}</text>
<text v-if="item.goods.saleCount">已售{{ item.goods.saleCount }}</text>
</view>
<view v-if="!noShare" class="Hlcu-info-right" @click.stop="goodsMaskIdx = index">
<view class="Hlcui-right-dot" />
<view class="Hlcui-right-dot" />
<view class="Hlcui-right-dot" />
</view>
</view>
<view
v-if="goodsMaskIdx === index && !noShare"
class="Hlc-item-mask"
@click.stop="goodsMaskIdx = -1"
>
<button
class="Hlci-mask-button"
open-type="share"
:data-shareinfo="item"
:data-goods="item"
@click.stop="toShare(item, index)"
>
<image src="https://img.lkbang.net/xcx/goods_share@2x.png" />
<text>分享好友</text>
</button>
<button v-if="isDelete" class="Hlci-mask-button" @click="delGoods(item, index)">
<image src="https://img.lkbang.net/xcx/no@2x.png" />
<text>不感兴趣</text>
</button>
</view>
</view>
<!-- </view> -->
</view>
</template>
<script>
import { debounce } from "@/utils";
import { saTrackEvent } from "@/utils/sa.js";
export default {
name: "GoodsCard",
props: {
list: {
type: Array,
default: () => []
},
isDelete: {
type: Boolean,
default: true
},
noShare: {
type: Boolean,
default: false
}
},
data() {
return {
goodsMaskIdx: -1,
goodList: []
};
},
watch: {
list: {
deep: true,
immediate: true,
handler(v) {
this.goodList = v;
}
}
},
methods: {
toShare(item, index) {
const currentPage = getCurrentPages();
saTrackEvent("PD_YXMMAEC_UserClickSelectionPageViewMoreBtn", {
page_id: currentPage[currentPage.length - 1].route,
commodity_id: item.goods.goodsId,
view_more_selection: "分享好友",
position_number: index
});
uni.reportAnalytics("c_selectionpageviewmorebtn", {
page_id: currentPage[currentPage.length - 1].route,
commodity_id: item.goods.goodsId,
view_more_selection: "分享好友",
position_number: index
});
},
delGoods(item, index) {
const currentPage = getCurrentPages();
saTrackEvent("PD_YXMMAEC_UserClickSelectionPageViewMoreBtn", {
page_id: currentPage[currentPage.length - 1].route,
commodity_id: item.goods.goodsId,
view_more_selection: "不感兴趣",
position_number: index
});
uni.reportAnalytics("c_selectionpageviewmorebtn", {
page_id: currentPage[currentPage.length - 1].route,
commodity_id: item.goods.goodsId,
view_more_selection: "不感兴趣",
position_number: index
});
this.goodList.splice(index, 1);
// this.$emit("update:goodsList", this.goodsList);
this.$api.msg("已减少此类信息推荐");
},
toDetail(good, index) {
const currentPage = getCurrentPages();
uni.reportAnalytics("c_selectionpagecommoditycard", {
page_id: currentPage[currentPage.length - 1].route,
commodity_id: good.goods.goodsId,
position_number: index,
uuid: uni.getStorageSync("userAuthInfo").uuid || "",
channel_id: uni.getStorageSync("vccChannel") || ""
});
saTrackEvent("PD_YXMMAEC_UserClickSelectionPageCommodityCard", {
page_id: currentPage[currentPage.length - 1].route,
commodity_id: good.goods.goodsId,
position_number: index
});
debounce(
uni.navigateTo({
url: `/pages/product/goodDetail?skuNo=${
good.goods.goodsId
}&count=1&receiverId=&goodsName=${encodeURIComponent(good.goods.goodsName)}&goodsImage=${
good.goods.goodsImage
}`
// url: `/pages/product/goodDetail?skuNo=144652147824&count=1&receiverId=&goodsName=${good.goods.goodsName}`
}),
300
);
}
}
};
</script>
<style lang="scss" scoped>
.home-list {
// &-container {
// padding-top: 20rpx;
// display: flex;
// justify-content: space-between;
// flex-wrap: wrap;
.Hl-container-item {
position: relative;
margin-bottom: 25rpx;
width: 339rpx;
background: #fff;
border-radius: 12rpx;
&-img {
height: 340rpx;
display: flex;
align-items: center;
}
.Hlc-item-img {
width: 100%;
height: 346rpx;
border-radius: 12rpx;
}
.Hlc-item-title {
height: 76rpx;
margin: 10rpx 20rpx 0rpx 14rpx;
text {
font-size: 26rpx;
line-height: 36rpx;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
.Hlc-item-tag {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
margin: -12rpx 0rpx 0rpx 14rpx;
&-normal {
display: inline-block;
font-size: 10px;
box-sizing: border-box;
border: 1rpx solid #ff5a4b;
color: #ff5a4b;
padding: 0px 4px;
border-radius: 3px;
margin-right: 5px;
line-height: 14px;
}
&-icon {
height: 28rpx;
margin-right: 5px;
vertical-align: middle;
}
}
.Hlc-item-info {
margin: 16rpx 20rpx 14rpx;
padding-bottom: 16rpx;
display: flex;
align-items: center;
justify-content: space-between;
.Hlcu-info-left {
display: flex;
align-items: flex-end;
text {
&:nth-child(1) {
font-size: 20rpx;
color: #ec3333;
font-weight: bold;
}
&:nth-child(2) {
margin-right: 4rpx;
font-size: 30rpx;
line-height: 34rpx;
color: #ec3333;
font-weight: bold;
}
&:nth-child(3) {
font-size: 19rpx;
line-height: 26rpx;
color: #999999;
text-align: right;
}
}
}
.Hlcu-info-right {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 6rpx;
// width: 66rpx;
width: 40rpx;
height: 40rpx;
.Hlcui-right-dot {
width: 6rpx;
height: 6rpx;
background: #d8d8d8;
border-radius: 50%;
}
// font-size: 35rpx;
// line-height: 26rpx;
// letter-spacing: -6rpx;
// color: #D8D8D8;
}
}
.Hlc-item-mask {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.4);
border-radius: 12rpx;
.Hlci-mask-button {
padding: 0 60rpx;
display: flex;
justify-content: space-between;
align-items: center;
width: 266rpx;
height: 60rpx;
border-radius: 31rpx;
font-size: 24rpx;
color: #333333;
&:first-child {
margin-bottom: 40rpx;
}
image {
width: 36rpx;
height: 36rpx;
}
}
}
}
// }
}
.memberImg {
width: 132.68rpx;
height: 28rpx;
}
</style>
<template>
<view v-if="isShow">
<view
class="goods-popup-box"
:style="{
transitionDuration: duration + 'ms',
opacity: contentOpacity || (type === 'center' ? 0 : 1),
transform: contentTransform || autoTransform,
zIndex: zIndex,
borderTopRightRadius:
type === 'center' || type === 'bottom' || type === 'left' ? radius + 'rpx' : 0,
borderTopLeftRadius:
type === 'center' || type === 'bottom' || type === 'right' ? radius + 'rpx' : 0,
borderBottomRightRadius:
type === 'center' || type === 'top' || type === 'left' ? radius + 'rpx' : 0,
borderBottomLeftRadius:
type === 'center' || type === 'top' || type === 'right' ? radius + 'rpx' : 0,
width: autoWidth,
height: autoHeight,
minWidth: width + 'rpx',
minHeight: height + 'rpx',
top: sizeChange && type === 'center' ? winReTop : autoTop,
bottom: autoBottom,
left: autoLeft,
right: autoRight,
backgroundColor: bgColor
}"
@tap.stop.prevent
@touchmove.stop.prevent
>
<view class="goods-popup-close">
<view v-if="title || desc" class="goods-popup-custom-head">
<view v-if="title" class="goods-popup-title">{{ title }}</view>
<view v-if="desc" class="goods-popup-desc">{{ desc }}</view>
</view>
<view class="goods-popup-custom-close" @tap="hide">
<span v-if="closeable" class="iconfont icon-close goods-popup-close-image" />
<!-- <image
v-if="closeable"
class="goods-popup-close-image"
src="https://img.lkbang.net/xcx/close.png"
/> -->
</view>
</view>
<scroll-view scroll-y class="goods-popup-slot">
<view class="goods-popup-slot--content">
<slot />
</view>
</scroll-view>
</view>
<view
class="goods-popup-mask"
:style="{
opacity: maskOpacity,
transitionDuration: duration + 'ms',
backgroundColor: 'rgba(0, 0, 0, ' + maskAlpha + ')',
zIndex: zIndex - 1
}"
@tap.stop="close"
@touchmove.stop.prevent
/>
</view>
</template>
<script>
let timeout = null;
export default {
provide() {
return {
popup: this
};
},
props: {
type: {
type: String,
default: "bottom"
},
mode: {
type: String,
default: "size-auto"
},
height: {
type: [String, Number],
default: 400
},
width: {
type: [String, Number],
default: 500
},
radius: {
type: [String, Number],
default: 32
},
zIndex: {
type: [String, Number],
default: 10076
},
maskClickClose: {
type: Boolean,
default: true
},
maskAlpha: {
type: Number,
default: 0.5
},
duration: {
type: Number,
default: 300
},
closeable: {
type: Boolean,
default: false
},
scrollY: {
type: Boolean,
default: false
},
scrollX: {
type: Boolean,
default: false
},
closeIcon: {
type: String,
default: ""
},
closeIconSize: {
type: [String, Number],
default: "20"
},
vertOffset: {
type: [String, Number],
default: "22"
},
horiOffset: {
type: [String, Number],
default: "22"
},
centerAnim: {
type: String,
default: "zoom-lessen"
},
bgColor: {
type: String,
default: "#ffffff"
},
zoomLessenMulti: {
type: Number,
default: 1.15
},
slideMulti: {
type: Number,
default: 1
},
negativeTop: {
type: Number,
default: 0
},
title: String,
desc: String
},
data() {
return {
w: uni.getSystemInfoSync().screenWidth,
h: uni.getSystemInfoSync().screenHeight,
isShow: false,
winReBottom: "",
winReTop: "",
sizeChange: false,
contentOpacity: null,
contentTransform: null,
maskOpacity: 0
};
},
computed: {
autoCenterTop() {
// let statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
let windowHeight = uni.getSystemInfoSync().windowHeight;
let popupHeight = this.rpxToPx(this.height);
// let navHeight = 44;
let result = `${(windowHeight - popupHeight) / 2 - this.negativeTop}px`;
return result;
},
autoTransform() {
let result = "";
switch (this.type) {
case "center":
if (this.centerAnim === "zoom-lessen") {
result = `scale(${this.zoomLessenMulti})`;
} else if (this.centerAnim === "slide-up") {
result = `translateY(${100 * this.slideMulti}%)`;
} else if (this.centerAnim === "slide-down") {
result = `translateY(${-100 * this.slideMulti}%)`;
} else if (this.centerAnim === "fade") {
result = "auto";
}
break;
case "bottom":
result = "translateY(100%)";
break;
case "top":
result = "translateY(-100%)";
break;
case "left":
result = "translateX(-100%)";
break;
case "right":
result = "translateX(100%)";
break;
}
return result;
},
autoWidth() {
if (this.type === "center") {
return `${this.width}rpx`;
} else {
if (this.mode === "size-fixed") {
if (this.type === "top" || this.type === "bottom") {
return "100%";
} else {
return `${this.width}rpx`;
}
} else {
if (this.type === "top" || this.type === "bottom") {
return "100%";
} else {
return "auto";
}
}
}
},
autoHeight() {
if (this.type === "center") {
return `${this.height}rpx`;
} else {
if (this.mode === "size-fixed") {
if (this.type === "left" || this.type === "right") {
return "100%";
} else {
return `${this.height}rpx`;
}
} else {
if (this.type === "left" || this.type === "right") {
return "100%";
} else {
return "auto";
}
}
}
},
autoTop() {
if (this.type === "center") {
return this.autoCenterTop;
} else if (this.type === "bottom") {
return "auto";
} else {
return 0;
}
},
autoBottom() {
if (this.type === "center" || this.type === "top") {
return "auto";
} else {
return 0;
}
},
autoLeft() {
if (this.type === "center") {
return `${(this.w - this.rpxToPx(622)) / 2}px`;
} else if (this.type === "right") {
return "auto";
} else {
return 0;
}
},
autoRight() {
if (this.type === "center" || this.type === "left") {
return "auto";
} else {
return 0;
}
}
},
mounted() {
// #ifdef H5
let winHeight = uni.getSystemInfoSync().windowHeight;
uni.onWindowResize(res => {
this.sizeChange = true;
if (this.type === "bottom") {
this.winReBottom = winHeight - res.size.windowHeight + "px";
} else if (this.type === "center") {
this.winReTop =
(res.size.windowHeight - this.rpxToPx(this.height)) / 2 - this.negativeTop + "px";
}
});
// #endif
},
methods: {
close() {
this.maskClickClose && this.hide();
},
open() {
this.isShow = true;
this.$nextTick(() => {
this.maskIn();
this.contentIn();
this.wait(this.duration + 1).then(() => {
this.$emit("show", {
pageScroll: false,
overflow: "hidden"
});
});
});
},
hide() {
this.contentOut();
this.maskOut();
this.wait(this.duration + 1).then(() => {
this.isShow = false;
this.$emit("hide", {
pageScroll: true,
overflow: "scroll"
});
});
},
contentIn() {
switch (this.type) {
case "center":
if (this.centerAnim === "zoom-lessen") {
this.contentOpacity = 1;
this.contentTransform = "scale(1)";
} else if (this.centerAnim === "slide-up" || this.centerAnim === "slide-down") {
this.contentOpacity = 1;
this.contentTransform = "translateY(0)";
} else if (this.centerAnim === "fade") {
this.contentOpacity = 1;
}
break;
case "bottom":
case "top":
this.contentTransform = "translateY(0)";
break;
case "left":
case "right":
this.contentTransform = "translateX(0)";
break;
}
},
contentOut() {
this.contentOpacity = null;
this.contentTransform = null;
},
maskIn() {
this.maskOpacity = 1;
},
maskOut() {
this.maskOpacity = 0;
},
rpxToPx(rpx) {
return (rpx / 750) * this.w;
},
wait(time) {
return new Promise(resolve => {
clearTimeout(timeout);
timeout = setTimeout(() => {
clearTimeout(timeout);
timeout = null;
resolve();
}, time);
});
}
}
};
</script>
<style>
.goods-popup-box {
position: fixed;
transition-timing-function: ease-out;
transition-property: opacity, transform;
overflow: scroll;
box-sizing: border-box;
overflow: hidden;
}
.goods-popup-container {
position: relative;
box-sizing: border-box;
}
.goods-popup-slot {
width: 100%;
height: 100%;
}
.goods-popup-slot--content {
padding: 115rpx 0 0 0;
padding-bottom: calc(constant(safe-area-inset-bottom) + 30rpx);
padding-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
box-sizing: border-box;
}
.goods-popup-mask {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
transition-timing-function: ease;
transition-property: opacity, transform;
}
.goods-popup-close {
position: absolute;
left: 0;
top: 0;
font-size: 40rpx;
color: #808080;
z-index: 20000;
width: 100%;
background-color: #fff;
height: 90rpx;
}
.goods-popup-custom-head {
padding: 30rpx 0 16rpx;
text-align: center;
}
.goods-popup-title {
font-size: 32rpx;
line-height: 44rpx;
font-weight: bold;
color: #333333;
}
.goods-popup-desc {
margin-top: 10rpx;
font-size: 26rpx;
line-height: 38rpx;
color: #999999;
}
.goods-popup-custom-close {
position: absolute;
right: 20rpx;
top: 10rpx;
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
}
.goods-popup-close-image {
width: 44rpx;
height: 44rpx;
}
</style>
<template>
<view v-if="showPopup" class="uni-popup" :class="[popupstyle]" @touchmove.stop.prevent="clear">
<uni-transition
v-if="maskShow"
:mode-class="['fade']"
:styles="maskClass"
:duration="duration"
:show="showTrans"
@click="onTap"
/>
<uni-transition
:mode-class="ani"
:styles="transClass"
:duration="duration"
:show="showTrans"
@click="onTap"
>
<view class="uni-popup__wrapper-box" @click.stop="clear">
<text class="uni-popup-icon iconfont icon-close-plane" @click="onTap" />
<view v-if="title || desc" class="uni-popup-header">
<text v-if="title" class="uni-popup-title">{{ title }}</text>
<text v-if="desc" class="uni-popup-desc">{{ desc }}</text>
</view>
<slot />
</view>
</uni-transition>
</view>
</template>
<script>
import { uniTransition } from "@dcloudio/uni-ui";
const config = {
// 顶部弹出
top: "top",
// 底部弹出
bottom: "bottom",
// 居中弹出
center: "center",
// 消息提示
message: "top",
// 对话框
dialog: "center",
// 分享
share: "bottom"
};
export default {
name: "UniPopup",
components: {
uniTransition
},
provide() {
return {
popup: this
};
},
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
// message: 消息提示 ; dialog : 对话框
type: {
type: String,
default: "bottom"
},
// maskClick
maskClick: {
type: Boolean,
default: true
},
title: {
type: String,
default: ""
},
desc: {
type: String,
default: ""
}
},
data() {
return {
duration: 300,
ani: [],
showPopup: false,
showTrans: false,
maskClass: {
position: "fixed",
bottom: 0,
top: 0,
left: 0,
right: 0,
backgroundColor: "rgba(0, 0, 0, 0.4)"
},
transClass: {
position: "fixed",
left: 0,
right: 0
},
maskShow: true,
mkclick: true,
popupstyle: "top",
config
};
},
watch: {
/**
* 监听type类型
*/
type: {
handler: function(newVal) {
this[this.config[newVal]]();
},
immediate: true
},
/**
* 监听遮罩是否可点击
* @param {Object} val
*/
maskClick(val) {
this.mkclick = val;
}
},
created() {
this.mkclick = this.maskClick;
if (this.animation) {
this.duration = 300;
} else {
this.duration = 0;
}
},
methods: {
clear(e) {
// TODO nvue 取消冒泡
e.stopPropagation();
},
open() {
this.showPopup = true;
this.$nextTick(() => {
new Promise(resolve => {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.showTrans = true;
// fixed by mehaotian 兼容 app 端
this.$nextTick(() => {
resolve();
});
}, 50);
}).then(() => {
// 自定义打开事件
clearTimeout(this.msgtimer);
this.msgtimer = setTimeout(() => {
this.customOpen && this.customOpen();
}, 100);
this.$emit("change", {
show: true,
type: this.type
});
});
});
},
close() {
this.showTrans = false;
this.$nextTick(() => {
this.$emit("change", {
show: false,
type: this.type
});
clearTimeout(this.timer);
// 自定义关闭事件
this.customOpen && this.customClose();
this.timer = setTimeout(() => {
this.showPopup = false;
}, 300);
});
},
onTap() {
if (!this.mkclick) return;
this.close();
},
/**
* 顶部弹出样式处理
*/
top() {
this.popupstyle = "top";
this.ani = ["slide-top"];
this.transClass = {
position: "fixed",
left: 0,
right: 0
};
},
/**
* 底部弹出样式处理
*/
bottom() {
this.popupstyle = "bottom";
this.ani = ["slide-bottom"];
this.transClass = {
position: "fixed",
left: 0,
right: 0,
bottom: 0
};
},
/**
* 中间弹出样式处理
*/
center() {
this.popupstyle = "center";
this.ani = ["zoom-out", "fade"];
this.transClass = {
position: "fixed",
/* #ifndef APP-NVUE */
display: "flex",
flexDirection: "column",
/* #endif */
bottom: 0,
left: 0,
right: 0,
top: 0,
justifyContent: "center",
alignItems: "center"
};
}
}
};
</script>
<style lang="scss" scoped>
.uni-popup {
position: fixed;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: $uni-bg-color-mask;
opacity: 0;
}
.mask-ani {
transition-property: opacity;
transition-duration: 0.2s;
}
.uni-top-mask {
opacity: 1;
}
.uni-bottom-mask {
opacity: 1;
}
.uni-center-mask {
opacity: 1;
}
.uni-popup__wrapper {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: absolute;
}
.top {
/* #ifdef H5 */
top: var(--window-top);
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
}
.bottom {
bottom: 0;
}
.uni-popup__wrapper-box {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
/* iphonex 等安全区设置,底部安全区适配 */
/* #ifndef APP-NVUE */
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
/* #endif */
padding: 40rpx 40rpx 0;
border-radius: 12rpx 12rpx 0 0;
background-color: #fff;
.uni-popup-icon {
position: absolute;
right: 40rpx;
top: 43rpx;
font-size: 36rpx;
color: #999999;
}
.uni-popup-header {
margin-bottom: 40rpx;
text {
display: inline-block;
width: 100%;
text-align: center;
}
.uni-popup-title {
font-size: 32rpx;
line-height: 44rpx;
font-weight: bold;
color: #333333;
}
.uni-popup-desc {
margin-top: 10rpx;
font-size: 26rpx;
color: #999999;
}
}
}
.content-ani {
// transition: transform 0.3s;
transition-property: transform, opacity;
transition-duration: 0.2s;
}
.uni-top-content {
transform: translateY(0);
}
.uni-bottom-content {
transform: translateY(0);
}
.uni-center-content {
transform: scale(1);
opacity: 1;
}
</style>
<template>
<view
class="HMfilterDropdown"
:class="{ setDropdownBottom: maskVisibility }"
:style="{ top: menuTop + 'rpx' }"
>
<!-- 顶部菜单 -->
<!-- <view class="nav">
<block v-for="(item, index) in menu" :key="index">
<view class="first-menu" :class="{ on: showPage == index }" @tap="togglePage(index)">
<text class="name">item.name</text>
<text
class="iconfont triangle"
:style="'transform:rotate(' + triangleDeg[index] + 'deg);'"
/>
</view>
</block>
</view> -->
<!-- 遮罩层 -->
<!-- <view
class="mask"
:class="{ show: isShowMask, hide: maskVisibility != true }"
@tap="hideMenu(false)"
/>
<block v-for="(page, page_index) in subData" :key="page_index">
<view
class="sub-menu-class"
:class="{ show: showPage == page_index, hide: pageState[page_index] != true }"
> -->
<!-- 分类 -->
<!-- <block v-if="page.type == 'hierarchy-column' && page.subCategory.length > 0">
<scroll-view
class="sub-menu-list"
:class="[activeMenuArr[page_index].length > 1 ? 'first' : 'alone']"
:scroll-y="true"
:scroll-into-view="'first_id' + firstScrollInto"
>
<block v-for="(sub, index) in page.subCategory" :key="index">
<view
:id="'first_id' + index"
class="sub-menu"
:class="{ on: activeMenuArr[page_index][0] == index }"
@tap="selectHierarchyMenu(page_index, index, nullish)"
>
<view class="menu-name">
<text>{{ sub.name }}</text>
<text class="iconfont selected" />
</view>
</view>
</block>
</scroll-view> -->
<!-- <block v-for="(sub, index) in page.subCategory" :key="index">
<scroll-view
v-if="activeMenuArr[page_index][0] == index && sub.subCategory.length > 0"
class="sub-menu-list not-first"
:scroll-y="true"
:scroll-into-view="'second_id' + secondScrollInto"
>
<block v-for="(sub_second, second_index) in sub.subCategory" :key="second_index">
<view
:id="'second_id' + second_index"
class="sub-menu"
:class="{ on: activeMenuArr[page_index][1] == second_index }"
>
<view
class="menu-name"
@tap="
selectHierarchyMenu(page_index, activeMenuArr[page_index][0], second_index)
"
> -->
<!-- <text>{{ sub_second.name }}</text>
</view>
</view>
</block>
</scroll-view>
</block> -->
<!-- 第三级菜单 -->
<!-- <block v-for="(sub, index) in page.subCategory" :key="index">
<block v-for="(sub_second, second_index) in sub.subCategory" :key="second_index">
<scroll-view
v-if="
activeMenuArr[page_index][0] == index &&
activeMenuArr[page_index][1] == second_index &&
sub_second.subCategory.length > 0
"
class="sub-menu-list not-first third"
:scroll-y="true"
:scroll-into-view="'third_id' + thirdScrollInto"
>
<block v-for="(sub_third, third_index) in sub_second.subCategory" :key="third_index">
<view
:id="'third_id' + third_index"
class="sub-menu"
:class="{ on: activeMenuArr[page_index][2] == third_index }"
>
<view
class="menu-name"
@tap="
selectHierarchyMenu(
page_index,
activeMenuArr[page_index][0],
second_index,
third_index
)
"
>
<text>{{ sub_third.name }}</text>
</view>
</view>
</block>
</scroll-view>
</block>
</block> -->
<!-- </block> -->
<!-- 推荐 -->
<!-- <block v-if="page.type == 'rank'">
<view>
<scroll-view class="sub-menu-list" :scroll-y="true">
<view v-for="(rankCondition, rank_index) in page.subCategory" :key="rank_index">
<view
:class="{ on: rankCondition.selected }"
@tap="selectRankCondition(page_index, rank_index)"
>{{ rankCondition.name }}</view
>
</view>
</scroll-view>
</view>
</block> -->
<!-- 价格 -->
<!-- <block v-if="page.type == 'radio'">
<view class="filter">
<scroll-view class="menu-box" :scroll-y="true">
<view v-for="(box, box_index) in page.subCategory" :key="box_index" class="box">
<view class="title">{{ box.name }}</view>
<view class="labels">
<view
v-for="(label, label_index) in box.subCategory"
:key="label_index"
:class="{ on: label.selected }"
@tap="selectRadioLabel(page_index, box_index, label_index)"
>{{ label.name }}</view
>
</view>
</view>
</scroll-view>
<view class="btn-box">
<view class="reset" @tap="resetFilterData(page_index)">重置</view>
<view class="submit" @tap="setFilterData(page_index)">确定</view>
</view>
</view>
</block>
</view>
</block>
</view> -->
<view class="nav">
<!-- 顶部菜单栏 -->
<block v-for="(item, index) in menu" :key="index">
<view class="first-menu" :class="{ on: showPage === index }" @tap="togglePage(index)">
<text class="name">{{ item.name }}</text>
<text
class="iconfont triangle"
:style="'transform:rotate(' + triangleDeg[index] + 'deg);'"
/>
</view>
</block>
</view>
<!-- 遮罩层 -->
<view
class="mask"
:class="{ show: isShowMask, hide: maskVisibility !== true }"
@tap="hideMenu(false)"
/>
<!-- 下拉菜单 -->
<block v-for="(page, page_index) in menu" :key="page_index">
<view
class="sub-menu-class"
:class="{ show: showPage === page_index, hide: pageState[page_index] !== true }"
>
<!-- 分类 -->
<block v-if="page.type === 'hierarchy' && page.subCategory.length > 0">
<scroll-view
class="sub-menu-list"
:class="[activeMenuArr[page_index].length > 1 ? 'first' : 'alone']"
:scroll-y="true"
>
<block v-for="(sub, first_index) in page.subCategory" :key="first_index">
<view
class="sub-menu"
:class="{ on: activeMenuArr[page_index][0] === first_index }"
@tap="selectHierarchyMenu(page_index, index, null, null)"
>
<view class="menu-name">
<text>{{ sub.cidName }}</text>
<text class="iconfont selected" />
</view>
</view>
</block>
</scroll-view>
<block v-for="(sub, first_index) in page.subCategory" :key="first_index">
<scroll-view
v-if="activeMenuArr[page_index][0] == index && sub.subCategory.length > 0"
class="sub-menu-list not-first"
:scroll-y="true"
>
<block v-for="(sub_second, second_index) in sub.subCategory" :key="second_index">
<view
class="sub-menu"
:class="{ on: activeMenuArr[page_index][1] == second_index }"
>
<view
class="menu-name"
@tap="
selectHierarchyMenu(
page_index,
activeMenuArr[page_index][0],
second_index,
null
)
"
>
<text>{{ sub_second.cidName }}</text>
</view>
</view>
</block>
</scroll-view>
</block>
<!-- 第三级菜单 -->
<block v-for="(sub, first_index) in page.subCategory" :key="first_index">
<block v-for="(sub_second, second_index) in sub.subCategory" :key="second_index">
<scroll-view
v-if="
activeMenuArr[page_index][0] == index &&
activeMenuArr[page_index][1] == second_index &&
sub_second.subCategory.length > 0
"
class="sub-menu-list not-first third"
:scroll-y="true"
>
<block
v-for="(sub_third, third_index) in sub_second.subCategory"
:key="third_index"
>
<view
class="sub-menu"
:class="{ on: activeMenuArr[page_index][2] == third_index }"
>
<view
class="menu-name"
@tap="
selectHierarchyMenu(
page_index,
activeMenuArr[page_index][0],
second_index,
third_index
)
"
>
<text>{{ sub_third.cidName }}</text>
</view>
</view>
</block>
</scroll-view>
</block>
</block>
</block>
<!-- 排序 -->
<block v-if="page.type === 'rank'">
<view>
<scroll-view class="sub-menu-list" :scroll-y="true">
<view v-for="(rankCondition, rank_index) in page.subCategory" :key="rank_index">
<view
:class="{ on: rankCondition.selected }"
@tap="selectRankCondition(page_index, rank_index)"
>{{ rankCondition.name }}</view
>
</view>
</scroll-view>
</view>
</block>
<!-- 价格 -->
<block v-if="page.type === 'radio'">
<view class="filter">
<view v-for="(item, index) in page.priceArea" :key="index">
<view class="priceInterval" @tap="selectRadioLabel(page_index, index)">
<text class="front">{{ item.minPrice }}</text>
<p>-</p>
<text class="back">{{ item.maxPrice }}</text>
</view>
</view>
<view class="priceInterval">
<input class="front input" type="text" placeholder="最低价" />
<p>-</p>
<input class="back input" type="text" placeholder="最高价" />
</view>
<view class="btn-box">
<view class="reset" @tap="reset(page_index)">重置</view>
<view class="submit" @tap="submit(page_index)">确定</view>
</view>
</view>
</block>
</view>
</block>
</view>
</template>
<script>
export default {
props: {
menuTop: {
type: Number,
default: 0
},
filterData: {
type: Object,
default: () => {}
},
updateMenuName: {
type: Boolean,
default: false
}
},
data() {
return {
menu: [
{
name: "分类",
type: "hierarchy"
},
{
name: "排序",
type: "rank"
},
{
name: "价格",
type: "radio"
}
],
menuData: [], //菜单数据
showPage: -1, //菜单页面显示
pageState: [], //页面状态
activeMenuArr: [], //UI状态
shadowActiveMenuArr: [], //记录选中
triangleDeg: [], //三角形的翻转动画控制
isShowMask: false, //遮罩层显示/隐藏动画控制
maskVisibility: false //遮罩层显示/隐藏状态
};
},
// data() {
// return {
// menuData: [],
// subData: [], //菜单数据
// menu: [], //顶部菜单数据
// showPage: -1, //菜单页面显示/隐藏动画控制
// pageState: [], //页面的状态
// activeMenuArr: [], //UI状态
// shadowActiveMenuArr: [], //记录选中
// defaultActive: [],
// triangleDeg: [], //小三角形的翻转动画控制
// isShowMask: false, //遮罩层显示/隐藏动画控制
// maskVisibility: false, //遮罩层显示/隐藏状态
// //滚动区域定位
// firstScrollInto: 0,
// secondScrollInto: 0,
// thirdScrollInto: 0,
// componentTop: 0 //组件top
// };
// },
// watch: {
// filterData: {
// handler(newVal) {
// this.menuData = JSON.parse(JSON.stringify(newVal));
// this.initMenu(); //filterData重新赋值初始化菜单
// },
// immediate: true,
// deep: true
// }
// // defaultSelected(newVal) {
// // if (newVal.length == 0) {
// // return;
// // }
// // this.defaultActive = JSON.parse(JSON.stringify(newVal));
// // this.activeMenuArr = JSON.parse(JSON.stringify(newVal));
// // this.shadowActiveMenuArr = JSON.parse(JSON.stringify(newVal));
// // }
// },
watch: {
filterData: {
handler(newVal) {
this.menuData = JSON.parse(JSON.stringify(newVal));
this.initMenu();
}
}
},
methods: {
initMenu() {
this.menuData.frontCategoryList.unshift({
cidName: "全部",
subCategory: []
});
this.menu[0].subCategory = this.menuData.frontCategoryList;
this.menu[2].priceArea = this.menuData.priceArea;
for (let i = 0; i < this.menu.length; i++) {
this.menu[i] = this.processSubMenu(this.menu[i]);
this.triangleDeg.push(0);
this.pageState.push(false);
}
this.activeMenuArr = [[null, null, null], [null], [null, null]];
this.shadowActiveMenuArr = [[null, null, null], [null], [null, null]];
},
processSubMenu(menu) {
if (
Object.prototype.hasOwnProperty.call(menu, "subCategory") &&
menu.subCategory.length > 0
) {
for (let i = 0; i < menu.subCategory.length; i++) {
menu.subCategory[i] = this.processSubMenu(menu.subCategory[i]);
}
} else {
menu.subCategory = [];
}
return menu;
},
selectHierarchyMenu(page_index, level1_index, level2_index, level3_index) {
if (
level2_index == null &&
level3_index == null &&
this.shadowActiveMenuArr[page_index].length > 0 &&
this.shadowActiveMenuArr[page_index][0] == level1_index
) {
this.activeMenuArr.splice(
page_index,
1,
JSON.parse(JSON.stringify(this.shadowActiveMenuArr[page_index]))
);
}
},
togglePage(index) {
if (this.isToggleing) {
return;
}
this.isToggleing = true;
setTimeout(() => {
this.isToggleing = false;
}, 150);
if (index == this.showPage) {
this.hideMenu();
} else {
this.showMenu(index);
}
},
hideMenu(isTriggerConfirm) {
this.hideMenuLayer(true);
this.hideMaskLayer();
this.showPage = -1;
if (isTriggerConfirm) {
this.confirm();
}
},
showMenu(index) {
if (this.showPage > -1) {
this.hideMenuLayer(false);
}
this.showMenuLayer(index);
this.showMaskLayer();
},
showMaskLayer() {
this.maskVisibility = true;
this.$nextTick(() => {
setTimeout(() => {
this.isShowMask = true;
}, 0);
});
},
hideMaskLayer() {
this.isShowMask = false;
setTimeout(() => {
this.maskVisibility = false;
}, 200);
},
hideMenuLayer(isAnimation) {
this.triangleDeg[this.showPage] = 0;
let tmpIndex = this.showPage;
if (isAnimation) {
setTimeout(() => {
this.pageState.splice(tmpIndex, 1, false);
}, 200);
} else {
this.pageState.splice(tmpIndex, 1, false);
}
this.firstScrollInto = null;
this.secondScrollInto = null;
},
showMenuLayer(index) {
this.processPage(index);
this.pageState.splice(index, 1, true);
this.$nextTick(() => {
setTimeout(() => {
this.showPage = index;
}, 0);
});
this.triangleDeg[index] = 180;
},
reloadActiveMenuArr() {
for (let i = 0; i < this.menuData.length; i++) {
let tmpitem = this.menuData[i];
let tmpArr = this.processActive(tmpitem);
tmpitem = this.processSubMenu(tmpitem);
if (this.activeMenuArr[i].length != tmpArr.length) {
this.menuData[i] = tmpitem;
this.activeMenuArr.splice(i, 1, JSON.parse(JSON.stringify(tmpArr)));
this.shadowActiveMenuArr.splice(i, 1, JSON.parse(JSON.stringify(tmpArr)));
}
}
this.subData = this.menuData;
this.$forceUpdate();
},
processPage(index) {
//check UI控制数组,结果数组,防止传入数据层级和UI控制数组不同步
this.reloadActiveMenuArr();
//重置UI控制数组
this.activeMenuArr.splice(index, 1, this.shadowActiveMenuArr[index]);
if (this.menu[index].type == "filter") {
//重载筛选页选中状态
let level = this.shadowActiveMenuArr[index].length;
for (let i = 0; i < level; i++) {
let box = this.subData[index].subCategory[i].subCategory;
for (let j = 0; j < box.length; j++) {
if (this.shadowActiveMenuArr[index][i].indexOf(j) > -1) {
this.subData[index].subCategory[i].subCategory[j].selected = true;
} else {
this.subData[index].subCategory[i].subCategory[j].selected = false;
}
}
}
} else if (this.menu[index].type == "hierarchy") {
return;
} else if (this.menu[index].type == "hierarchy-column") {
return;
} else if (this.menu[index].type == "radio") {
//重载筛选页选中状态
// let level = this.shadowActiveMenuArr[index].length;
// for (let i = 0; i < level; i++) {
// let box = this.subData[index].subCategory[i].subCategory;
// for (let j = 0; j < box.length; j++) {
// if (this.shadowActiveMenuArr[index][i].indexOf(j) > -1) {
// this.subData[index].subCategory[i].subCategory[j].selected = true;
// } else {
// this.subData[index].subCategory[i].subCategory[j].selected = false;
// }
// }
// }
}
}
}
// methods: {
// initMenu() {
// let tmpMenuActiveArr = [];
// let tmpMenu = [];
// for (let i = 0; i < this.menuData.length; i++) {
// let tmpitem = this.menuData[i];
// tmpMenu.push({
// //如果没有设置name,则取第一个菜单作为menu.name,filter类型则将"筛选"作为menu.name
// name: tmpitem.name || (tmpitem.type == "filter" ? "筛选" : tmpitem.subCategory[0].name),
// type: tmpitem.type
// });
// //初始化选中项数组-ui状态
// tmpMenuActiveArr.push(this.processActive(tmpitem));
// //初始化角度数组
// this.triangleDeg.push(0);
// //初始化控制显示状态数组
// this.pageState.push(false);
// //递归处理子菜单数据
// tmpitem = this.processSubMenu(tmpitem);
// this.menuData[i] = tmpitem;
// }
// this.menu = tmpMenu;
// //初始化选中项数组
// tmpMenuActiveArr =
// this.defaultActive.length > 0
// ? this.defaultActive
// : this.activeMenuArr.length > 0
// ? this.activeMenuArr
// : tmpMenuActiveArr;
// this.defaultActive = [];
// this.activeMenuArr = JSON.parse(JSON.stringify(tmpMenuActiveArr));
// this.shadowActiveMenuArr = JSON.parse(JSON.stringify(tmpMenuActiveArr));
// //加载菜单数据
// this.subData = this.menuData;
// } //选中
// selectHierarchyMenu(page_index, level1_index, level2_index) {
// //读取记录
// if (
// level2_index == null &&
// this.shadowActiveMenuArr[page_index].length > 0 &&
// this.shadowActiveMenuArr[page_index][0] == level1_index
// ) {
// this.activeMenuArr.splice(
// page_index,
// 1,
// JSON.parse(JSON.stringify(this.shadowActiveMenuArr[page_index]))
// );
// }
// this.activeMenuArr[page_index].splice(0, 1, level1_index);
// let tmpMemu = this.subData[page_index].subCategory[level1_index];
// if (tmpMemu.subCategory.length == 0) {
// this.selectedMemu(page_index, level1_index, level2_index);
// } else if (level2_index != null) {
// this.activeMenuArr[page_index].splice(1, 1, level2_index);
// tmpMemu = tmpMemu.subCategory[level2_index];
// if (tmpMemu.subCategory.length == 0 || this.menu[page_index].type == "hierarchy") {
// this.selectedMemu(page_index, level1_index, level2_index);
// }
// }
// },
// selectedMemu(page_index, level1_index, level2_index) {
// let sub = this.subData[page_index].subCategory[level1_index].subCategory[level2_index];
// if (this.updateMenuName) {
// this.menu[page_index].name =
// (level2_index != null && sub.name) || this.subData[page_index].subCategory[level1_index].name;
// }
// this.shadowActiveMenuArr[page_index] = JSON.parse(
// JSON.stringify(this.activeMenuArr[page_index])
// );
// this.hideMenu(true);
// },
// setFilterData(page_index) {
// this.shadowActiveMenuArr[page_index] = JSON.parse(
// JSON.stringify(this.activeMenuArr[page_index])
// );
// this.hideMenu(true);
// },
// resetFilterData(page_index) {
// let tmpArr = [];
// let level = this.shadowActiveMenuArr[page_index].length;
// while (level > 0) {
// tmpArr.push([]);
// let box = this.subData[page_index].subCategory[level - 1].subCategory;
// for (let i = 0; i < box.length; i++) {
// this.subData[page_index].subCategory[level - 1].subCategory[i].selected = false;
// }
// level--;
// }
// this.activeMenuArr[page_index] = JSON.parse(JSON.stringify(tmpArr));
// this.$forceUpdate();
// },
// selectRadioLabel(page_index, box_index, label_index) {
// let activeIndex = this.activeMenuArr[page_index][box_index][0];
// if (activeIndex == label_index) {
// this.subData[page_index].subCategory[box_index].subCategory[activeIndex].selected = false;
// this.activeMenuArr[page_index][box_index][0] = null;
// } else {
// if (
// activeIndex != null &&
// activeIndex < this.subData[page_index].subCategory[box_index].subCategory.length
// ) {
// this.subData[page_index].subCategory[box_index].subCategory[activeIndex].selected = false;
// }
// this.subData[page_index].subCategory[box_index].subCategory[label_index].selected = true;
// this.activeMenuArr[page_index][box_index][0] = label_index;
// }
// this.$forceUpdate();
// },
// selectRankCondition(page_index, rank_index) {
// let activeIndex = this.activeMenuArr[page_index][0];
// if (activeIndex == rank_index) {
// this.subData[page_index].subCategory[activeIndex].selected = false;
// this.activeMenuArr[page_index][0] = null;
// } else {
// if (activeIndex != null && activeIndex < this.subData[page_index].subCategory.length) {
// this.subData[page_index].subCategory[activeIndex].selected = false;
// }
// this.subData[page_index].subCategory[activeIndex].selected = true;
// this.activeMenuArr[page_index][0] = rank_index;
// }
// },
// togglePage(index) {
// if (this.isToggleing) {
// return;
// }
// this.isToggleing = true;
// setTimeout(() => {
// this.isToggleing = false;
// }, 150);
// if (index == this.showPage) {
// this.hideMenu();
// } else {
// this.showMenu(index);
// }
// },
// hideMenu(isTriggerConfirm) {
// this.hideMenuLayer(true);
// this.hideMaskLayer();
// this.showPage = -1;
// if (isTriggerConfirm) {
// this.confirm();
// }
// },
// showMenu(index) {
// if (this.showPage > -1) {
// this.hideMenuLayer(false);
// }
// this.showMenuLayer(index);
// this.showMaskLayer();
// },
// hideMaskLayer() {
// this.isShowMask = false;
// setTimeout(() => {
// this.maskVisibility = false;
// }, 200);
// },
// hideMenuLayer(isAnimation) {
// this.triangleDeg[this.showPage] = 0;
// let tmpIndex = this.showPage;
// if (isAnimation) {
// setTimeout(() => {
// this.pageState.splice(tmpIndex, 1, false);
// }, 200);
// } else {
// this.pageState.splice(tmpIndex, 1, false);
// }
// this.firstScrollInto = null;
// this.secondScrollInto = null;
// },
// showMenuLayer(index) {
// this.processPage(index);
// this.pageState.splice(index, 1, true);
// this.$nextTick(() => {
// setTimeout(() => {
// this.showPage = index;
// }, 0);
// });
// this.triangleDeg[index] = 180;
// },
// processActive(tmpitem) {
// let tmpArr = [];
// if (
// (tmpitem.type == "hierarchy" || tmpitem.type == "hierarchy-column") &&
// tmpitem.hasOwnProperty("subCategory") &&
// tmpitem.subCategory.length > 0
// ) {
// let level = this.getMaxFloor(tmpitem.subCategory);
// while (level > 0) {
// tmpArr.push(null);
// level--;
// }
// } else if (tmpitem.type == "filter") {
// let level = tmpitem.subCategory.length;
// while (level > 0) {
// tmpArr.push([]);
// level--;
// }
// } else if (tmpitem.type == "radio") {
// let level = tmpitem.subCategory.length;
// while (level > 0) {
// tmpArr.push([]);
// level--;
// }
// }
// return tmpArr;
// },
// processSubMenu(menu) {
// if (menu.hasOwnProperty("subCategory") && menu.subCategory.length > 0) {
// for (let i = 0; i < menu.subCategory.length; i++) {
// menu.subCategory[i] = this.processSubMenu(menu.subCategory[i]);
// }
// } else {
// menu.subCategory = [];
// }
// return menu;
// },
// getMaxFloor(treeData) {
// let max = 0;
// function each(data, floor) {
// data.forEach(e => {
// max = floor > max ? floor : max;
// if (e.hasOwnProperty("subCategory") && e.subCategory.length > 0) {
// each(e.subCategory, floor + 1);
// }
// });
// }
// each(treeData, 1);
// return max;
// }
// }
};
//
</script>
<style lang="scss">
.HMfilterDropdown {
flex-shrink: 0;
width: 100%;
position: fixed;
// position: sticky;
z-index: 997;
flex-wrap: nowrap;
display: flex;
flex-direction: row;
top: var(--window-top);
left: 0;
// top:100px;
overflow-y: hidden;
&.setDropdownBottom {
// height: 345px;
bottom: 0;
}
view {
display: flex;
flex-wrap: nowrap;
}
}
.region {
flex: 1;
height: 44px;
}
.nav {
width: 100%;
height: 44px;
border-bottom: solid 1rpx #eee;
z-index: 12;
background-color: #ffffff;
flex-direction: row;
.first-menu {
width: 100%;
font-size: 13px;
color: #757575;
flex-direction: row;
align-items: center;
justify-content: center;
transition: color 0.2s linear;
&.on {
color: #ec652b;
.iconfont {
color: #ec652b;
}
}
.name {
height: 20px;
text-align: center;
text-overflow: clip;
overflow: hidden;
}
.iconfont {
width: 13px;
height: 13px;
align-items: center;
justify-content: center;
transition: transform 0.2s linear, color 0.2s linear;
}
}
}
.sub-menu-class {
width: 100%;
position: absolute;
left: 0;
transform: translate3d(0, -100%, 0);
max-height: 345px;
background-color: #ffffff;
z-index: 11;
box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1);
overflow: hidden;
flex-direction: row;
transition: transform 0.15s linear;
&.hide {
display: none;
}
&.show {
transform: translate3d(0, calc(44px + 1rpx), 0);
}
}
.sub-menu-list {
width: 100%;
height: 345px;
flex-direction: column;
.sub-menu {
min-height: 44px;
font-size: 13px;
flex-direction: column;
padding-right: 15px;
> .menu-name {
height: 44px;
flex-direction: row;
align-items: center;
justify-content: space-between;
> .iconfont {
display: none;
font-size: 18px;
color: #ec652b;
}
}
}
&.first {
flex-shrink: 0;
width: 236rpx;
background-color: #f0f0f0;
.sub-menu {
padding-left: 15px;
&.on {
background-color: #fff;
}
}
box-shadow: 5rpx 0 5rpx rgba($color: #000000, $alpha: 0.1);
}
&.alone {
max-height: 345px;
min-height: 170px;
height: auto;
.sub-menu {
min-height: calc(44px - 1rpx);
margin-left: 15px;
border-bottom: solid 1rpx #e5e5e5;
&.on {
color: #ec652b;
> .menu-name {
> .iconfont {
display: block;
}
}
}
}
}
&.third {
box-shadow: 5rpx 0 20rpx rgba($color: #000000, $alpha: 0.2) inset;
}
&.not-first {
box-shadow: 5rpx 0 5rpx rgba($color: #000000, $alpha: 0.1);
.sub-menu {
min-height: calc(44px - 1rpx);
margin-left: 15px;
border-bottom: solid 1rpx #e5e5e5;
> .menu-name {
height: calc(44px - 1rpx);
> .iconfont {
display: none;
font-size: 18px;
color: #ec652b;
}
}
&.on {
color: #ec652b;
> .menu-name {
> .iconfont {
display: block;
}
}
}
.more-sub-menu {
flex-direction: row;
flex-wrap: wrap;
padding-bottom: 9px;
> text {
height: 30px;
border-radius: 3px;
background-color: #f5f5f5;
color: #9b9b9b;
margin-bottom: 6px;
margin-right: 6px;
text-align: center;
line-height: 30px;
border: solid #f5f5f5 1rpx;
flex: 0 0 calc(33.33% - 6px);
overflow: hidden;
font-size: 12px;
&:nth-child(3n) {
margin-right: 0;
}
&.on {
border-color: #f6c8ac;
color: #ec652b;
}
.iconfont {
color: #9b9b9b;
}
}
}
}
}
}
.filter {
width: 100%;
height: 345px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
.menu-box {
width: 698rpx;
height: calc(345px - 75px);
flex-shrink: 1;
.box {
width: 100%;
padding-top: 16px;
flex-direction: column;
.title {
width: 100%;
font-size: 13px;
color: #888;
}
.labels {
flex-direction: row;
flex-wrap: wrap;
.on {
border-color: #ec652b;
background-color: #ec652b;
color: #fff;
}
> view {
width: calc((698rpx - 30rpx * 3) / 4 - 1rpx * 2);
height: 30px;
border: solid 1rpx #adadad;
border-radius: 2px;
margin-right: 30rpx;
margin-top: 8px;
font-size: 12px;
flex-direction: row;
justify-content: center;
align-items: center;
&:nth-child(4n) {
margin-right: 0;
}
}
}
}
}
.btn-box {
flex-shrink: 0;
width: 698rpx;
height: 75px;
flex-direction: row !important;
align-items: center;
justify-content: space-between;
> view {
width: 320rpx;
height: 40px;
border-radius: 40px;
border: solid 1rpx #ec652b;
align-items: center;
justify-content: center;
}
.reset {
color: #ec652b;
}
.submit {
color: #fff;
background-color: #ec652b;
}
}
}
.mask {
z-index: 10;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0);
transition: background-color 0.15s linear;
&.show {
background-color: rgba(0, 0, 0, 0.5);
}
&.hide {
display: none;
}
}
/* 字体图标 */
@font-face {
font-family: "HM-FD-font";
src: url("data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAALAAAsAAAAABpQAAAJzAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgp4gQIBNgIkAwwLCAAEIAWEbQc5G8sFERWMIbIfCbbzqA4hp7InSBibVsYGb4J42o82b3e/nJlHMw/NHbGOlwKJRCRpwzPtpAECCOZubdqxjYpQLMlVg+70/08edrgQOtx2ukpVyApZn+dyehPoQObHo3O85rYx9vOjXoBxQIHugW2yIkqIW2QXcScu4jwE8CSWbKSmrqUHFwOaJoCsLM5P4haSGIxRcRHshrUGucLCVcfqI3AZfV/+USguKCwNmtsxVztDxU/n55C+3W0Z4QQpEOTNFqCBbMCAjDUWB9CIwWk87aa70cYgqLkyd3dEmm+18R8eKATEBrV7A5CulBT8dKiWOYZk412XNcDdKSEKSGODnyKIDl+dmVt9/Dx4pu/xyeutkMlHISGPTsPCnoTNP9nOT6wTtDdlO6dPr47efvj942lkYuQzrhMKEjq9N6y98P3340gmlJ/RStUD6F31CAEEPtUW94/7rf+7XgaAz57X0ZHXAGsFFwVgw38yALuMb0IBbVyNamFYEw4oKMDTj3AHRQP5Pt4dci9VwSVkRNQh5r7CLskZadhsWHhRDBsXczk8ZYk3ewnCxmQeQKa3BOHvA8XXO2j+vqRhf7CE+sPmn4anvoL29JLa4qqaUQkmoK+QG2osCckq7txi2leK86aIPyJ3eQZ8xytXYmyQ51jQndJAxIJlqiGSLsOqImiZCjTiZCJt6Lq26U2OoXqwUo0hRaAE0K5AziANy/uLVeXzWyjVqyjcoeupjxDr5MMDn8MDkLG9Aenu5ZrOSSoghAUsRmogkkahSoWAtnlUARnCkY3It0Iu7mWhdmd9Z/19BwBP6GidEi0G56opckXTGZVSPxgAAAA=");
}
.iconfont {
font-family: "HM-FD-font" !important;
font-size: 13px;
font-style: normal;
color: #757575;
&.triangle {
&:before {
content: "\e65a";
}
}
&.selected {
&:before {
content: "\e607";
}
}
}
</style>
<template>
<view class="home-list">
<view class="home-list-container">
<view v-for="(item, index) in goodsList" :key="index" class="Hl-container-item">
<image
lazy-load
class="Hlc-item-img"
mode="aspectFit"
:src="item.goods.goodsImage"
@click="goDetail(item)"
/>
<view class="Hlc-item-info">
<view class="Hlc-item-info-title" @click="goDetail(item)">
<text>{{ item.goods.goodsName }}</text>
</view>
<view class="Hlc-item-tag" @click="goDetail(item)">
<view v-for="(tag, i) in item.goods.tagList" :key="i" class="Hlc-item-tag-wrap">
<span v-if="tag.type == 2" :key="i" class="Hlc-item-tag-normal">{{ tag.name }}</span>
<img
v-if="tag.type == 1"
mode="heightFix"
class="Hlc-item-tag-icon"
:src="tag.icon"
alt=""
/>
</view>
</view>
<view class="Hlc-item-info-count">
<div @click="goDetail(item)">
<view class="Hlc-item-info-count-left">
<text>¥{{ item.goods.goodsSalePrice }}</text>
<!-- <text v-if="item.goods.goodsPrice">¥{{ item.goods.goodsPrice }}</text> -->
</view>
<view class="Hlc-item-info-count-right">
<text v-if="item.goods.saleCount">已售{{ item.goods.saleCount }}</text>
</view>
</div>
<view class="Hlc-item-info-count-icon">
<text class="iconfont icon-cart" @click="addProduct(item)" />
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { debounce } from "@/utils";
import api from "../api/addProduct.api.js";
export default {
name: "GoodsCard",
props: {
goodsList: {
type: Array,
default: () => []
}
},
data() {
return {};
},
methods: {
goDetail(good) {
debounce(
uni.navigateTo({
url: `/pages/product/goodDetail?skuNo=${
good.goods.goodsId
}&count=1&receiverId=&goodsName=${encodeURIComponent(good.goods.goodsName)}&goodsImage=${
good.goods.goodsImage
}`
}),
300
);
},
async addProduct(good) {
const shopCartBaseList = [
{
skuId: good.goods.goodsId,
skuNum: 1,
skuSource: good.goods.goodsType,
type: 1
}
];
await api.addProduct({ shopCartBaseList, selected: true });
this.$emit("addProduct", good.goods.goodsSalePrice);
uni.showToast({
title: "购物车添加成功",
icon: "none"
});
}
}
};
</script>
<style lang="scss" scoped>
.home-list {
background: $white;
padding: 0 $space-md * 2;
&-container {
.Hl-container-item {
display: flex;
margin: 0 0 40rpx 0;
.Hlc-item-img {
width: 270rpx;
height: 270rpx;
border-radius: 12rpx;
// background: #aaa;
}
.Hlc-item-info {
width: 450rpx;
height: 260rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 20rpx;
&-title {
text {
font-size: 26rpx;
line-height: 36rpx;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
&-count {
display: flex;
justify-content: space-between;
&-left {
color: #ec3333;
margin: 1px;
text {
&:nth-child(1) {
margin-right: 10rpx;
font-size: $uni-font-size-lg;
line-height: 34rpx;
color: #ec3333;
font-weight: bold;
}
&:nth-child(2) {
font-size: $uni-font-size-tiny;
line-height: 24rpx;
color: #999999;
text-align: right;
text-decoration: line-through;
}
}
}
&-right {
font-size: $uni-font-size-tiny;
line-height: 24rpx;
color: #999999;
}
&-icon {
align-items: center;
height: 28px;
width: 28px;
line-height: 28px;
padding-left: 4px;
border: 1px solid #f2f3f5;
background-color: #f2f3f5;
border-radius: 50%;
}
}
}
.Hlc-item-tag {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
height: 60rpx;
margin-top: -40rpx;
&-normal {
// display: inline-block;
// font-size: 22rpx;
// box-sizing: border-box;
// border: 1px solid #ec1500;
// color: #ec1500;
// padding: 0px 4px;
// border-radius: 3px;
// margin-right: 5px;
// // line-height: 14px;
height: 32rpx;
/* #ifdef MP-ALIPAY */
line-height: 30rpx;
/* #endif */
display: flex-inline;
font-size: $uni-font-size-tiny;
justify-content: center;
align-items: center;
margin-top: 8rpx;
border-radius: $uni-border-radius-base;
color: $font-color-search;
padding: 0 $padding-sm;
margin-right: $padding-sm;
border: 1px solid $font-color-search;
::v-deep .uni-tag {
width: 10rpx;
}
}
&-icon {
height: 15px;
margin-right: 5px;
}
}
}
}
}
</style>
<template>
<view class="member-tag">{{ text }}</view>
</template>
<script>
export default {
props: {
text: {
type: String,
default: "会员专享"
}
}
};
</script>
<style lang="scss" scoped>
.member-tag {
display: inline-flex;
justify-content: center;
align-items: center;
min-width: 128rpx;
height: 28rpx;
background: #ffe1b0 url(https://img.lkbang.net/xcx/memberCenter/member_tag_bg.png);
background-size: 124rpx 28rpx;
background-repeat: no-repeat;
border-top-right-radius: 6rpx;
border-bottom-right-radius: 6rpx;
padding-left: 46rpx;
padding-right: 6rpx;
font-size: 20rpx;
color: #252931;
}
</style>
<template>
<view>
<view class="goods-bottom">
<view
url="/pages/cart/cart"
class="goods-bottom-icon"
style="position: relative"
@click="goCart"
>
<view class="goods-bottom-badge">
<uni-badge size="small" :text="cartCount || ''" type="primary" />
</view>
<text class="iconfont icon-cart-line" />
<text>购物车</text>
</view>
<button v-if="noGoods" class="goods-bottom-similar" @click="goSimilar">查看相似</button>
<button v-if="!noGoods" class="goods-bottom-car" @click="addToCart">加入购物车</button>
<button v-if="!noGoods" class="goods-bottom-buy" @click="buy">立即购买</button>
</view>
</view>
</template>
<script>
import { saTrackEvent } from "@/utils/sa.js";
import { uniBadge } from "@dcloudio/uni-ui";
import { getCartCount } from "../api/home.api";
import { setTimeout } from "timers";
import { mapMutations } from "vuex";
export default {
name: "BottomNav",
components: {
uniBadge
},
props: {
noGoods: {
type: Boolean,
default: false
},
shopBtnName: {
type: String,
default: "立即购买" // shoppingCar 购物车;settlement 结算;submitOrder 确认订单
},
info: {
type: Object,
default() {
return {};
}
},
goodsId: {
type: String,
default: ""
}
},
data() {
return {
cartCount: ""
};
},
mounted() {
this.getCartCount();
uni.$on("cartUpdate", () => {
console.log("获取购物车数量");
this.getCartCount();
});
},
beforeDestroy() {
uni.$off("cartUpdate");
},
methods: {
...mapMutations(["saveCartCount"]),
goCart() {
saTrackEvent("MINI_CommodityDetailPageShoppingCartBtnClick");
const token = uni.getStorageSync("token") || "";
if (!token) {
this.$emit("goLogin");
return;
}
setTimeout(() => {
uni.switchTab({
url: "/pages/shopcart/index",
fail: err => {
console.log("失败", err);
}
});
}, 200);
},
async getCartCount() {
const token = uni.getStorageSync("token") || "";
// console.log("token--cart", token);
if (!token) {
return;
}
const [data] = await getCartCount();
this.saveCartCount(data.count);
const count = data && data.count > 99 ? "99+" : data.count ? data.count : "";
this.cartCount = count || "";
},
addToCart() {
this.$emit("addToCart");
},
goSimilar() {
saTrackEvent("MINI_CommodityDetailPageViewSimilarityBtnClick", {
sku_no: this.goodsId
});
setTimeout(() => {
this.$emit("goSimilar");
}, 200);
},
buy() {
this.$emit("buy");
},
goHome() {
const that = this;
// const currentPage = getCurrentPages();
saTrackEvent("PD_YXMMAEC_UserClickCommodityDetailHomePageBtn", {
commodity_id: that.goodsId
});
uni.reportAnalytics("c_commoditydetailhomepagebtn", {
commodity_id: that.goodsId
});
setTimeout(() => {
uni.switchTab({
url: "/pages/index/index"
});
}, 500);
}
}
};
</script>
<style lang="scss" scoped>
@import "@/style/icon.scss";
.goods-bottom {
position: fixed;
left: 0;
bottom: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: calc(env(safe-area-inset-bottom) + 150rpx);
padding: 30rpx 15rpx 0rpx 30rpx;
background: $white;
border-top: $border-sm solid $bg-color-g1;
padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
overflow: hidden;
box-sizing: border-box;
// safe-area-inset-bottom: 20rpx;
&-badge {
position: absolute;
right: -17rpx;
top: -12rpx;
}
&-radio {
display: flex;
align-items: center;
justify-content: space-around;
padding-top: 8rpx;
width: 140rpx;
radio {
transform: scale(0.7);
}
text {
font-size: 24rpx;
color: #999999;
}
}
&-text {
display: flex;
flex-direction: column;
align-items: flex-end;
flex: 1;
margin: 0 20rpx;
.Gb-text-top {
display: flex;
align-items: center;
text {
&:nth-child(1) {
padding-top: 8rpx;
font-size: 24rpx;
color: #333333;
}
&:nth-child(2) {
padding-top: 8rpx;
font-size: 24rpx;
color: #ec3333;
}
&:nth-child(3) {
font-size: 38rpx;
font-weight: bold;
color: #ec3333;
}
}
}
.Gb-text-bottom {
font-size: 24rpx;
color: #999999;
}
}
&-icon {
display: flex;
align-items: center;
flex-direction: column;
height: 80rpx;
text {
&:first-child {
font-size: $font-2;
}
&:last-child {
font-size: $uni-font-size-tiny;
color: $text-color-n1;
}
}
.iconfont {
font-size: 46rpx;
}
}
button {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 80rpx;
font-size: 32rpx;
// font-weight: bold;
border-radius: $border-radius-2;
&.disabled {
opacity: 0.7;
}
}
&-car {
border: $border-sm solid $border-color-search;
background: $white;
color: $font-color-search;
width: 42%;
}
&-buy {
color: $white;
background-image: $background-primary;
width: 42%;
}
&-similar {
color: $white;
background-image: $background-primary;
width: 85%;
}
}
</style>
<template>
<view
:class="['tui-keyboard-input', 'tui-pwd-box']"
:style="{ backgroundColor: backgroundColor }"
>
<view :class="['tui-inner-box', { 'input-box-border': border }]">
<view
v-for="(item, index) in inputvalue"
:key="index"
class="tui-input"
:class="[
inputvalue.length === 4 ? 'tui-margin-right' : '',
{ 'input-border': border },
{ 'input-last': border && index === inputvalue.length - 1 },
{ 'input-inputing': !border && (inputvalue[index - 1] || index === 0) },
{ 'input-number': !border }
]"
:style="{
fontSize: size + 'rpx',
color: color,
width: (inputvalue.length === 4 ? 90 : 70) + 'rpx'
}"
>{{ item }}</view
>
</view>
</view>
</template>
<script>
export default {
name: "TuiKeyboardInput",
props: {
//背景颜色
backgroundColor: {
type: String,
default: "#fff"
},
size: {
type: Number,
default: 32
},
color: {
type: String,
default: "#333"
},
//输入框的值:数组格式,长度即为输入框个数
inputvalue: {
type: Array,
default: () => ["", "", "", "", "", ""] //密码圆点 ●
},
border: {
type: Boolean,
default: false
}
},
data() {
return {};
}
};
</script>
<style scoped>
.tui-pwd-box {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
vertical-align: top;
}
.tui-inner-box {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.input-box-border {
border-radius: 8rpx;
border: 1px solid #dcdcdc;
}
.tui-input {
height: 90rpx;
position: relative;
display: flex;
align-items: center;
justify-content: center;
margin-right: 50rpx;
border-bottom: 4rpx solid #dcdcdc;
}
.input-border {
flex: 1;
border: none;
margin-right: 0px;
border-right: 2rpx solid #dcdcdc;
}
.input-last {
border: none;
}
.input-inputing {
border-color: #666666;
}
.input-number {
font-size: 52rpx !important;
}
.tui-margin-right {
margin-right: 30rpx;
}
.tui-input:last-child {
margin-right: 0 !important;
}
</style>
<template>
<view>
<view
v-if="mask"
class="tui-keyboard-mask"
:class="[show ? 'tui-mask-show' : '']"
@tap="handleClose"
/>
<view
class="tui-keyboard"
:class="{
'tui-keyboard-radius': radius,
'tui-keyboard-action': action,
'tui-keyboard-show': show
}"
>
<slot />
<view class="tui-keyboard-grids">
<!--{{(index==9 || index==10 || index==11)?'tui-grid-bottom':''}}-->
<view
v-for="(item, index) in itemList"
:key="index"
class="tui-keyboard-grid"
:class="{ 'tui-bg-gray': index == 9 || index == 11 }"
hover-class="tui-keyboard-hover"
:hover-stay-time="150"
:data-index="index"
@tap="handleClick"
>
<view
v-if="index < 11"
class="tui-keyboard-item"
:class="{ 'tui-fontsize-32': index == 9 }"
>{{ getKeyBoard(index, action) }}</view
>
<view v-else class="tui-keyboard-item">
<view class="tui-icon tui-keyboard-delete" />
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "TuiKeyboard",
props: {
//是否需要mask
mask: {
type: Boolean,
default: true
},
//控制键盘显示
show: {
type: Boolean,
default: false
},
//是否直接显示,不需要动画,一般使用在锁屏密码
action: {
type: Boolean,
default: true
},
//是否带圆角
radius: {
type: Boolean,
default: false
}
},
data() {
return {
itemList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
};
},
methods: {
getKeyBoard: function(index, action) {
var content = index + 1;
if (index == 9) {
content = action ? "取消" : "清除";
} else if (index == 10) {
content = 0;
}
return content;
},
//关闭
handleClose() {
if (!this.show) {
return;
}
this.$emit("close", {});
},
handleClick(e) {
if (!this.show) {
return;
}
const dataset = e.currentTarget.dataset;
this.$emit("click", {
index: Number(dataset.index)
});
}
}
};
</script>
<style scoped>
@font-face {
font-family: "keyboardFont";
src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAASgAA0AAAAABugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAEhAAAABoAAAAch/nJvUdERUYAAARkAAAAHgAAAB4AKQAKT1MvMgAAAZwAAABDAAAAVj4mSapjbWFwAAAB8AAAAD4AAAFCAA/rY2dhc3AAAARcAAAACAAAAAj//wADZ2x5ZgAAAjwAAACsAAAA0BLVU2FoZWFkAAABMAAAAC0AAAA2FXPmsWhoZWEAAAFgAAAAHAAAACQH3gOFaG10eAAAAeAAAAAOAAAAEAwAAABsb2NhAAACMAAAAAoAAAAKAGgAAG1heHAAAAF8AAAAHwAAACABEQBLbmFtZQAAAugAAAFJAAACiCnmEVVwb3N0AAAENAAAACgAAAA6nLlLs3jaY2BkYGAAYukqK754fpuvDNwsDCBwU+tiFBKtwMLA9ABIczAwgUQB4ccH+gAAAHjaY2BkYGBu+N/AEMPCAAJAkpEBFbAAAEcKAm142mNgZGBgYGGwZ2BmAAEmIOYCQgaG/2A+AwAPIgFdAHjaY2BkYWCcwMDKwMDUyXSGgYGhH0IzvmYwYuQAijKwMjNgBQFprikMDs93PN/B3PC/gSGGuYGhASjMCJIDAPenDU0AeNpjYYAAFigGAACAAA0AAHjaY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+8x3//0NICW+oSgZGNgYYk4GRCUgwMaACRoZhDwAItAhZAAAAAAAAAAAAAABoAAB42l3MTQqCUBSG4fNpqBxECS/+YFTXRGcFKteZjW0nuoqWVtOgPbgKZ1cqaBDN3snzkklE+xUZEwUkqSOCzGx4EGGEsJYd2vURgQdbomhayC0iu8h8lEVmiR1sS4TVGVFYqeaEVjXmVT8TsWjf83yYIjFq1QM9I0/1c9HMMI06zfHgmMeRY8HDwOKnjSlYZvdQ5u4yB+gVbqrX97cAOxsHn9GF/9G3iV4WbSWBeNp9kD1OAzEQhZ/zByQSQiCoXVEA2vyUKRMp9Ailo0g23pBo1155nUg5AS0VB6DlGByAGyDRcgpelkmTImvt6PObmeexAZzjGwr/3yXuhBWO8ShcwREy4Sr1F+Ea+V24jhY+hRvUf4SbuFUD4RYu1BsdVO2Eu5vSbcsKZxgIV3CKJ+Eq9ZVwjfwqXMcVPoQb1L+EmxjjV7iFa2WpDOFhMEFgnEFjig3jAjEcLJIyBtahOfRmEsxMTzd6ETubOBso71dilwMeaDnngCntPbdmvkon/mDLgdSYbh4FS7YpjS4idCgbXyyc1d2oc7D9nu22tNi/a4E1x+xRDWzU/D3bM9JIbAyvkJI18jK3pBJTj2hrrPG7ZynW814IiU68y/SIx5o0dTr3bmniwOLn8owcfbS5kj33qBw+Y1kIeb/dTsQgil2GP5PYcRkAAAB42mNgYoAALjDJyIAOWMCiTIxM/FmZiXkFiXnxxRmJeckZpQA1nQZRAAAAAf//AAIAAQAAAAwAAAAWAAAAAgABAAMAAwABAAQAAAACAAAAAHjaY2BgYGQAgqtL1DlA9E2ti1EwGgA9dwYGAAA=)
format("woff");
font-weight: normal;
font-style: normal;
}
.tui-icon {
font-family: "keyboardFont" !important;
font-size: 22px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
line-height: 1;
color: #333;
}
.tui-keyboard-delete:before {
content: "\e7b8";
}
.tui-keyboard-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 998;
transition: all 0.3s ease-in-out;
opacity: 0;
visibility: hidden;
}
.tui-mask-show {
opacity: 1;
visibility: visible;
}
.tui-keyboard {
width: 100%;
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
padding-bottom: env(safe-area-inset-bottom);
background-color: #fff;
}
.tui-keyboard-radius {
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
overflow: hidden;
}
.tui-keyboard-action {
visibility: hidden;
transform: translate3d(0, 100%, 0);
transform-origin: center;
transition: all 0.3s ease-in-out;
}
.tui-keyboard-show {
transform: translate3d(0, 0, 0);
visibility: visible;
}
.tui-bg-gray {
background-color: #e7e6eb !important;
}
.tui-keyboard-grids {
width: 100%;
position: relative;
overflow: hidden;
display: flex;
display: -webkit-flex;
flex-direction: row;
flex-wrap: wrap;
}
.tui-keyboard-grids::after {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
border-top: 1px solid #eaeef1;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
.tui-keyboard-grid {
position: relative;
padding: 24rpx 20rpx;
box-sizing: border-box;
background-color: #fff;
width: 33.33333333%;
}
.tui-keyboard-grid:nth-of-type(3n)::before {
width: 0;
border-right: 0;
}
.tui-keyboard-grid::before {
content: " ";
position: absolute;
right: 0;
top: 0;
width: 1px;
bottom: 0;
border-right: 1px solid #eaeef1;
-webkit-transform-origin: 100% 0;
transform-origin: 100% 0;
-webkit-transform: scaleX(0.5);
transform: scaleX(0.5);
}
.tui-keyboard-grid::after {
content: " ";
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #eaeef1;
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
.tui-grid-bottom::after {
height: 0 !important;
border-bottom: 0 !important;
}
.tui-keyboard-hover {
background-color: #f7f7f9 !important;
}
.tui-keyboard-item {
display: flex;
align-items: center;
justify-content: center;
font-size: 48rpx;
height: 60rpx;
color: #000;
}
.tui-fontsize-32 {
font-size: 32rpx;
color: #333 !important;
}
</style>
<template>
<view class="scroll-wrap" :disable-scroll="isShow">
<scroll-view :scroll-y="true" class="scroll-Y" enable-back-to-top @scrolltolower="getData">
<view v-if="isShow" class="mark" catchtouchmove="true" />
<slot />
<more />
<view class="good">
<goodsCard :no-share="true" :show-header="false" :goods-list="getGoodsList" />
</view>
<uni-load-more :status="noMore ? 'loading' : 'noMore'" />
</scroll-view>
</view>
</template>
<script>
import goodsCard from "./goodsCard";
import more from "./more";
import { getGoodsList } from "../api/home.api";
import uniLoadMore from "@/components/uni-load-more/uni-load-more.vue";
export default {
components: {
more,
goodsCard,
uniLoadMore
},
props: {
pageType: Number,
isShow: Boolean
},
data() {
return {
getGoodsList: [],
noMore: true,
progress: "finished",
params: {
pageSize: 10,
pageNo: 1,
pageType: this.pageType
}
};
},
watch: {
isShow: {
deep: true,
immediate: true,
handler(val) {
console.log(val, "11");
}
}
},
mounted() {
this.getData();
},
methods: {
async getData() {
if (!this.noMore || this.progress === "loading") return;
this.progress = "loading";
const [data = {}] = await getGoodsList({ ...this.params });
this.progress = "finished";
this.params.pageNo++;
data.goodsList = data.goodsList || [];
this.noMore = data.hasNext;
this.getGoodsList = [...this.getGoodsList, ...data.goodsList];
}
}
};
</script>
<style lang="scss">
.scroll-wrap {
height: 100vh;
.scroll-Y {
height: 100%;
.good {
padding: 0 $uni-spacing-row-base;
}
}
}
.mark {
position: absolute;
height: 100%;
color: #fff;
background: rgba(0, 0, 0, 0.5);
left: 0%;
right: 0%;
font-size: 26rpx;
text-align: center;
box-shadow: 2px -3px 100px -5px #ffffff;
z-index: 99;
}
</style>
<template>
<view class="maxMemberInstallment">
<view class="content">
<image v-if="iconUrl" class="icon" mode="heightFix" :src="iconUrl" />
<text>小程序暂不支持MAX会员免息分期,请移步APP操作</text>
</view>
</view>
</template>
<script>
export default {
props: {
displayInfo: {
type: Object,
default: () => {}
}
},
computed: {
iconUrl() {
let url = "";
try {
url = this.displayInfo.installmentInfo.cancelInterestExplainImgUrl;
} catch (e) {
url = "";
}
return url;
}
}
};
</script>
<style lang="scss" scoped>
.maxMemberInstallment {
width: 100%;
padding: 16rpx;
.content {
display: flex;
width: 100%;
height: 48rpx;
background: #e8f6ff;
font-size: 22rpx;
color: #001746;
border-radius: 8rpx;
padding: 0 4px;
align-items: center;
.icon {
width: auto;
margin-right: 8rpx;
height: 32rpx;
}
}
}
</style>
<template>
<view class="content">
<view
class="mix-list-cell"
:class="border"
hover-class="cell-hover"
:hover-stay-time="50"
@click="eventClick"
>
<text
v-if="icon"
class="cell-icon iconfont"
:style="[
{
color: iconColor
}
]"
:class="icon"
/>
<text class="cell-tit clamp">{{ title }}</text>
<text v-if="tips" class="cell-tip">{{ tips }}</text>
<text class="cell-more iconfont" :class="typeList[navigateType]" />
</view>
</view>
</template>
<script>
/**
* 简单封装了下, 应用范围比较狭窄,可以在此基础上进行扩展使用
* 比如加入image, iconSize可控等
*/
export default {
props: {
icon: {
type: String,
default: ""
},
title: {
type: String,
default: "标题"
},
tips: {
type: String,
default: ""
},
navigateType: {
type: String,
default: "right"
},
border: {
type: String,
default: "b-b"
},
hoverClass: {
type: String,
default: "cell-hover"
},
iconColor: {
type: String,
default: "#333"
}
},
data() {
return {
typeList: {
left: "icon-arrow-left",
right: "icon-arrow",
up: "icon-arrow-up",
down: "icon-arrow-down"
}
};
},
methods: {
eventClick() {
this.$emit("eventClick");
}
}
};
</script>
<style lang="scss">
.icon .mix-list-cell.b-b:after {
left: 90rpx;
}
.mix-list-cell {
display: flex;
align-items: baseline;
padding: 20rpx $page-row-spacing;
line-height: 60rpx;
position: relative;
&.cell-hover {
background: #fafafa;
}
&.b-b:after {
left: 30rpx;
}
.cell-icon {
align-self: center;
width: 56rpx;
max-height: 60rpx;
font-size: 38rpx;
}
.cell-more {
align-self: center;
font-size: 30rpx;
color: $font-color-base;
margin-left: $uni-spacing-row-sm;
}
.cell-tit {
flex: 1;
font-size: $font-base;
color: $font-color-dark;
margin-right: 10rpx;
}
.cell-tip {
font-size: $font-sm + 2rpx;
color: $font-color-light;
}
}
</style>
<template>
<view
class="tui-modal__container"
:class="[show ? 'tui-modal-show' : '']"
:style="{ zIndex: zIndex }"
@touchmove.stop.prevent
>
<view
class="tui-modal-box"
:style="{
width: width,
padding: padding,
borderRadius: radius,
backgroundColor: backgroundColor,
zIndex: zIndex + 1
}"
:class="[fadeIn || show ? '-normal' : 'tui-modal-scale', show ? 'tui-modal-show' : '']"
>
<view v-if="!custom">
<image
v-if="!closeIcon"
src="https://img.lkbang.net/xcx/close.png"
class="close-icon"
@click="handleClickCancel"
/>
<view v-if="title" class="tui-modal-title">{{ title }}</view>
<view
class="tui-modal-content"
:class="[title ? '' : 'tui-mtop']"
:style="{ color: color, fontSize: size + 'rpx' }"
><slot
/></view>
<view class="tui-modalBtn-box" :class="[button.length != 2 ? 'tui-flex-column' : '']">
<slot name="footer">
<block v-for="(item, index) in button" :key="index">
<button
class="tui-modal-btn"
:class="[
'tui-' + (item.type || 'primary') + (item.plain ? '-outline' : ''),
button.length != 2 ? 'tui-btn-width' : '',
button.length > 2 ? 'tui-mbtm' : '',
shape == 'circle' ? 'tui-circle-btn' : ''
]"
:hover-class="'tui-' + (item.plain ? 'outline' : item.type || 'primary') + '-hover'"
:data-index="index"
@tap="handleClick"
>
{{ item.text || "确定" }}
</button>
</block>
</slot>
</view>
</view>
<view v-else><slot /></view>
</view>
<view
class="tui-modal-mask"
:class="[show ? 'tui-mask-show' : '']"
:style="{ zIndex: maskZIndex }"
@tap="handleClickCancel"
/>
</view>
</template>
<script>
export default {
name: "TuiModal",
props: {
//是否显示
show: {
type: Boolean,
default: false
},
width: {
type: String,
default: "90%"
},
backgroundColor: {
type: String,
default: "#fff"
},
padding: {
type: String,
default: "40rpx 64rpx"
},
radius: {
type: String,
default: "24rpx"
},
//标题
title: {
type: String,
default: ""
},
//内容
content: {
type: String,
default: ""
},
//内容字体颜色
color: {
type: String,
default: "#999"
},
//内容字体大小 rpx
size: {
type: Number,
default: 28
},
//形状 circle, square
shape: {
type: String,
default: "square"
},
button: {
type: Array,
default: function() {
return [
{
text: "取消",
type: "red",
plain: true //是否空心
},
{
text: "确定",
type: "red",
plain: false
}
];
}
},
//点击遮罩 是否可关闭
maskClosable: {
type: Boolean,
default: true
},
//淡入效果,自定义弹框插入input输入框时传true
fadeIn: {
type: Boolean,
default: false
},
//自定义弹窗内容
custom: {
type: Boolean,
default: false
},
//容器z-index
zIndex: {
type: Number,
default: 9997
},
//mask z-index
maskZIndex: {
type: Number,
default: 9990
},
closeIcon: {
type: Boolean,
default: false
}
},
data() {
return {};
},
methods: {
handleClick(e) {
if (!this.show) return;
const dataset = e.currentTarget.dataset;
this.$emit("click", {
index: Number(dataset.index)
});
},
handleClickCancel() {
if (!this.maskClosable) return;
this.$emit("cancel");
}
}
};
</script>
<style scoped>
.tui-modal__container {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
visibility: hidden;
}
.tui-modal-box {
position: relative;
opacity: 0;
visibility: hidden;
box-sizing: border-box;
transition: all 0.3s ease-in-out;
margin-bottom: 200rpx;
}
.close-icon {
width: 30rpx;
height: 30rpx;
position: absolute;
right: 40rpx;
top: 40rpx;
}
.tui-modal-scale {
transform: scale(0);
}
.tui-modal-normal {
transform: scale(1);
}
.tui-modal-show {
opacity: 1;
visibility: visible;
}
.tui-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
transition: all 0.3s ease-in-out;
opacity: 0;
visibility: hidden;
}
.tui-mask-show {
visibility: visible;
opacity: 1;
}
.tui-modal-title {
text-align: center;
font-size: 32rpx;
color: #333;
padding-top: 20rpx;
font-weight: bold;
}
.tui-modal-content {
text-align: center;
color: #999;
font-size: 28rpx;
padding-top: 24rpx;
padding-bottom: 24rpx;
}
.tui-mtop {
margin-top: 30rpx;
}
.tui-mbtm {
margin-bottom: 30rpx;
}
.tui-modalBtn-box {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.tui-flex-column {
flex-direction: column;
}
.tui-modal-btn {
width: 46%;
height: 68rpx;
line-height: 68rpx;
position: relative;
border-radius: 10rpx;
font-size: 26rpx;
overflow: visible;
margin-left: 0;
margin-right: 0;
}
.tui-modal-btn::after {
content: " ";
position: absolute;
width: 200%;
height: 200%;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
transform: scale(0.5, 0.5) translateZ(0);
left: 0;
top: 0;
border-radius: 20rpx;
z-index: 2;
}
.tui-btn-width {
width: 80% !important;
}
.tui-primary {
background: #5677fc;
color: #fff;
}
.tui-primary-hover {
background: #4a67d6;
color: #e5e5e5;
}
.tui-primary-outline {
color: #5677fc;
background: transparent;
}
.tui-primary-outline::after {
border: 1px solid #5677fc;
}
.tui-danger {
background: #ed3f14;
color: #fff;
}
.tui-danger-hover {
background: #d53912;
color: #e5e5e5;
}
.tui-danger-outline {
color: #ed3f14;
background: transparent;
}
.tui-danger-outline::after {
border: 1px solid #ed3f14;
}
.tui-red {
background: #e41f19;
color: #fff;
}
.tui-red-hover {
background: #c51a15;
color: #e5e5e5;
}
.tui-red-outline {
color: #e41f19;
background: transparent;
}
.tui-red-outline::after {
border: 1px solid #e41f19;
}
.tui-warning {
background: #ff7900;
color: #fff;
}
.tui-warning-hover {
background: #e56d00;
color: #e5e5e5;
}
.tui-warning-outline {
color: #ff7900;
background: transparent;
}
.tui-warning-outline::after {
border: 1px solid #ff7900;
}
.tui-green {
background: #19be6b;
color: #fff;
}
.tui-green-hover {
background: #16ab60;
color: #e5e5e5;
}
.tui-green-outline {
color: #19be6b;
background: transparent;
}
.tui-green-outline::after {
border: 1px solid #19be6b;
}
.tui-white {
background: #fff;
color: #333;
}
.tui-white-hover {
background: #f7f7f9;
color: #666;
}
.tui-white-outline {
color: #333;
background: transparent;
}
.tui-white-outline::after {
border: 1px solid #333;
}
.tui-gray {
background: #ededed;
color: #999;
}
.tui-gray-hover {
background: #d5d5d5;
color: #898989;
}
.tui-gray-outline {
color: #999;
background: transparent;
}
.tui-gray-outline::after {
border: 1px solid #999;
}
.tui-outline-hover {
opacity: 0.6;
}
.tui-circle-btn {
border-radius: 40rpx !important;
}
.tui-circle-btn::after {
border-radius: 80rpx !important;
}
</style>
<template>
<text class="more">
{{ text }}
</text>
</template>
<script>
export default {
props: {
text: {
type: String,
default() {
return "更多宝贝";
}
}
}
};
</script>
<style lang="scss">
@mixin line {
content: "";
width: 100rpx;
height: 1rpx;
border-top: 1rpx solid #ccc;
}
.more {
font-size: 24rpx;
color: #999999;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
position: relative;
padding: 20rpx 0;
&:after {
@include line;
margin-left: 14rpx;
}
&:before {
@include line;
margin-right: 14rpx;
}
}
</style>
<template>
<view class="nav-bar_container">
<view class="nav-bar_statusBar" :style="[statusBarStyle]" />
<view class="nav-bar_tween" :style="[tweenStyle]" />
<view class="nav-bar" :style="[offsetStyle]">
<view v-if="leftBtns" class="nav-bar_left" :style="[leftStyle]">
<slot name="left">
<view
v-for="(item, index) in leftBtns"
:key="index"
class="nav-bar_left-item"
@click="clickLeftBtn(index, item)"
>
<i :class="['iconfont', 'icon-' + item.icon]" />
<text v-if="item.title">{{ item.title }}</text>
</view>
</slot>
</view>
<view class="nav-bar_title" :style="{ color: titleColor }">
<view v-if="scrollTop > 0 || topShowTitle || bgStatus === 'solid'">
<slot name="title">
<text v-if="!searchBar">{{ title }}</text>
<view v-else class="search-header" :style="[leftStyle]" @click="navToSearch">
<text class="iconfont icon-search Sh-icon" />
<view class="Sh-placeholder">搜索商品</view>
</view>
</slot>
</view>
</view>
<view class="nav-bar_cube" :style="[cubeStyle]" />
</view>
</view>
</template>
<script>
import { saTrackEvent } from "@/utils/sa.js";
/**
* NavBar 自定义标题栏实现
* @description 主要用户标题栏为custom时,效果实现,滚动显示,回退
* ! 需要注意,在自定义组件模式下,组件不存在onPageScroll这个声明周期,此组件通过监听props实现
*/
const CLICK_LEFT_EVENT = "leftClick"; // 左侧按钮点击事件
export default {
name: "NavBar",
props: {
// 标题栏背景色
bgColor: {
type: String,
default: "#ffffff"
},
// 标题内容
title: {
type: String,
default: "标题"
},
// 标题颜色
titleColor: {
type: String,
default: "#000"
},
// 背景展示方式, none - 透明,solid - 不透明,scroll - 滚动显示
bgStatus: {
type: String,
default: "scroll"
},
position: {
type: String,
default: "fixed"
},
// 顶部偏移量
offset: {
type: Number,
default: 0
},
// 滚动状态下,顶部是否显示title
topShowTitle: {
type: Boolean,
default: false
},
// 滚动条高度
scrollTop: {
type: Number,
default: 0
},
// 状态栏是否占位
statusBar: {
type: Boolean,
default: false
},
// 搜索框
searchBar: {
type: Boolean,
default: true
},
// 左侧按钮组,默认显示返回,false不展示,scroll状态下会添加圆形白色背景
leftBtns: {
type: [Array, Boolean],
default: function() {
return [];
}
}
},
data() {
return {
statusBarHeight: 50,
cubeInfo: {},
navbarHeight: 70
};
},
computed: {
// 标题栏样式
offsetStyle() {
const {
statusBarHeight,
offset,
bgStatus,
bgColor,
scrollTop,
cubeInfo,
navbarHeight
} = this;
let mgRight = cubeInfo.marginRight;
// #ifdef MP-BAIDU
mgRight -= 5;
// #endif
return {
marginTop: statusBarHeight + offset + "px",
padding: `0 ${mgRight + "px"}`,
height: navbarHeight + "px",
// eslint-disable-next-line
backgroundColor: bgStatus == 'solid' ? bgColor : bgStatus == "none" ? "transparent" : bgStatus == "scroll" && scrollTop == 0 ? "transparent" : bgColor
};
},
// 页面顶部补间样式,防止跳动
tweenStyle() {
const {
statusBarHeight,
offset,
bgStatus,
bgColor,
scrollTop,
statusBar,
navbarHeight
} = this;
// eslint-disable-next-line
let _height = offset + (bgStatus == "none" ? 0 : bgStatus == "scroll" && scrollTop == 0 ? 0 : navbarHeight + (!statusBar ? statusBarHeight : 0));
return {
height: _height + "px",
backgroundColor: bgStatus !== "scroll" ? bgColor : "transparent",
// eslint-disable-next-line
position: bgStatus == "none" ? "fixed" : bgStatus == "scroll" && scrollTop > 0 ? "fixed" : "relative"
};
},
// 状态栏样式
statusBarStyle() {
const { statusBarHeight, bgColor, statusBar } = this;
return {
height: (statusBar ? statusBarHeight : 0) + "px",
backgroundColor: bgColor
};
},
cubeStyle() {
return {
width: this.cubeInfo.width + "px"
};
},
leftStyle() {
return {
height: this.cubeInfo.height + "px",
lineHeight: this.cubeInfo.height + "px"
};
}
},
watch: {
// !监听滚动条高度
scrollTop: {
immediate: true,
handler() {
if (this.bgStatus != "scroll") return;
}
}
},
created() {
this.getNavBarHeight();
},
// onPageScroll(e) {
// this.scrollTop = e.scrollTop;
// console.log(e);
// },
methods: {
clickLeftBtn(index, item) {
this.$emit(CLICK_LEFT_EVENT, { index, item });
},
navToSearch() {
saTrackEvent("PD_YXMMAEC_UserClickSearchTrigger", {});
uni.navigateTo({
url: `/pages/search/index?keyWords=`
});
},
getNavBarHeight() {
const sysInfo = uni.getSystemInfoSync();
const cubeInfo = uni.getMenuButtonBoundingClientRect();
this.statusBarHeight = sysInfo.statusBarHeight;
this.navbarHeight = (cubeInfo.top - sysInfo.statusBarHeight) * 2 + cubeInfo.height;
cubeInfo.marginRight = sysInfo.windowWidth - cubeInfo.right;
this.cubeInfo = cubeInfo;
this.$emit("getHeight", this.statusBarHeight + this.navbarHeight);
}
}
};
</script>
<style lang="scss">
@mixin border-line {
content: "";
pointer-events: none;
display: block;
position: absolute;
left: 0;
top: 0;
transform-origin: 0 0;
border: 1rpx solid rgba(151, 151, 151, 0.2);
box-sizing: border-box;
width: 200%;
height: 200%;
transform: scale(0.5);
}
.nav-bar {
position: fixed;
z-index: 999999;
top: 0;
left: 0;
width: 100%;
// transition: all 0.2s linear;
display: flex;
align-items: center;
&_tween {
width: 100%;
z-index: 999999;
}
&_left {
display: flex;
align-items: center;
border: 1rpx solid rgba(151, 151, 151, 0.2);
border-radius: 100rpx;
&-item {
width: 86rpx;
text-align: center;
position: relative;
text-align: center;
&::before {
content: " ";
display: block;
position: absolute;
top: 12rpx;
right: 0;
height: 37rpx;
width: 1rpx;
background-color: rgba(0, 0, 0, 0.2);
}
&:last-child {
&::before {
display: none;
}
}
/* #ifdef MP-BAIDU */
.icon-arrow-left {
color: #fff;
}
&:first-child {
width: 70rpx;
}
/* #endif */
}
i {
font-size: 34rpx;
position: relative;
z-index: 2;
}
}
&_title {
flex: 1;
text-align: center;
padding: 4rpx 16rpx;
margin: 0 auto;
font-size: 32rpx;
font-weight: 600;
/* #ifdef MP-ALIPAY */
padding-right: 45px;
/* #endif */
}
&_cube {
background-color: rgba(251, 255, 0, 0.384);
}
}
.search-header {
position: relative;
display: flex;
align-items: center;
padding: 12rpx;
background: rgba(255, 255, 255, 0.6);
border-radius: 100rpx;
border: 1rpx solid rgba(151, 151, 151, 0.2);
.Sh {
&-icon {
font-size: 32rpx;
color: #c8c9cc;
margin-right: 10rpx;
}
&-placeholder {
font-size: 28rpx;
font-weight: 400;
line-height: 40rpx;
color: #c8c9cc;
}
}
}
</style>
<template>
<view class="order-card">
<view class="confirm-state">
<view class="state-title">当前订单状态</view>
<view
class="state-txt"
:class="
orderData.orderStatusText === '已完成' || orderData.orderStatusText === '交易关闭'
? 'color-gray'
: orderData.orderStatusText === '售后中'
? 'state-txt'
: ''
"
>
{{ orderData.orderStatusText }}
</view>
</view>
<view class="confirm-goods-box">
<view
v-for="(item, inx) in orderData.skuList"
:key="inx"
class="confirm-goods"
@click="goodsDealer"
>
<image class="confirm-goods-left" mode="aspectFit" :src="item.imageUrl" />
<view class="confirm-goods-middle">
<text class="Cg-middle-name">{{ item.skuName || "" }}</text>
</view>
<view class="confirm-goods-right">
<view class="gR-top">
<text>¥{{ item.salePrice || "0.00" }}</text>
<text>{{ item.count }}</text>
</view>
<view
v-if="
item.havingService && (orderData.orderStatus == 31 || orderData.orderStatus == 41)
"
class="gR-bottom"
>
<button @click.stop="toAftersale(item)">
售后中
</button>
</view>
</view>
</view>
</view>
<view class="confirm-sum">
<!-- <text>总价¥{{ orderData.originalFee || 0 }},</text> -->
<!-- <text>优惠¥{{ orderData.reduceFee || 0 }},</text> -->
<text v-if="orderData.orderStatus == 11" class="stress"
>待付款 ¥{{ orderData.totalFee || 0 }}</text
>
<text v-else class="stress">实付款 ¥{{ orderData.totalFee || 0 }}</text>
</view>
<view v-if="[11, 21, 31, 41].indexOf(orderData.orderStatus) > -1" class="confirm-status">
<text class="confirm-status-left Cs-left-orange" />
<!-- 等待买家付款 -->
<view v-if="orderData.orderStatus == 11" class="confirm-status-right">
<button class="Cs-right_grey" @click="handleOptionClick('cancel')">
取消订单
</button>
<button class="Cs-right_red" @click="handleOptionClick('pay')">付款</button>
</view>
<!-- 等待卖家发货 -->
<view v-else-if="orderData.orderStatus == 21" class="confirm-status-right">
<!-- isShowRefund===1 && isShowRefundAudit===1 展示审核中 -->
<!-- isShowRefund===1 && isShowRefundAudit===0 展示申请退款 -->
<view v-if="orderData.isShowRefund">
<button v-if="orderData.isShowRefundAudit" class="Cs-right_grey" disabled>
审核中
</button>
<template v-else>
<button
v-if="$config('yxm')"
class="Cs-right_grey"
@click="handleOptionClick('refund')"
>
申请退款
</button>
</template>
</view>
<button class="Cs-right_grey" @click="handleOptionClick('notify')">提醒发货</button>
</view>
<!-- 卖家已发货 31 -->
<view v-else-if="orderData.orderStatus == 31" class="confirm-status-right">
<!-- <button
v-if="orderData.isShowRefund"
class="Cs-right_grey"
@click="handleOptionClick('refund')"
>
申请退款
</button> -->
<button
v-if="orderData.isShowLogistics"
class="Cs-right_grey"
@click="handleOptionClick('logis')"
>
查看物流
</button>
<button
v-if="!orderData.isShowRemindCancel"
class="Cs-right_red"
@click="handleOptionClick('confirm')"
>
确认收货
</button>
</view>
<!-- 交易完成 -->
<view v-else-if="orderData.orderStatus == 41" class="confirm-status-right">
<button
v-if="orderData.isShowLogistics"
class="Cs-right_grey"
@click="handleOptionClick('logis')"
>
查看物流
</button>
<!-- <button class="Cs-right_red" :data-id="skuNo" @click="handleOptionClick('again')">再次购买</button> -->
</view>
</view>
</view>
</template>
<script>
import config from "@/config/index";
// import { kaGetNextUrl } from "@/api/ka.api";
import { REFUND_TYPE } from "../constants/refunnd";
export default {
props: {
idx: [Number, String],
orderData: {
type: Object,
default() {
return {};
}
}
},
data() {
return {
REFUND_TYPE
};
},
computed: {
orderNo() {
return this.orderData.orderNo;
}
},
methods: {
handleOptionClick(eventType) {
const { idx, orderData } = this;
this.$emit("option-click", eventType, idx, orderData);
},
goodsDealer() {
let shipping = false;
if (this.orderData.orderStatusText == "卖家发货中") {
shipping = true;
}
uni.navigateTo({
url: `/pages/order/orderDetail?orderNo=${this.orderNo}&shipping=${shipping}`
});
},
toAftersale(info) {
let { afterServiceType, serviceStatus } = info;
const url = config.MALL_URL;
const vccToken = uni.getStorageSync("token") || "";
const vccChannel = uni.getStorageSync("vccChannel") || "";
const urlpj = `vccChannel=${vccChannel}&vccToken=${vccToken}&orderSkuId=${info.orderSkuId}&orderNo=${this.orderNo}`;
let refundUrlName = "";
// if ([REFUND_TYPE.AUDITING, REFUND_TYPE.REFUNDING].includes(+info.serviceStatus)) {
// refundUrlName = "refundOnlyDetail";
// } else if ([REFUND_TYPE.AUDIT_PASS, REFUND_TYPE.POSTING].includes(+info.serviceStatus)) {
// refundUrlName = "refundDetail";
// } else {
// refundUrlName = "refundType";
// }
// afterServiceType 售后类型 1-仅退货 2-退货退款
// 已经取消售后或者商家拒绝售后 重新走售后流程
let isRefund = [REFUND_TYPE.CANCEL, REFUND_TYPE.UN_ACCEPT, REFUND_TYPE.AUDIT_REFUSE].includes(
+serviceStatus
);
if (+afterServiceType === 1 && !isRefund) {
refundUrlName = "refundOnlyDetail";
} else if (+afterServiceType === 2 && !isRefund) {
refundUrlName = "refundDetail";
} else {
refundUrlName = "refundType";
}
const urlDetail = `${url}/${refundUrlName}?${urlpj}`;
uni.navigateTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(urlDetail))}`
});
}
}
};
</script>
<style lang="scss" scoped>
.confirm-state {
display: flex;
justify-content: space-between;
height: 90rpx;
line-height: 90rpx;
border-bottom: 1rpx solid rgba(216, 216, 216, 0.3);
background: #fff;
padding: 0 24rpx;
font-size: 24rpx;
color: #999;
border-radius: 12rpx 12rpx 0 0;
}
.state-txt {
color: #ec1500;
}
.color-gray {
color: #999999;
}
.color-orange {
color: #faab0c;
}
.order-card {
// font-size: 0;
.confirm-title {
display: inline-block;
padding: 20rpx 20rpx 0;
border-radius: 12rpx 12rpx 0 0;
font-size: 26rpx;
font-weight: bold;
color: #333333;
background: #fff;
width: 100%;
}
.confirm-goods-box {
.confirm-goods:last-child {
padding-bottom: 20rpx;
}
}
.confirm-goods {
display: flex;
padding: 20rpx 20rpx 0;
background: #fff;
&_failure {
align-items: center;
}
&:first-child {
border-radius: 12rpx 12rpx 0 0;
}
&:last-child {
// margin-bottom: 20rpx;
padding-bottom: 20rpx;
// border-radius: 0 0 12rpx 12rpx;
}
&-icon {
margin-right: 10rpx;
width: 56rpx;
height: 32rpx;
line-height: 32rpx;
text-align: center;
border-radius: 16rpx;
background: #979797;
font-size: 20rpx;
color: #ffffff;
}
&-left {
width: 200rpx;
height: 200rpx;
border-radius: 12rpx;
}
&-middle {
flex: 1;
display: flex;
flex-direction: column;
margin: 0 20rpx;
.Cg-middle-name {
/* #ifdef MP-ALIPAY */
line-height: 36rpx;
/* #endif */
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
margin-bottom: 10rpx;
overflow: hidden;
font-size: 26rpx;
color: #333333;
}
.Cg-middle-param {
margin-bottom: 30rpx;
font-size: 24rpx;
color: #999999;
}
.Cg-middle-warn {
display: flex;
align-items: center;
image {
margin-right: 10rpx;
width: 24rpx;
height: 24rpx;
}
text {
font-size: 26rpx;
color: #ec1500;
}
}
.Cg-middle_failure {
text {
color: #333333;
}
}
}
&-right {
display: flex;
flex-flow: column;
justify-content: space-between;
.gR-top {
display: flex;
flex-direction: column;
align-items: flex-end;
width: 120rpx;
text {
&:first-child {
margin-bottom: 10rpx;
font-size: 26rpx;
color: #333333;
}
&:last-child {
font-size: 24rpx;
color: #999999;
}
}
}
.gR-bottom {
button {
margin: 0;
width: 144rpx;
height: 48rpx;
line-height: 48rpx;
font-size: 24rpx;
border-radius: $border-radius-2;
background: $white;
color: #faab0c;
border: $border-sm solid #faab0c;
}
}
}
}
.confirm-sum {
padding: 20rpx;
width: 100%;
height: 70rpx;
font-size: 26rpx;
line-height: 38rpx;
color: #999;
text-align: right;
background: $white;
border-top: 1rpx solid rgba(216, 216, 216, 0.3);
border-radius: 0 0 12rpx 12rpx;
text.stress {
color: #333333;
}
text {
margin-left: 12rpx;
display: inline;
}
}
.confirm-status {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20rpx 20rpx;
height: 100rpx;
background: $white;
border-radius: 0 0 12rpx 12rpx;
&-left {
font-size: 26rpx;
}
.Cs-left_grey {
color: #999999;
}
.Cs-left-orange {
color: $text-color-orange;
}
&-right {
display: flex;
button {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
width: 180rpx;
height: 60rpx;
font-size: $font-base;
border-radius: $border-radius-2;
background: $white;
&:last-child {
margin-left: 10rpx;
}
}
.Cs-right_grey {
border: $border-sm solid $border-gray;
/* color: $text-color-n3; */
color: $text-color-n5;
}
.Cs-right_red {
border: $border-sm solid $border-color-search;
color: $font-color-search;
}
}
}
}
</style>
<template>
<view class="pay-type-list">
<view class="type-title b-b">{{ value.title }}</view>
<payGroupItem
v-if="value.isGroupPay"
:value="payList"
:pay-type="payType"
:disabled="disabled"
:coupon-info="couponInfo"
:show-coupon="showCoupon"
:pay-coupon-list="payCouponList"
:coupon-disabled="showCoupon && !payCouponCouldBeUsed"
/>
<template v-else>
<template v-for="(item, key) of payList">
<payCardItem
v-if="item.show"
:key="key"
:pay-type="payType"
:value="item"
:disabled="disabled"
:coupon-info="couponInfo"
:show-coupon="showCoupon"
:pay-coupon-list="payCouponList"
:coupon-disabled="showCoupon && !payCouponCouldBeUsed"
/>
</template>
</template>
<!-- MAX会员分期免息提示,小程序暂不支持分期功能, -->
<maxMemberInstallmentDesc v-if="showMaxMemberNotice" :display-info="displayInfo" />
</view>
</template>
<script>
import payCardItem from "./payCardItem";
import payGroupItem from "./payGroupCard";
import maxMemberInstallmentDesc from "./maxMemberInstallmentDesc";
export default {
name: "PayCard",
components: {
payCardItem,
payGroupItem,
maxMemberInstallmentDesc
},
provide() {
return {
payCard: this
};
},
props: {
value: Object,
payType: Number,
payText: String,
disabled: Boolean,
couponInfo: Object,
riskLimit: Number,
showCoupon: Boolean,
payCouponCouldBeUsed: Boolean,
payCouponList: { type: Array, default: () => [] },
single: { type: Boolean, default: false },
creditPay: { type: Boolean, default: false },
displayInfo: { type: Object, default: () => {} }
},
data() {
return {
payList: this?.value?.payList || {}
};
},
computed: {
showMaxMemberNotice() {
// 小程序收银台不支持分期功能,MAX会员引导去app下单
if (!this.displayInfo) return false;
let installmentStatus = false; // 分期付款状态
let detailList = []; // 分期付款详情列表
const { installmentInfo } = this.displayInfo;
try {
detailList = installmentInfo.detailList || [];
} catch (e) {
detailList = [];
}
// 遍历分期付款选项,选项中包括免息字段allowCancelInterest,并且值为1,则允许免息
for (let i = 0; i < detailList.length; i++) {
if (detailList[i].allowCancelInterest == 1) {
installmentStatus = true;
break;
}
}
if (!installmentInfo || !installmentInfo.isInstallment || !installmentStatus) return false;
return true;
}
},
watch: {
value(newValuem) {
this.payList = newValuem?.payList || {};
}
}
};
</script>
<style lang="scss">
.pay-type-list {
background-color: #fff;
border-radius: $border-radius-md;
margin-top: $margin-base;
.type-title {
height: 96rpx;
line-height: 96rpx;
font-size: $uni-font-size-lg;
font-weight: bold;
padding-left: $padding-md;
position: relative;
}
}
</style>
<template>
<view class="payCardItem">
<view
:class="['type-item', { 'pay-border': !isGroupPay || value.payType === 1 }]"
@click="changePayType(value)"
>
<view class="type-item-content">
<view class="type-item-content-info">
<image :src="value.icon" class="icon" mode="aspectFit" />
<view class="content-info-con">
<view class="content-info-tit">
<view class="content-info-tit-wrap">
<text class="content-info-tit">{{ value.name }}</text>
<text v-if="value.tagName" class="content-info-tit_tag">{{ value.tagName }}</text>
</view>
<text v-if="isGroupPay && value.payAmt" class="content-info-amount">
{{ value.payAmt }}
</text>
</view>
<text>{{ value.accountStatusDesc }}</text>
</view>
</view>
<!-- <view v-if="showCoupon && value.payType === 1" class="coupon"> -->
<view v-if="value.payType === 1" class="coupon">
<view
class="couponDes"
:class="{ disable: couponDisabled || !payCouponList.length }"
@click.stop="openCouponModal"
>
<template v-if="couponInfo.pickupId">
{{ `满${couponInfo.limitAmountNew}减${couponInfo.faceValueNew}元` }}
</template>
<template v-else>
<!-- 未选择优惠券 -->
<template v-if="!payCouponList.length">暂无优惠券</template>
<template v-else>未选择优惠券</template>
</template>
<text
v-if="payCouponList.length"
:class="{ disable: couponDisabled }"
class="iconfont icon-arrow"
/></view>
</view>
<view
v-if="value.accountStatus === 5 && value.miniFace === 1 && value.riskManagementDesc"
class="limitDes"
>{{ value.riskManagementDesc }}</view
>
<view v-else-if="value.riskLimitDesc" class="limitDes">
{{ value.riskLimitDesc }}
</view>
</view>
<radio
v-if="!isGroupPay"
:class="{ 'radio-cls': value.payType === 1 }"
:value="value.payType"
color="#EC1500"
:checked="payType === value.payType"
:disabled="disabled || value.disabled || (payType === 6 && value.payType !== 6)"
style="transform:scale(0.7)"
/>
<!-- disabled || value.disabled || (payType === 6 && value.payType !== 6) -->
<!-- @click.native="changePayType(value)" -->
</view>
</view>
</template>
<script>
import { saTrackEvent } from "@/utils/sa";
const payTypeE = [
"PD_YXMMAEC_UserClickCashierSelectXiangHuaCardPay",
"PD_YXMMAEC_UserClickCashierSelectWechatPay"
];
const payTypeMiniAppE = ["c_cashierselectxianghuacardpay", "c_cashierselectwechatpay"];
export default {
name: "PayCardItem",
inject: ["payCard", "pay"],
props: {
value: Object,
payType: Number,
disabled: Boolean,
couponInfo: Object,
showCoupon: Boolean,
riskLimit: Boolean,
isGroupPay: Boolean,
couponDisabled: Boolean,
payCouponList: { type: Array, default: () => [] }
},
data() {
return {};
},
methods: {
changePayType({ payType, mergePayPretreatmentInfo }) {
if (this.disabled || this.value.disabled || this.isGroupPay) {
if ((this.value.disabled && this.value.accountStatus) === 5) {
this.pay.openConfigModal(
"canUseAmt",
"抱歉,您的本笔订单暂不支持享花卡支付,请您使用其他支付方式~"
);
}
return;
}
this.pay.changePayType(payType, mergePayPretreatmentInfo);
saTrackEvent(payTypeE[payType - 1], {
order_id: this.pay.orderNo
});
uni.reportAnalytics(payTypeMiniAppE[payType - 1], {
order_id: this.pay.orderNo,
uuid: uni.getStorageSync("userAuthInfo").uuid || "",
channel_id: uni.getStorageSync("vccChannel") || ""
});
},
openCouponModal() {
if (this.couponDisabled) {
this.$api.msg("优惠卷不可更改");
return;
}
this.payCouponList.length && this.pay.openCouponModal(this.pay.orderNo);
}
}
};
</script>
<style lang="scss">
@import "@/style/var.scss";
.payCardItem {
padding-bottom: 2rpx;
}
/* .pay-border {} */
.coupon {
margin-top: 8rpx;
height: 40rpx;
padding-left: 110rpx;
display: flex;
}
.couponDes {
display: inline-block;
color: $text-color-red;
font-size: $font-sm;
border: 1rpx solid $text-color-light;
border-radius: 8rpx;
padding: 0 7rpx;
&.disable {
color: $border-gray;
border-color: $border-gray;
}
text {
color: $text-color-red;
font-size: $font-sm;
&.disable {
color: $font-color-disabled;
}
}
}
.limitDes {
color: #ed6a0c;
background: #fffbe8;
font-size: 22rpx;
padding: 8rpx 16rpx;
margin: 16rpx 16rpx 16rpx 8rpx;
border-radius: 6rpx;
}
.type-item {
// height: 134rpx;
padding: 16rpx;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.radio-cls {
position: absolute;
right: 8px;
top: 30px;
}
&-content {
width: 100%;
}
&-content-info {
width: 100%;
display: flex;
align-items: center;
}
}
.icon {
width: 78rpx;
height: 78rpx;
margin-right: $padding-md;
}
.content-info-tit {
font-size: 30rpx;
color: $font-color-dark;
margin-bottom: 4rpx;
display: flex;
align-items: center;
justify-content: space-between;
&-wrap {
display: flex;
}
&_tag {
display: inline-flex;
align-items: center;
height: 36rpx;
border: $border-sm solid $text-color-light;
border-radius: $uni-border-radius-base;
font-size: 22rpx;
color: $text-color-light;
margin-left: $margin-sm;
padding: 0 5rpx;
}
}
.content-info-con {
flex: 1;
display: flex;
flex-direction: column;
font-size: $font-sm;
color: $font-color-light;
}
.content-info-amount {
width: 200rpx;
text-align: left;
word-break: break-all;
&::before {
content: "¥";
}
@include text-size(30);
color: $black;
}
</style>
<template> <template>
<div> <view @click="changePayType(thirdPayInfo)">
<div @click="changePayType(thirdPayInfo)"> <view class="groupCard">
<div class="groupCard"> <payCardItem
<PayCardItem :is-group-pay="true"
:is-group-pay="true" :value="creditPayInfo"
:value="creditPayInfo"
:coupon-info="couponInfo"
:show-coupon="showCoupon"
:risk-limit="riskLimit"
:coupon-disabled="couponDisabled"
/>
</div>
<div class="dashed">
<p class="dashed-line" />
<cr-image
src="../../../assets/images/pay/addicon.png"
width="24px"
height="24px"
class="dashed-icon"
/>
<cr-checkbox
v-model="thirdPayInfo.isCheck"
shape="round"
checked-color="#EC1500"
:disabled="disabled || thirdPayInfo.disabled"
class="dashed-checkbox"
@click.native="changePayType(thirdPayInfo)"
/>
</div>
<div class="groupCard">
<PayCardItem :is-group-pay="true" :value="thirdPayInfo" />
</div>
</div>
<p class="group-more b-t" @click="openMore">更多支付组合<cr-icon type="arrow" size="15px" /></p>
<cr-popup v-model="morePopup" round position="bottom" :style="{ height: '30%' }" closeable>
<p class="more-title">更换支付组合</p>
<PayCardItem
v-for="item in thirdPayList"
:key="item.payType"
:value="item"
:coupon-info="couponInfo" :coupon-info="couponInfo"
:show-coupon="showCoupon" :show-coupon="showCoupon"
:risk-limit="riskLimit" :risk-limit="riskLimit"
@click="morePopup = false" :pay-coupon-list="payCouponList"
:coupon-disabled="couponDisabled"
/> />
</cr-popup> </view>
</div> <view class="dashed">
<p class="dashed-line" />
<image
src="https://img.lkbang.net/xcx/addicon.png"
width="24px"
height="24px"
class="dashed-icon"
/>
<radio
color="#EC1500"
:checked="thirdPayInfo.isCheck"
:disabled="disabled || thirdPayInfo.disabled"
style="transform:scale(0.7)"
@click.native="changePayType(thirdPayInfo)"
/>
</view>
<view class="groupCard">
<payCardItem :is-group-pay="true" :value="thirdPayInfo" />
</view>
</view>
</template> </template>
<script> <script>
import PayCardItem from './PayCardItem.vue'; import payCardItem from "./payCardItem";
export default { export default {
name: 'PayGroupCard', name: "PayGroupCard",
inject: ['payCard', 'pay'],
components: { components: {
PayCardItem payCardItem
}, },
inject: ["payCard", "pay"],
props: { props: {
value: Object, value: Object,
payType: Number, payType: Number,
...@@ -62,7 +47,8 @@ export default { ...@@ -62,7 +47,8 @@ export default {
couponInfo: Object, couponInfo: Object,
showCoupon: Boolean, showCoupon: Boolean,
riskLimit: Boolean, riskLimit: Boolean,
couponDisabled: Boolean couponDisabled: Boolean,
payCouponList: { type: Array, default: () => [] }
}, },
data() { data() {
return { return {
...@@ -88,25 +74,14 @@ export default { ...@@ -88,25 +74,14 @@ export default {
return temp; return temp;
} }
}, },
watch: {
'value.creditPayInfo'(v) {
this.creditPayInfo = v || {};
this.getThirdPayList();
}
},
mounted() { mounted() {
this.getThirdPayList(); for (const key in this.value) {
if (this.value[key].isGroupPay) {
this.thirdPayList.push(this.value[key]);
}
}
}, },
methods: { methods: {
getThirdPayList() {
const arr = [];
for (const key in this.value) {
if (this.value[key].isGroupPay) {
arr.push(this.value[key]);
}
}
this.thirdPayList = arr;
},
changePayType({ payType, mergePayPretreatmentInfo }) { changePayType({ payType, mergePayPretreatmentInfo }) {
if (this.disabled || this.creditPayInfo.disabled) { if (this.disabled || this.creditPayInfo.disabled) {
return; return;
...@@ -119,12 +94,12 @@ export default { ...@@ -119,12 +94,12 @@ export default {
} }
}; };
</script> </script>
<style lang="less"> <style lang="scss">
.groupCard { .groupCard {
width: 100%; width: 100%;
} }
.group-more { .group-more {
.text-size(13); font-size: $uni-font-size-md;
width: 335px; width: 335px;
height: 36px; height: 36px;
margin: auto; margin: auto;
...@@ -133,14 +108,13 @@ export default { ...@@ -133,14 +108,13 @@ export default {
position: relative; position: relative;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-top: 1px solid @border-color-line;
} }
.cr-popup--close-top-right { .cr-popup--close-top-right {
z-index: 2; z-index: 2;
} }
.dashed { .dashed {
width: 100%; width: 100%;
padding: 0 8px; padding: 0 12px;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -154,6 +128,8 @@ export default { ...@@ -154,6 +128,8 @@ export default {
width: 18px; width: 18px;
} }
&-icon { &-icon {
width: 42rpx;
height: 42rpx;
position: absolute; position: absolute;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
...@@ -161,12 +137,12 @@ export default { ...@@ -161,12 +137,12 @@ export default {
} }
.more-title { .more-title {
.text-size(16); font-size: $uni-font-size-lg;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 48px; height: 48px;
color: @black; color: $black;
position: relative; position: relative;
} }
</style> </style>
<template>
<view class="popup-area">
<view class="currentList">
<text
v-for="(item, index) in areas"
:key="index"
class="selectedName"
:class="currentColumn === index ? 'selectedName--active' : ''"
@click="viewArea(index)"
>{{ item.name }}
</text>
</view>
<view class="swiper">
<view
v-for="(area, index) in areas"
:key="index"
class="area-container"
:class="{ active: currentColumn === index }"
>
<scroll-view :scroll-y="true" class="scroll-area">
<p
v-for="item in area.list"
:key="item.addrName"
class="areaName"
:class="item.addrId === area.selectedId ? 'areaName--active' : ''"
@click="selectArea(item.addrId, item.addrName, index)"
>
{{ item.addrName }}
</p>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import address from "../api/address.api";
export default {
name: "PopupArea",
props: {
resetOnClose: {
type: Boolean,
default: true
}
},
data() {
return {
areas: [],
currentColumn: 0
};
},
computed: {},
created() {
this.loadNext();
},
methods: {
async loadNext(id) {
const [{ addrList: list }] = await address.loadArea(id);
console.log("Address List===============>", list);
if (!list.length) {
this.finish();
return;
}
this.areas.push({
name: "请选择",
id,
selectedId: "",
list
});
return true;
},
async selectArea(id, name, index) {
if (id === this.areas[index].selectedId) return;
this.areas[index].selectedId = id;
this.areas[index].name = name;
this.areas = this.areas.slice(0, index + 1);
const status = await this.loadNext(id);
if (status) {
this.viewArea(index + 1);
}
},
viewArea(index) {
this.currentColumn = index;
},
finish() {
this.$emit(
"finish",
this.areas.map(area => {
return {
name: area.name,
selectedId: area.selectedId
};
})
);
this.reset();
},
reset() {
if (!this.resetOnClose) return;
// 参考京东,只保留省份数据
this.areas = [
{
name: "请选择",
id: "",
selectedId: "",
list: this.areas[0].list
}
];
this.currentColumn = 0;
}
}
};
</script>
<style lang="scss" scoped>
// todo: 整理uni.scss后,修改组件样式
.popup-area {
background-color: $uni-bg-color;
display: flex;
flex-direction: column;
justify-content: flex-start;
.currentList {
display: flex;
flex-direction: row;
position: relative;
&:after {
position: absolute;
content: "";
width: 100%;
left: 0;
bottom: 0;
height: 1px;
background-color: #dcdcdc;
-webkit-transform: scale(1, 0.5);
transform: scale(1, 0.5);
-webkit-transform-origin: center bottom;
transform-origin: center bottom;
}
.selectedName {
// flex: 1;
font-size: 30rpx;
line-height: 50rpx;
color: $uni-text-color;
padding: 10rpx 30rpx;
max-width: 180rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
&--active {
color: $font-color-search;
font-weight: bold;
}
}
}
.swiper {
height: 400px;
.area-container {
display: none;
&.active {
display: block;
}
}
.areaName {
font-size: 26rpx;
line-height: 36rpx;
color: $uni-text-color;
padding: $uni-spacing-col-base 30rpx;
&--active {
color: $font-color-search;
font-weight: bold;
}
}
}
}
.scroll-area {
height: 400px;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
</style>
<template>
<popup ref="popup" background="transparent" class="pop" @change="change">
<modal :title="typeInfo[type].title" type="warning" hide-cancel-btn hide-confirm-btn mkclick>
<view v-if="type !== 'poster'" class="content">
<view class="content__top">{{ typeInfo[type].top }}</view>
<image v-if="typeInfo[type].qr" :src="typeInfo[type].qr" class="content__qrcode" />
<template v-for="item in typeInfo[type].bottom">
<view :key="item.text" class="content__bottom">
<text v-if="item.tag" class="content__bottom--tag">{{ item.tag }}</text>
<tetx class="content__bottom__text">{{ item.text }}</tetx>
</view>
</template>
<template v-for="btn in typeInfo[type].btn">
<button v-if="!btn.type" :key="btn.text" class="content__btn" @click="action(btn)">
{{ btn.text }}
</button>
<view v-else :key="btn.text" class="content__text" @click="action(btn)">
{{ btn.text }}
</view>
</template>
</view>
<view v-if="type === 'poster'" class="content__poster">
<image v-if="typeInfo[type].url" :src="typeInfo[type].url" class="content__poster" />
</view>
</modal>
</popup>
</template>
<script>
import modal from "./uni-popup/uni-popup-dialog";
import popup from "./uni-popup/uni-popup";
import { downApp } from "../utils/index";
import { saTrackEvent } from "@/utils/sa";
import { getFaceUrl } from "@/api/face.api";
export default {
options: { styleIsolation: "shared" },
components: {
modal,
popup
},
props: {
value: {
type: Boolean,
default: false
},
type: {
type: String,
default: "gzh"
},
scene: {
// 用于区分ka渠道活体场景,user -> 我的页面 pay -> 收银台
type: String,
default: "user"
}
},
data() {
return {
vccChannel: "",
sonVccChannel: "",
typeInfo: {
wx: {
url: "https://img.lkbang.net/xcx/downGzh.png",
qr: "https://img.lkbang.net/xcx/gzhQrcode.png",
top: "请关注【羊小咩Plus】公众号,获得更多信息",
title: "关注微信",
bottom: [{ text: "下载保存图片" }, { text: "微信扫一扫识别二维码" }],
btn: [{ text: "保存图片", fn: this.saveEwm }]
},
gzh: {
url: "https://img.lkbang.net/xcx/downGzh.png",
qr: "https://img.lkbang.net/xcx/gzhQrcode.png",
top: "请关注【羊小咩Plus】公众号,获得更多信息",
title: "该功能正在开发中",
bottom: [{ text: "下载保存图片" }, { text: "微信扫一扫识别二维码" }],
btn: [{ text: "保存图片", fn: this.saveEwm }]
},
app: {
url: "https://img.lkbang.net/xcx/downApp.png",
qr: "https://img.lkbang.net/xcx/appQrcode.png",
top: "请在羊小咩APP中完成后续操作",
title: "该功能正在开发中",
bottom: [
{ text: "微信识别图中二维码下载羊小咩APP" },
{ text: "复制链接在浏览器打开前往应用市场下载", tag: "推荐" }
],
btn: [
{ text: "复制链接", fn: this.clipboard },
{ text: "保存图片", fn: this.saveEwm, type: "text" }
]
},
appToFace: {
url: "",
qr: "",
top: "完成后即可释放享花卡额度",
title: "请前往浏览器完成活体认证",
bottom: [
{ text: "复制链接在浏览器打开进行活体认证" }
// { text: "微信识别图中二维码下载羊小咩APP" },
// { text: "复制链接在浏览器打开前往应用市场下载", tag: "推荐" }
],
btn: [
{ text: "复制链接", fn: this.clipboard }
// { text: "保存图片", fn: this.saveEwm, type: "text" }
]
},
poster: {
url: "https://appsync.lkbang.net/FntLKua4kHYylJqI1EPXO7rB4yug"
}
}
};
},
watch: {
value: {
immediate: true,
handler: function(val) {
val ? this.$refs.popup.open && this.$refs.popup.open() : null;
}
}
},
methods: {
saveEwm() {
const _self = this;
uni.getSetting({
success(res) {
if (!res.authSetting["scope.writePhotosAlbum"]) {
uni.authorize({
scope: "scope.writePhotosAlbum",
success() {
//这里是用户同意授权后的回调
_self.saveImage();
},
fail(error) {
console.log(error);
uni.showModal({
title: "温馨提示",
content: "保存图片功能需要您的微信授权才能使用",
cancelText: "不授权",
confirmText: "授权",
confirmColor: "#ec1500",
success: function(res) {
if (res.confirm) {
// 这个 API 是基础库 1.1.0 才有的,所以需要做兼容处理:
if (uni.openSetting) {
uni.openSetting({
//进入授权设置页面手动授权
success: function() {}
});
}
//低版本兼容 做提示操作
else {
uni.showModal({
title: "授权提示",
confirmColor: "#ec1500",
content:
"保存图片需要您的微信授权才能使用,错过授权页面的处理方法:1、删除小程序->重新搜索进入->点击授权按钮;2、可在小程序设置打开相应权限"
});
}
}
//用户继续拒绝授权。
else if (res.cancel) {
uni.showModal({
title: "温馨提示",
content:
"相册授权失败,错过授权页面的处理方法:1、删除小程序->重新搜索进入->点击授权按钮;2、可在小程序设置打开相应权限",
showCancel: false,
confirmColor: "#ec1500",
success: function() {
_self.refuseSaveImage && _self.refuseSaveImage();
}
});
}
}
});
} //这里是用户拒绝授权后的回调
});
} else {
//用户已经授权过了
_self.saveImage();
}
}
});
},
saveImage() {
uni.downloadFile({
url: this.typeInfo[this.type].url,
success: function(res) {
if (res.statusCode === 200) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: function() {
uni.showToast({
title: "保存成功",
icon: "none"
});
},
fail: function() {
uni.showToast({
title: "保存失败",
icon: "none"
});
}
});
}
},
fail: function(error) {
console.log(error);
}
});
},
change(val) {
if (val?.show === false) {
saTrackEvent("PD_YXMMACP_UserClickGuidePopupWindowBtn", {
buttons_name: "遮罩层"
});
}
this.$emit("change", val);
},
async clipboard() {
if (this.type === "appToFace") {
// 活体认证提示
const pages = getCurrentPages();
const page = pages[pages.length - 1];
const orderNo = Object.keys(page.options).length == 0 ? "" : page.options.orderNo;
const pagePath = page.route || "";
const from = pagePath.indexOf("pages/user/user") > -1 ? "user" : "pay";
const token = uni.getStorageSync("token") || "";
this.vccChannel = uni.getStorageSync("vccChannel") || "";
this.sonVccChannel = uni.getStorageSync("sonVccChannel") || "";
console.log(token, from, orderNo);
const [result] = await getFaceUrl(token, from, orderNo);
if (!result) return;
uni.setClipboardData({
data: result.faceUrl,
success: function() {
console.log("open vcc face ocr");
}
});
return;
}
uni.setClipboardData({
data: downApp,
success: function() {
console.log(downApp);
}
});
},
action(btn) {
saTrackEvent("PD_YXMMACP_UserClickGuidePopupWindowBtn", {
buttons_name: btn.text
});
if (this.type === "appToFace") {
const pages = getCurrentPages();
const page = pages[pages.length - 1];
const pagePath = page.route || "";
saTrackEvent("MINI_BodyConfirmationPopupWindowBtnClick", {
page_name: pagePath.indexOf("pages/user/user") > -1 ? "user" : "pay",
buttons_name: btn.text
});
}
btn.fn();
}
}
};
</script>
<style lang="scss">
.pop {
text-align: center;
.uni-dialog-content {
padding: 0 0 48rpx 0;
}
.content {
&__top {
font-size: 24rpx;
color: #999999;
}
&__qrcode {
width: 300rpx;
height: 300rpx;
margin-top: 40rpx;
margin-bottom: 18rpx;
}
&__poster {
width: 300rpx;
height: 500rpx;
}
&__bottom {
font-size: 28rpx;
color: #333333;
margin: 16rpx;
display: flex;
align-items: flex-start;
justify-content: center;
&--tag {
min-width: 60rpx;
font-size: 20rpx;
color: #ffffff;
padding: 4rpx 8rpx;
border-radius: 8rpx;
margin-right: 8rpx;
@include primary-bg;
margin-top: 2rpx;
}
}
&__btn {
color: $white;
margin-top: 48rpx;
font-size: 32rpx;
border-radius: $uni-border-radius-xl;
width: 526rpx;
@include primary-bg;
}
&__text {
font-size: 32rpx;
margin-top: 36rpx;
color: #ec1500;
}
}
}
</style>
<template>
<view>
<view class="canvas-in">
<canvas
:style="{ width: widthIn + 'px', height: heightIn + 'px' }"
canvas-id="graceCanvas"
class="grace-canvas"
/>
<view
v-if="imgSrc != null"
class="grace-canvas-img"
:style="{ width: widthIn + 'px', height: heightIn + 'px' }"
>
<image :src="imgSrc" mode="widthFix" style="width:100%;" @longpress="longpress" />
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
width: 750, // 画布宽度,单位 rpx
height: 1150, // 画布高度
widthIn: 300, // 自动计算转换为 px
heightIn: 500, // 自动计算转换为 px
bgColor: "#7ACBDC", // 背景颜色
bgImg:
"https://img-cdn-qiniu.dcloud.net.cn/uploads/article/20200708/cbac7a710b90ed11fdcffa410f97acb4.jpg",
imgSrc: null
};
},
onLoad: function() {
// 画布初始化
this.context = uni.createCanvasContext("graceCanvas");
this.initSize();
//延迟1秒等待画布创建
setTimeout(() => {
this.draw();
}, 1000);
},
methods: {
// 画布初始化
initSize: function() {
this.widthIn = uni.upx2px(this.width);
this.heightIn = uni.upx2px(this.height);
},
// 海报绘制代码
draw: function() {
// 步骤 01. 绘制背景颜色
this.step01();
// 步骤 02. 绘制背景图片(如果需要,条件结构)
if (this.bgImg != "") {
this.drawBGIMG(this.bgImg, () => {
// 步骤 03
this.step03();
});
} else {
this.step03();
}
},
// 步骤 01 : 绘制背景颜色
step01: function() {
this.context.setFillStyle(this.bgColor);
this.context.fillRect(0, 0, this.widthIn, this.heightIn);
},
// 步骤 03 :
// 3.1 绘制标题 [ 居中对应 x = 画布的一半 ]
// 3.2 绘制验证码
step03: function() {
// 3.1 绘制标题 [ 居中对应 x = 画布的一半 ]
this.drawText(
"GraceUI 更丰富 更漂亮",
this.widthIn / 2,
this.heightIn - 12,
"#FFFFFF",
16,
"center"
);
// 3.2 绘制二维码
uni.downloadFile({
// 此处可修改二维码数据 ?text=您的数据
url: "http://qr.topscan.com/api.php?text=http://grace.hcoder.net",
success: res => {
if (res.statusCode === 200) {
// 绘制二维码
// x = (画布宽度 - 图片宽度 ) / 2
var qrCodeWidth = 180;
var x = (this.widthIn - qrCodeWidth) / 2;
this.context.drawImage(res.tempFilePath, x, 260, qrCodeWidth, qrCodeWidth);
// 3.3 二维码下面的小字描述
this.drawText(
"GraceUI 官网二维码 长按图片保存 ~ ",
this.widthIn / 2,
468,
"#FFFFFF",
12,
"center"
);
// 在最后一步执行 drawIt 完整最终的绘制
this.drawIt();
}
},
fail: function(e) {
console.log(e);
}
});
},
// 绘制文本, 参数 : 文本内容,x,y,颜色,文本大小,横向对齐方式
drawText: function(content, x, y, color, size, align) {
this.context.setFontSize(size);
this.context.setFillStyle(color);
this.context.setTextAlign(align);
this.context.fillText(content, x, y);
},
// 最终绘制函数
drawIt: function() {
this.context.draw(true, () => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: this.widthIn,
height: this.heightIn,
destWidth: this.widthIn,
destHeight: this.heightIn,
canvasId: "graceCanvas",
success: res => {
// 在H5平台下,tempFilePath 为 base64
console.log(res);
this.imgSrc = res.tempFilePath;
}
});
});
},
// 绘制图片,参数 : 图片地址, 绘制完成后执行的回调函数
drawBGIMG: function(img, callback) {
uni.downloadFile({
url: img,
success: res => {
if (res.statusCode == 200) {
// 绘制
uni.getImageInfo({
src: res.tempFilePath,
success: res2 => {
var bgImgHeight = (this.widthIn / res2.width) * res2.height;
console.log(bgImgHeight);
this.context.drawImage(res.tempFilePath, 0, 0, this.widthIn, bgImgHeight);
callback();
}
});
}
}
});
},
// 长按事件
longpress: function() {
console.log("ok");
uni.saveImageToPhotosAlbum({
filePath: this.imgSrc,
success: () => {
console.log("save success");
uni.showToast({
title: "图片已经保存到您的相册~"
});
}
});
}
}
};
</script>
<style>
page {
background-color: #7acbdc;
}
.canvas-in {
width: 100%;
position: relative;
}
/* .grace-canvas {
} */
.grace-canvas-img {
position: absolute;
background-color: #007aff;
z-index: 99;
left: 0;
top: 0;
font-size: 0;
}
</style>
<template>
<view class="pwd-modal">
<modal :show="modal" title="请输入支付密码" @cancel="closeModal">
<view class="amount">
<text class="amount-title" />
<!-- <view class="amount-amount">{{ (+amount || 0).toFixed(2) }}</view> -->
<view class="amount-input">
<keyboard-input :inputvalue="pwdArr" border />
</view>
</view>
<view slot="footer" class="pwd-action">
<text v-if="errorInfo" class="pwd-error">{{ errorInfo }}</text>
<!-- <text class="pwd-set" @click="setPwd">忘记密码?</text> --><!-- 临时隐藏享花卡的需求 -->
</view>
</modal>
<keyboard
:radius="radius"
:show="pwdModal"
:mask="false"
@close="closeKeyboard"
@click="keyboardClick"
/>
</view>
</template>
<script>
import modal from "./modal";
import keyboard from "./keyboard";
import keyboardInput from "./keyboard-input";
import { h5Mixin } from "@/utils/h5Mixin";
import { saTrackEvent } from "@/utils/sa";
export default {
components: {
modal,
keyboard,
keyboardInput
},
mixins: [h5Mixin()],
props: {
modal: {
type: Boolean,
default: false
},
errorInfo: String,
hasPwd: Boolean,
forgetPwdJumpUrl: String,
amount: Number
},
data() {
return {
pwdModal: false,
numberArr: [],
pwdArr: ["", "", "", "", "", ""],
temp: ["", "", "", "", "", ""],
isDel: false
};
},
computed: {},
watch: {
modal: function(val) {
this.pwdModal = val;
},
errorInfo: function(val) {
if (val) {
this.pwdArr = [...this.temp];
this.numberArr = [];
}
}
},
onShow() {},
onLoad() {},
onReady() {},
methods: {
closeModal() {
this.$emit("close", this.modal);
},
closeKeyboard: function() {
this.pwdModal = false;
this.closeModal();
this.numberArr = [];
this.pwdArr = this.temp;
},
keyboardClick: function(e) {
let numberArr = this.numberArr;
let pwdArr = this.pwdArr;
let index = e.index;
if (
(numberArr.length === pwdArr.length || index == undefined) &&
index !== 9 &&
index !== 11
) {
return;
}
if (index == 9) {
//取消键
this.closeKeyboard();
return;
} else if (index == 11) {
//退格键
this.isDel = true;
let len = numberArr.length;
if (len) {
pwdArr.splice(len - 1, 1, "");
} else {
pwdArr = this.temp;
}
numberArr.pop();
} else if (index == 10) {
this.sendSa();
numberArr.push(0);
pwdArr.splice(numberArr.length - 1, 1, "");
} else {
this.sendSa();
numberArr.push(index + 1);
pwdArr.splice(numberArr.length - 1, 1, "");
}
this.numberArr = numberArr;
this.pwdArr = pwdArr;
this.getPwd();
},
getPwd: function() {
//判断并取出密码
if (this.numberArr.length === this.pwdArr.length) {
this.$emit("submit", this.numberArr.join(""));
}
},
async setPwd() {
saTrackEvent("PD_YXMMACP_UserClickForgetPassword");
uni.reportAnalytics("c_forgetpassword", {});
// const url = `${this.forgetPwdJumpUrl}&vccChannel={vccChannel}`;
// this.goH5(url);
this.$emit("setPwd");
},
sendSa() {
if (!this.numberArr.length && !this.isDel) {
saTrackEvent("PD_YXMMACP_UserClickPasswordInputbox");
uni.reportAnalytics("c_passwordinputbox", {});
}
}
}
};
</script>
<style lang="scss">
.amount {
&-title {
font-size: 28rpx;
color: #323233;
}
&-amount {
margin-top: 4px;
font-size: 60rpx;
color: #333333;
&:before {
content: "¥";
font-size: $uni-font-size-sm;
}
}
&-input {
margin-top: 16px;
}
}
.pwd-action {
width: 100%;
display: flex;
justify-content: space-between;
text {
font-size: 28rpx;
color: #666666;
}
.pwd-set {
text-align: right;
flex: 1;
}
.pwd-error {
color: #ee0a24;
flex: 2;
}
}
</style>
<template>
<view
v-if="show"
class="mask"
:style="{ backgroundColor: backgroundColor }"
@click="toggleMask"
@touchmove.stop.prevent="stopPrevent"
>
<view
class="mask-content"
:style="[
{
height: config.height,
transform: transform
}
]"
@click.stop.prevent="stopPrevent"
>
<scroll-view class="view-content" scroll-y>
<view class="share-header">
分享至
</view>
<view class="share-list">
<view
v-for="(item, index) in shareList"
:key="index"
class="share-item"
@click="shareToFriend(item.text)"
>
<image :src="item.icon" mode="" />
<text>{{ item.text }}</text>
</view>
</view>
</scroll-view>
<view class="bottom b-t" @click="toggleMask">取消</view>
</view>
</view>
</template>
<script>
export default {
props: {
contentHeight: {
type: Number,
default: 0
},
//是否是tabbar页面
hasTabbar: {
type: Boolean,
default: false
},
shareList: {
type: Array,
default: function() {
return [];
}
}
},
data() {
return {
transform: "translateY(50vh)",
timer: 0,
backgroundColor: "rgba(0,0,0,0)",
show: false,
config: {}
};
},
created() {
const height = uni.upx2px(this.contentHeight) + "px";
this.config = {
height: height,
transform: `translateY(${height})`,
backgroundColor: "rgba(0,0,0,.4)"
};
this.transform = this.config.transform;
},
methods: {
toggleMask() {
console.log(this.shareList);
//防止高频点击
if (this.timer == 1) {
return;
}
this.timer = 1;
setTimeout(() => {
this.timer = 0;
}, 500);
if (this.show) {
this.transform = this.config.transform;
this.backgroundColor = "rgba(0,0,0,0)";
setTimeout(() => {
this.show = false;
this.hasTabbar && uni.showTabBar();
}, 200);
return;
}
this.show = true;
//等待mask重绘完成执行
if (this.hasTabbar) {
uni.hideTabBar({
success: () => {
setTimeout(() => {
this.backgroundColor = this.config.backgroundColor;
this.transform = "translateY(0px)";
}, 10);
}
});
} else {
setTimeout(() => {
this.backgroundColor = this.config.backgroundColor;
this.transform = "translateY(0px)";
}, 10);
}
},
//防止冒泡和滚动穿透
stopPrevent() {},
//分享操作
shareToFriend(type) {
console.loga("分享操作", type);
this.$api.msg(`分享给${type}`);
this.toggleMask();
}
}
};
</script>
<style lang="scss">
.mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: flex-end;
z-index: 998;
transition: 0.3s;
.bottom {
position: absolute;
left: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 90rpx;
background: #fff;
z-index: 9;
font-size: $font-base + 2rpx;
color: $font-color-dark;
}
}
.mask-content {
width: 100%;
height: 580rpx;
transition: 0.3s;
background: #fff;
&.has-bottom {
padding-bottom: 90rpx;
}
.view-content {
height: 100%;
}
}
.share-header {
height: 110rpx;
font-size: $font-base + 2rpx;
color: font-color-dark;
display: flex;
align-items: center;
justify-content: center;
padding-top: 10rpx;
&:before,
&:after {
content: "";
width: 240rpx;
border-top: 1px solid $border-color-base;
transform: scaleY(0.5);
margin-right: 30rpx;
}
&:after {
margin-left: 30rpx;
margin-right: 0;
}
}
.share-list {
display: flex;
flex-wrap: wrap;
}
.share-item {
min-width: 33.33%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 180rpx;
image {
width: 80rpx;
height: 80rpx;
margin-bottom: 16rpx;
}
text {
font-size: $font-base;
color: $font-color-base;
}
}
</style>
<template>
<view class="sms-modal">
<modal :show="modal" title="请输入短信验证码" @cancel="closeModal">
<view class="sms">
<text class="sms-title">为保证您账户安全,此笔交易需要短信验证</text>
<text class="sms-title phone">已发送至 {{ getPhone() }}</text>
<view class="sms-input">
<keyboard-input :inputvalue="smsArr" />
</view>
</view>
<view slot="footer" class="sms-action">
<text v-if="errorInfo" class="sms-error">{{ errorInfo }}</text>
<text v-if="!send" class="sms-set" @click="sendSms()">获取验证码</text>
<text v-else class="sms-set grey">{{ time }}s后重新获取验证码</text>
</view>
</modal>
<keyboard
:radius="radius"
:show="smsModal"
:mask="false"
@close="closeKeyboard"
@click="keyboardClick"
/>
</view>
</template>
<script>
import modal from "./modal";
import keyboard from "./keyboard";
import keyboardInput from "./keyboard-input";
import { saTrackEvent } from "@/utils/sa";
export default {
components: {
modal,
keyboard,
keyboardInput
},
props: {
modal: {
type: Boolean,
default: false
},
errorInfo: String
},
data() {
return {
smsModal: false,
numberArr: [],
send: false,
smsArr: ["", "", "", "", "", ""],
temp: ["", "", "", "", "", ""],
time: 60,
timer: null,
isDel: false
};
},
computed: {},
watch: {
modal: function(val) {
if (val) {
this.sendSms(1);
}
this.smsModal = val;
},
errorInfo: function(val) {
if (val) {
this.smsArr = [...this.temp];
this.numberArr = [];
}
}
},
onShow() {},
onLoad() {},
onReady() {},
methods: {
closeModal() {
this.clearTimer();
this.$emit("close", this.modal);
},
closeKeyboard: function() {
this.smsModal = false;
this.closeModal();
this.numberArr = [];
this.smsArr = this.temp;
},
keyboardClick: function(e) {
let numberArr = this.numberArr;
let smsArr = this.smsArr;
let index = e.index;
if ((numberArr.length === smsArr.length || index == undefined) && index !== 11) {
return;
}
if (index == 9) {
//取消键
this.closeKeyboard();
return;
} else if (index == 11) {
//退格键
this.isDel = true;
let len = numberArr.length;
if (len) {
smsArr.splice(len - 1, 1, "");
} else {
smsArr = this.temp;
}
numberArr.pop();
} else if (index == 10) {
this.sendSa();
numberArr.push(0);
smsArr.splice(numberArr.length - 1, 1, 0);
} else {
this.sendSa();
numberArr.push(index + 1);
smsArr.splice(numberArr.length - 1, 1, index + 1);
}
this.numberArr = numberArr;
this.smsArr = smsArr;
this.getsms();
},
getsms: function() {
//判断并取出密码
if (this.numberArr.length === this.smsArr.length) {
this.$emit("submit", this.numberArr.join(""));
}
},
sendSms(val) {
// 页面摧毁清掉定时器
if (this.send) return;
if (!val) {
saTrackEvent("PD_YXMMACP_UserClickResendCaptcha");
uni.reportAnalytics("c_resendcaptcha", {});
}
saTrackEvent("");
this.$emit("send", () => {
this.send = true;
this.timer = setInterval(() => {
--this.time;
if (!this.time) {
this.clearTimer();
}
}, 1000);
});
},
getPhone() {
const phone = uni.getStorageSync("phone");
const phoneS = phone.replace(/(\d{3})\d*(\d{4})/, "+86 $1 **** $2");
return phoneS;
},
sendSa() {
if (!this.numberArr.length && !this.isDel) {
saTrackEvent("PD_YXMMACP_UserClickAgainVerificationCodeInputbox");
uni.reportAnalytics("c_againverificationcodeinputbox", {});
}
},
clearTimer() {
clearInterval(this.timer);
this.send = false;
this.time = 60;
}
}
};
</script>
<style lang="scss">
.sms {
&-title {
display: flex;
justify-content: flex-start;
font-size: 24rpx;
color: #999999;
}
.phone {
margin-top: 16rpx;
color: #323233;
font-size: 28rpx;
}
&-sms {
margin-top: 4px;
font-size: 60rpx;
color: #333333;
&:before {
content: "¥";
font-size: $uni-font-size-sm;
}
}
&-input {
margin-top: 16px;
}
}
.sms-action {
width: 100%;
display: flex;
justify-content: space-between;
text {
font-size: 28rpx;
color: #666666;
}
.sms-error {
flex: 1;
color: #ee0a24;
}
.sms-set {
flex: 1;
text-align: right;
}
.grey {
color: #999999;
}
}
</style>
<template>
<uni-popup ref="subscribeDialog" type="dialog">
<uni-popup-dialog
:subscribe-message="true"
type="input"
:show-title="false"
content="非常感谢亲对羊小咩的关注,您可以关注【羊小咩 信用钱包】公众号获取最新的活动资讯,点击【订阅消息】即可哦~"
message=""
:duration="2000"
:before-close="true"
confirm-txt="订阅消息"
@confirm="authSubscribe"
@cancel="bundleCancelClick"
/>
</uni-popup>
</template>
<script>
import uniPopup from "@/components/uni-popup/uni-popup";
import uniPopupDialog from "@/components/uni-popup/uni-popup-dialog";
import { getVaildSubTmplIds, subscribe } from "@/api/home.api";
import { saTrackEvent } from "@/utils/sa.js";
import { getVaildTmplIds, submitSubcribeInfo, getAcceptList } from "@/utils/subscribe";
import config from "@/config";
const tmplIds = [
config.SUB_MSG_LIST.GROUP_BUY_REFUND,
config.SUB_MSG_LIST.GROUP_SUCCESS,
config.SUB_MSG_LIST.ACTIVITY_START
]; // 需要变更为消息通知
let vaildTmplIds = [];
export default {
name: "ActionSheet",
components: {
uniPopup,
uniPopupDialog
},
async created() {
// #ifdef MP-WEIXIN
this.getVaildSubTpl();
// #endif
},
methods: {
/**
* @exposed-api
*/
open() {
// 非羊小咩不触发订阅消息
if (this.$config("yxm")) this.$refs.subscribeDialog.open();
},
/**
* @exposed-api
*/
close() {
this.$refs.subscribeDialog.close();
},
authSubscribe() {
// 非羊小咩不触发订阅消息
if (this.$config("yxm")) {
wx.requestSubscribeMessage({
tmplIds: vaildTmplIds,
success: async res => {
console.log(res);
await subscribe({
enable: 1
});
this.submitInfo(res);
const vaildTmplIds = getVaildTmplIds(res);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "登录成功后(百人团)",
check_content: vaildTmplIds,
buttons_name: "允许"
});
this.$emit("confirm");
this.$refs.subscribeDialog.close();
},
fail: err => {
console.error("requestSubscribeMessage", err);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "登录成功后(百人团)",
check_content: "退款通知,拼团成功提醒,活动开始提醒",
buttons_name: "取消"
});
this.$emit("confirm");
this.$refs.subscribeDialog.close();
}
});
} else {
this.$emit("confirm");
this.$refs.subscribeDialog.close();
}
},
submitInfo(res) {
const acceptList = getAcceptList(res);
submitSubcribeInfo(acceptList);
},
bundleCancelClick() {
this.$emit("cancel");
},
async getVaildSubTpl() {
vaildTmplIds = await getVaildSubTmplIds(tmplIds);
}
}
};
</script>
<template name="tougdun">
<view>
<canvas canvas-id="tdcanvas" style="visibility: hidden;position: fixed;z-index: -999;" />
</view>
</template>
<template>
<view
class="tui-modal__container"
:class="[show ? 'tui-modal-show' : '']"
:style="{ zIndex: zIndex }"
@touchmove.stop.prevent
>
<view
class="tui-modal-box"
:style="{
width: width,
padding: padding,
borderRadius: radius,
backgroundColor: backgroundColor,
zIndex: zIndex + 1
}"
:class="[
fadeIn || show ? 'tui-modal-normal' : 'tui-modal-scale',
show ? 'tui-modal-show' : ''
]"
>
<view v-if="!custom">
<image
src="https://img.lkbang.net/xcx/close.png"
class="close-icon"
@click="handleClickCancel"
/>
<view v-if="title" class="tui-modal-title">{{ title }}</view>
<view
class="tui-modal-content"
:class="[title ? '' : 'tui-mtop']"
:style="{ color: color, fontSize: size + 'rpx' }"
><slot
/></view>
<view class="tui-modalBtn-box" :class="[button.length != 2 ? 'tui-flex-column' : '']">
<slot name="footer">
<block v-for="(item, index) in button" :key="index">
<button
class="tui-modal-btn"
:class="[
'tui-' + (item.type || 'primary') + (item.plain ? '-outline' : ''),
button.length != 2 ? 'tui-btn-width' : '',
button.length > 2 ? 'tui-mbtm' : '',
shape == 'circle' ? 'tui-circle-btn' : ''
]"
:hover-class="'tui-' + (item.plain ? 'outline' : item.type || 'primary') + '-hover'"
:data-index="index"
@tap="handleClick"
>
{{ item.text || "确定" }}
</button>
</block>
</slot>
</view>
</view>
<view v-else><slot /></view>
</view>
<view
class="tui-modal-mask"
:class="[show ? 'tui-mask-show' : '']"
:style="{ zIndex: maskZIndex }"
@tap="handleClickCancel"
/>
</view>
</template>
<script>
export default {
name: "TuiModal",
props: {
//是否显示
show: {
type: Boolean,
default: false
},
width: {
type: String,
default: "90%"
},
backgroundColor: {
type: String,
default: "#fff"
},
padding: {
type: String,
default: "40rpx 64rpx"
},
radius: {
type: String,
default: "24rpx"
},
//标题
title: {
type: String,
default: ""
},
//内容
content: {
type: String,
default: ""
},
//内容字体颜色
color: {
type: String,
default: "#999"
},
//内容字体大小 rpx
size: {
type: Number,
default: 28
},
//形状 circle, square
shape: {
type: String,
default: "square"
},
button: {
type: Array,
default: function() {
return [
{
text: "取消",
type: "red",
plain: true //是否空心
},
{
text: "确定",
type: "red",
plain: false
}
];
}
},
//点击遮罩 是否可关闭
maskClosable: {
type: Boolean,
default: true
},
//淡入效果,自定义弹框插入input输入框时传true
fadeIn: {
type: Boolean,
default: false
},
//自定义弹窗内容
custom: {
type: Boolean,
default: false
},
//容器z-index
zIndex: {
type: Number,
default: 9997
},
//mask z-index
maskZIndex: {
type: Number,
default: 9990
}
},
data() {
return {};
},
methods: {
handleClick(e) {
if (!this.show) return;
const dataset = e.currentTarget.dataset;
this.$emit("click", {
index: Number(dataset.index)
});
},
handleClickCancel() {
if (!this.maskClosable) return;
this.$emit("cancel");
}
}
};
</script>
<style scoped>
.tui-modal__container {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
visibility: hidden;
}
.tui-modal-box {
position: relative;
opacity: 0;
visibility: hidden;
box-sizing: border-box;
transition: all 0.3s ease-in-out;
margin-bottom: 200rpx;
}
.close-icon {
width: 30rpx;
height: 30rpx;
position: absolute;
right: 40rpx;
top: 40rpx;
}
.tui-modal-scale {
transform: scale(0);
}
.tui-modal-normal {
transform: scale(1);
}
.tui-modal-show {
opacity: 1;
visibility: visible;
}
.tui-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
transition: all 0.3s ease-in-out;
opacity: 0;
visibility: hidden;
}
.tui-mask-show {
visibility: visible;
opacity: 1;
}
.tui-modal-title {
text-align: center;
font-size: 32rpx;
color: #333;
padding-top: 20rpx;
font-weight: bold;
}
.tui-modal-content {
text-align: center;
color: #999;
font-size: 28rpx;
padding-top: 24rpx;
padding-bottom: 24rpx;
}
.tui-mtop {
margin-top: 30rpx;
}
.tui-mbtm {
margin-bottom: 30rpx;
}
.tui-modalBtn-box {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.tui-flex-column {
flex-direction: column;
}
.tui-modal-btn {
width: 46%;
height: 68rpx;
line-height: 68rpx;
position: relative;
border-radius: 10rpx;
font-size: 26rpx;
overflow: visible;
margin-left: 0;
margin-right: 0;
}
.tui-modal-btn::after {
content: " ";
position: absolute;
width: 200%;
height: 200%;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
transform: scale(0.5, 0.5) translateZ(0);
left: 0;
top: 0;
border-radius: 20rpx;
z-index: 2;
}
.tui-btn-width {
width: 80% !important;
}
.tui-primary {
background: #5677fc;
color: #fff;
}
.tui-primary-hover {
background: #4a67d6;
color: #e5e5e5;
}
.tui-primary-outline {
color: #5677fc;
background: transparent;
}
.tui-primary-outline::after {
border: 1px solid #5677fc;
}
.tui-danger {
background: #ed3f14;
color: #fff;
}
.tui-danger-hover {
background: #d53912;
color: #e5e5e5;
}
.tui-danger-outline {
color: #ed3f14;
background: transparent;
}
.tui-danger-outline::after {
border: 1px solid #ed3f14;
}
.tui-red {
background: #e41f19;
color: #fff;
}
.tui-red-hover {
background: #c51a15;
color: #e5e5e5;
}
.tui-red-outline {
color: #e41f19;
background: transparent;
}
.tui-red-outline::after {
border: 1px solid #e41f19;
}
.tui-warning {
background: #ff7900;
color: #fff;
}
.tui-warning-hover {
background: #e56d00;
color: #e5e5e5;
}
.tui-warning-outline {
color: #ff7900;
background: transparent;
}
.tui-warning-outline::after {
border: 1px solid #ff7900;
}
.tui-green {
background: #19be6b;
color: #fff;
}
.tui-green-hover {
background: #16ab60;
color: #e5e5e5;
}
.tui-green-outline {
color: #19be6b;
background: transparent;
}
.tui-green-outline::after {
border: 1px solid #19be6b;
}
.tui-white {
background: #fff;
color: #333;
}
.tui-white-hover {
background: #f7f7f9;
color: #666;
}
.tui-white-outline {
color: #333;
background: transparent;
}
.tui-white-outline::after {
border: 1px solid #333;
}
.tui-gray {
background: #ededed;
color: #999;
}
.tui-gray-hover {
background: #d5d5d5;
color: #898989;
}
.tui-gray-outline {
color: #999;
background: transparent;
}
.tui-gray-outline::after {
border: 1px solid #999;
}
.tui-outline-hover {
opacity: 0.6;
}
.tui-circle-btn {
border-radius: 40rpx !important;
}
.tui-circle-btn::after {
border-radius: 80rpx !important;
}
</style>
<template>
<view class="upload-content">
<block v-for="(item, index) in imageList" :key="index">
<view class="upload-item">
<image
class="upload-img"
:src="item.filePath"
mode="aspectFill"
@click="previewImage(index)"
/>
<image
class="upload-del-btn"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAmCAYAAACoPemuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjNBODgzQjUwNDM5MTFFOUJDMjlGN0UwRTJGMjVCNjQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjNBODgzQjYwNDM5MTFFOUJDMjlGN0UwRTJGMjVCNjQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGM0E4ODNCMzA0MzkxMUU5QkMyOUY3RTBFMkYyNUI2NCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGM0E4ODNCNDA0MzkxMUU5QkMyOUY3RTBFMkYyNUI2NCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuYQTIAAAAHNSURBVHjazJgxasMwFIbjnsD4BDmCLxDQDZrNQ5bcILlBvXvpDRLIWmiHFkyH2t0LyVbwEkPpbE/eYlUCGYQax096UuIffkIgij7ryU/vyZuYy2e+Z56K70R8lsJcOfPn5AriMCvmZ2YKdMW8EQ/hRA9iEorwXlpZtObMRySQ6kysvrFWloHUEIcmUBuHUDLccmxQskErt7wyVLdy00tQ4Q2g5De2V9kNwWjffiNDA33f/42i6E13Qj5uNptlwJD+SyODuaqqqi/KVBTFOxSKA7VtW/NxSZI8AcbE2nuraZpvKgSBk6G4drsdBOwogz1CwAghH/JEl+BUKJ1VltPHHjoIAoeE4l53YFqb+RKcBSgqyqXhtxEKZwkKB3YOThYCqjPuCDoHZwGK3mGLtdPp5LmqTI1Dqe4p26EkNqA4iE6eg2z+iQ0okyQMATvYgLIIt9Y6knTyFBIudHqIq3BpmkL60VJ9O0sXZY8MBwSLtdNGEAQ/i8XiVXcz83EcEPDbuq/fzMdYWt+6GTmMsX2rh9q3TtsxNrzXhKt1rwg6rR1Dhdjqo7QMlWOvoWTF4imxQMRF7eaL8L5ohmwrLgDB8pCQc8DlcG7y538CDABJNGPqfaJgfgAAAABJRU5ErkJggg=="
mode="scaleToFill"
@click="delImage(index)"
/>
<view v-if="item.progress < 100" class="upload-progress">{{ item.progress }}%</view>
</view>
</block>
<view v-if="rduLength > 0" class="upload-add-btn" @click="chooseImage" />
</view>
</template>
<script>
export default {
props: {
url: {
type: String,
value: "" //上传接口地址
},
count: {
type: Number,
value: 4 //单次可选择的图片数量
},
length: {
type: Number,
value: 50 //可上传总数量
}
},
data() {
return {
imageList: []
};
},
computed: {
rduLength() {
return this.length - this.imageList.length;
}
},
methods: {
//选择图片
chooseImage: function() {
uni.chooseImage({
count: this.rduLength < this.count ? this.rduLength : this.count, //最多可以选择的图片张数,默认9
sizeType: ["original", "compressed"], //original 原图,compressed 压缩图,默认二者都有
sourceType: ["album"], //album 从相册选图,camera 使用相机,默认二者都有
success: res => {
const images = res.tempFilePaths;
this.uploadFiles(images);
}
});
},
//上传图片
async uploadFiles(images) {
this.imageList.push({
filePath: images[0],
progress: 0
});
uni.showLoading({
title: "请稍后..",
/* #ifdef MP-WEIXIN */
mask: true
/* #endif */
});
let uploadUrl;
try {
uploadUrl = await this.uploadImage(images[0]);
} catch (err) {
console.log(err);
return;
}
if (uploadUrl !== false) {
images.splice(0, 1);
this.imageList[this.imageList.length - 1].src = uploadUrl;
//判断是否需要继续上传
if (images.length > 0 && this.rduLength > 0) {
this.uploadFiles(images);
} else {
uni.hideLoading();
}
} else {
//上传失败处理
this.imageList.pop();
uni.hideLoading();
uni.showToast({
title: "上传中出现问题,已终止上传",
icon: "none",
mask: true,
duration: 2000
});
}
},
uploadImage: function(file) {
return new Promise((resolve, reject) => {
//发送给后端的附加参数
const formData = {
thumb_mode: 1
};
this.uploadTask = uni.uploadFile({
url: this.url,
filePath: file,
name: "file",
formData: formData,
success(uploadFileResult) {
const uploadFileRes = JSON.parse(uploadFileResult.data) || {};
if (uploadFileRes.status === 1 && uploadFileRes.data) {
resolve(uploadFileRes.data);
} else {
reject("接口返回错误");
}
},
fail() {
reject("网络链接错误");
}
});
//上传进度
this.uploadTask.onProgressUpdate(progressRes => {
this.imageList[this.imageList.length - 1].progress = progressRes.progress;
});
});
},
//删除图片
delImage: function(index) {
uni.showModal({
content: "确定要放弃这张图片么?",
success: confirmRes => {
if (confirmRes.confirm) {
this.imageList.splice(index, 1);
}
}
});
},
//预览图片
previewImage: function(index) {
const urls = [];
this.imageList.forEach(item => {
urls.push(item.filePath);
});
uni.previewImage({
current: urls[index],
urls: urls,
indicator: "number"
});
}
}
};
</script>
<style lang="scss">
.upload-content {
padding: 24rpx 0 0 28rpx;
background-color: #fff;
overflow: hidden;
}
.upload-item {
position: relative;
float: left;
width: 150rpx;
height: 150rpx;
margin-right: 30rpx;
margin-bottom: 30rpx;
&:nth-child(4n) {
margin-right: 0;
}
.upload-img {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
.upload-del-btn {
position: absolute;
right: -16rpx;
top: -14rpx;
width: 36rpx;
height: 36rpx;
border: 4rpx solid #fff;
border-radius: 100px;
}
.upload-progress {
position: absolute;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
color: #fff;
font-size: 24rpx;
border-radius: 8rpx;
}
}
.upload-add-btn {
position: relative;
float: left;
width: 150rpx;
height: 150rpx;
z-index: 99;
border-radius: 8rpx;
background: #f9f9f9;
&:before,
&:after {
content: " ";
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
width: 4rpx;
height: 60rpx;
background-color: #d6d6d6;
}
&:after {
width: 60rpx;
height: 4rpx;
}
&:active {
background-color: #f7f7f7;
}
}
</style>
<template>
<uni-popup ref="auth-popup" type="dialog" title="提示">
<view class="auth-info">
<view class="auth-info__tip">
为了提供更好的服务,我们需要获取您的头像、昵称等个人信息
</view>
<button v-if="canIUseGetUserProfile" class="auth-info__agree" @click="getUserInfo">
一键授权
</button>
<button v-else class="auth-info__agree" open-type="getUserInfo" @getuserinfo="handleUserInfo">
一键授权
</button>
<view
class="auth-info__cancel"
@click="
close();
$emit('get-user-close');
"
>暂不需要</view
>
</view>
</uni-popup>
</template>
<script>
import uniPopup from "@/components/uni-popup/uni-popup";
export default {
name: "UserInfoPopup",
components: {
uniPopup
},
data() {
return {
canIUseGetUserProfile: false
};
},
watch: {
value: {
immediate: true,
handler(val) {
this.$nextTick(() => {
val ? this.open() : this.close();
});
}
}
},
created() {
// this.checkUserInfoState();
if (wx.canIUse("getUserProfile")) {
this.canIUseGetUserProfile = true;
}
},
methods: {
checkUserInfoState() {
const vm = this;
wx.getSetting({
success(res) {
const state = res.authSetting["scope.userInfo"];
vm.$emit("auth-state", state);
if (state) {
vm.getUserInfo();
}
}
});
},
getUserInfo() {
const vm = this;
const localUserInfo = uni.getStorageSync("userBaseInfo");
if (localUserInfo && localUserInfo.nickName) {
vm.setUserInfo(localUserInfo);
return;
}
if (this.canIUseGetUserProfile) {
wx.getUserProfile({
desc: "获取您的头像、昵称等个人信息",
success(res) {
vm.setUserInfo(res.userInfo);
vm.close();
},
fail(e) {
console.error("error", e);
}
});
return;
}
wx.getUserInfo({
success(res) {
console.log("getUserInfo-success", res);
vm.setUserInfo(res.userInfo);
vm.close();
},
fail() {
console.log("getUserInfo-false");
console.error("获取用户信息失败!");
}
});
},
open() {
this.$refs["auth-popup"].open();
},
close() {
this.$refs["auth-popup"].close();
},
handleUserInfo(e) {
this.setUserInfo(e.detail.userInfo);
this.close();
},
setUserInfo(data) {
console.log(data.nickName);
if (data.nickName === "微信用户") {
data.nickName = "点击登录/注册";
}
this.$emit("get-user-info", data);
uni.setStorageSync("userBaseInfo", data);
}
}
};
</script>
<style lang="scss" scoped>
.auth-info {
width: 622rpx;
padding: 0 40rpx;
&__tip {
color: #666;
font-size: 28rpx;
line-height: 40rpx;
text-align: center;
padding: 24rpx 0 48rpx;
}
&__agree {
background: linear-gradient(270deg, #ff5d00 0%, #ff1900 100%);
height: 72rpx;
border-radius: 36rpx;
color: #fff;
font-size: 28rpx;
line-height: 72rpx;
}
&__cancel {
font-size: 28rpx;
color: #ec1500;
line-height: 40rpx;
text-align: center;
padding: 24rpx 0 36rpx;
}
}
</style>
const APPID_MAP = {
wxe16bf9293671506c: {
tenantId: 560761,
tenantName: "羊小咩",
name: "狼大呜",
setting: "yxm" // 页面配置文件
},
wxb3e6270e1b1e0bc7: {
tenantId: 560761,
tenantName: "羊小咩",
name: "羊小咩plus",
setting: "yxm" // 页面配置文件
},
wxccb8435d68e8c7d6: {
tenantId: 560867,
tenantName: "青海移动",
name: "狗大旺",
setting: "qinghai", // 页面配置文件
vccChannel: "560867002"
},
wxbd0bc68b270a1dab: {
tenantId: 560867,
tenantName: "青海移动",
name: "花一得二优选",
setting: "qinghai", // 页面配置文件
vccChannel: "560867002"
},
/************************************************/
/*****************支付宝小程序*********************/
2021003126632272: {
tenantId: 560761,
tenantName: "羊小咩",
name: "狼大呜",
setting: "yxm" // 页面配置文件
},
/************************************************/
/************************************************/
/************************************************/
/*******************百度小程序*********************/
// 25998612
S7hLi03Uwui21ydfpDtDFaGLaEZWVAXe: {
tenantId: 560761,
tenantName: "羊小咩",
name: "狼大呜",
setting: "yxm" // 页面配置文件
}
/************************************************/
/************************************************/
};
export default APPID_MAP;
{"mp":"mp-weixin","yxm":true,"tenantId":560761,"tenantName":"羊小咩","appName":"狼大呜","defaultTitle":"羊小咩","logoImg":"https://img.lkbang.net/xcx/login-logo2.png","yinSiUrl":"https://appsync.lkbang.net/agreement-three.html?contractTemplateId=434","yinSiText":"羊小咩用户隐私协议","zhuCeUrl":"https://appsync.lkbang.net/agreement-three.html?contractTemplateId=433","zhuCeText":"羊小咩注册协议","tuiJianUrl":"https://mall-qa.liangkebang.net/recommend?vccToken={token}","tuiJianText":"个性化推荐管理","similarList":true,"order":{"cancel":true,"refund":true,"afterSale":true},"virtualMsg":"请选择现金券支付!","templateList":{"SELLER_SHIP":"1JhEINnMkdCLfEKkBu_g4kBYBwZ5ttdc8wJCHM3rptQ","ORDER_RECEIPT":"yuTVWlf5mfMJ1OdVepV4lNGNlC0ODsuPRKznTQxPUIY","COUPON_RECEIPT":"7O1W4EdNo1CDe7xLCzV7bzzqX57RCjZoibUkwWHx-BE","GROUP_BUY_REFUND":"BsS1di1gz_fxCrXYYPjQSw9juezCEhklyuJFwrr81EA","GROUP_SUCCESS":"jjQDF-xjFGWif1ePik6NsTnHHLYERMvCUjvgUWhZ2iM","ACTIVITY_START":"YCLxz0TtrymAOOW74pIEht5dMLBlyI84dHgu-RdVjVw","PAY_SUCCESS":"mqriYSvLJO-4QLrQi4h7A00VXp16i1Uyr_1bmkA7POo","RESULT_NOTICE":"GfvGAKzYBotsosAmGF90g_qndPPg_s8X7y31raPDUu4","RECEIPT_OPEN_SUCCESS":"zx4AIHgLWV4Ge-ssmrbMsqpj9Ijha7fQREeX5J48lVc"}}
\ No newline at end of file
import { TERMINAL, VCC_CHANNEL } from "@/utils/mpConfig/types";
const envName = "yxm";
const shenceUrl = "https://bn.xyqb.com/sa?project=default";
const talosApi = `https://talos-${envName}.liangkebang.net`;
// const yxmGateway = `https://yxm-gateway-${envName}.liangkebang.net`;
const yxmGateway = `https://gw-${envName}.liangkebang.net`;
const kdspApi = `https://kdsp-api-${envName}.liangkebang.net`;
// const kdspHost = `https://yxm-gateway-${envName}.liangkebang.net`;
const kdspHost = `https://kdsp-talos-${envName}.liangkebang.net`;
const vccHost = `https://vcc-spider-${envName}.liangkebang.net/face-finished?h=0&vccToken=`;
const groupBuyHost = `https:https://group-buy-${envName}.liangkebang.net`;
const VCC_URL = `https://vcc-${envName}.liangkebang.net`;
const MALL_URL = `https://xincheng-${envName}.liangkebang.net`;
// const MALL_URL = `http://192.168.1.108:8081`;
const SHARE_CHANNEL = "159960"; //! 从分享、二维码进入小程序并下单时使用此渠道号
const VERSION = "7.7.01";
const env = "test";
const SUB_MSG_LIST = {
SELLER_SHIP: "1JhEINnMkdCLfEKkBu_g4kBYBwZ5ttdc8wJCHM3rptQ", // 商家发货通知
ORDER_RECEIPT: "yuTVWlf5mfMJ1OdVepV4lNGNlC0ODsuPRKznTQxPUIY", // 订单签收通知
COUPON_RECEIPT: "7O1W4EdNo1CDe7xLCzV7bzzqX57RCjZoibUkwWHx-BE", // 优惠券到账通知
// 以下是新增的团购消息模板
GROUP_BUY_REFUND: "BsS1di1gz_fxCrXYYPjQSw9juezCEhklyuJFwrr81EA", // 退款通知
GROUP_SUCCESS: "jjQDF-xjFGWif1ePik6NsTnHHLYERMvCUjvgUWhZ2iM", // 拼团成功
ACTIVITY_START: "YCLxz0TtrymAOOW74pIEht5dMLBlyI84dHgu-RdVjVw", // 活动开始提醒
// 新增订阅节点
PAY_SUCCESS: "mqriYSvLJO-4QLrQi4h7A00VXp16i1Uyr_1bmkA7POo", //支付成功
RESULT_NOTICE: "GfvGAKzYBotsosAmGF90g_qndPPg_s8X7y31raPDUu4", //审核结果通知
RECEIPT_OPEN_SUCCESS: "zx4AIHgLWV4Ge-ssmrbMsqpj9Ijha7fQREeX5J48lVc", // 发票开具成功提醒
// NEWPRODUCT_NOTICE: "36c1LKstbzyrC1W1mknnnRtNq7_AffQf0-vOMrWANiU" // 新品上架通知
// 新增
RECEIVE_COUPON: "MrOElIkBsGY5oBH9AzArM7t73h8Tw0YbBFuIcXd0c1w", // 优惠券领取提醒
ACTIVITY_OPEN: "K1er4dN_rmaAZoqMNFHGs5LOTT5hu2ejfvi-mU9wvoU", // 活动开始提醒
SPECIAL_PRODUCT: "cTNqo4EMyZ59JLt00pkWI2AAyUnSqYPcbbmDXln2mCc" // 特价商品提醒
};
const tmplIdsList = {
SELLER_SHIP: "商家发货通知",
ORDER_RECEIPT: "订单签收通知",
COUPON_RECEIPT: "优惠券到账通知",
// 以下是新增的团购消息模板
GROUP_BUY_REFUND: "退款通知",
GROUP_SUCCESS: "拼团成功",
ACTIVITY_START: "活动开始提醒",
// 新增订阅节点
PAY_SUCCESS: "支付成功",
RESULT_NOTICE: "审核结果通知",
RECEIPT_OPEN_SUCCESS: "发票开具成功提醒",
// 新增
RECEIVE_COUPON: "优惠券领取提醒",
ACTIVITY_OPEN: "活动开始提醒",
SPECIAL_PRODUCT: "特价商品提醒"
};
const REYUN_APP_KEY = "68a35d6d6e48de2c1cf8a9bb15215a71";
const SMAPPID = "YXM_TEST";
// const tdApiHost = "https://yxm-gateway-yxm.liangkebang.net";
// let tdApiHost = "https://talos-yxm.liangkebang.net"; // 同盾上报服务
// /* #ifndef MP-WEIXIN */
// tdApiHost = "https://yxm-gateway-yxm.liangkebang.net";
// /* #endif */
export default {
shenceUrl,
env,
talosApi,
kdspApi,
vccHost,
groupBuyHost,
VCC_CHANNEL,
SHARE_CHANNEL,
TERMINAL,
VERSION,
VCC_URL,
SUB_MSG_LIST,
MALL_URL,
REYUN_APP_KEY,
tmplIdsList,
kdspHost,
// tdApiHost,
yxmGateway,
SMAPPID
};
import config from "./index";
import { saDeviceId } from "@/utils/sa";
import { getAppId } from "@/utils/index";
const invalidValueMap = [
"undefined",
"null",
"0",
"{registerFrom}",
"{vccChannel}",
"{sonVccChannel}",
" "
];
// vccChannel处理
function getVccChannel(channel) {
if (channel) return channel;
let vccChannel = uni.getStorageSync("vccChannel");
if (!vccChannel || invalidValueMap.includes(vccChannel)) {
vccChannel = config.VCC_CHANNEL;
uni.setStorageSync("vccChannel", config.VCC_CHANNEL);
}
return vccChannel;
}
export default {
service: {
response(response) {
const { res, options } = response;
const data = res.data;
const success =
(data.code === 0 && data.business_code === 0) ||
(data.code === "0000" && data.businessCode === "0000");
// 业务完成,返回有效载荷
if (success) {
return [data.data, null];
}
if (data.businessCode === "401") {
const token = uni.getStorageSync("token");
token && uni.removeStorageSync("token");
uni.navigateTo({
url: `/pages/user/login`
});
}
// 接下来处理异常业务
const msg = data.msg || "服务异常";
if (!options.hideToast) {
if (!data.noAlert) {
uni.showToast({ title: msg, icon: "none", duration: 2500 });
}
}
// 给用户提示信息,明确发生错误
// 请求参数和响应数据都可以控制不提示
let error = { msg };
error.response = data;
console.error(error);
return [null, error];
},
request(cfg) {
const {
method,
hideVccChannel,
emulateFormData,
needScDeviceId,
creditToken,
customizeChannel
} = cfg;
if (!cfg.header) cfg.header = {};
// appID
cfg.header["mini-app-id"] = getAppId() || "";
// 租户ID
cfg.header["qg-tenant-id"] = uni.getStorageSync("tenantId") || 560761;
cfg.header["X-Auth-Token"] = uni.getStorageSync("token") || "";
cfg.header["x-user-terminal"] = config.TERMINAL;
if (!cfg.header["version"]) {
cfg.header["version"] = config.VERSION;
}
// 使用creditToken
if (creditToken) {
cfg.header["X-Auth-Token"] = uni.getStorageSync("creditToken");
}
// 添加神策deviceid
if (needScDeviceId) {
// const saInfo = uni.getStorageSync("sensorsdata2015_wechat") || {};
// const saDeviceId = saInfo.anonymous_id || "";
cfg.header["scDeviceId"] = saDeviceId;
}
// 隐藏VccChannel
if (!hideVccChannel) {
cfg.header["vccChannel"] = getVccChannel(customizeChannel);
}
// 添加sonVccChannel
// if (sonVccChannel) {
cfg.header["sonVccChannel"] = uni.getStorageSync("sonVccChannel") || "";
// }
// 改为formData
if (method.toLocaleLowerCase() === "post" && emulateFormData) {
cfg.header["Content-Type"] = "application/x-www-form-urlencoded";
}
return cfg;
}
}
};
import { TERMINAL, VCC_CHANNEL } from "@/utils/mpConfig/types";
const protocol = "https:";
const shenceUrl = protocol + "//bn.xyqb.com/sa?project=production";
const talosApi = protocol + "//talos-pre.xyqb.com";
const kdspApi = protocol + "//kdsp-api-pre.xyqb.com";
const vccHost = protocol + "//vcc-spider-pre.xyqb.com/face-finished?h=0&vccToken=";
const groupBuyHost = protocol + "//group-buy-pre.q-gp.com";
const yxmGateway = "https://gw.yxmie.com";
const VCC_URL = protocol + "//vcc-pre.xyqb.com";
const MALL_URL = protocol + "//saas.91xr.cn";
const SHARE_CHANNEL = "159960"; //! 从分享、二维码进入小程序并下单时使用此渠道号
const VERSION = "7.7.01";
const env = "prod";
const SUB_MSG_LIST = {
SELLER_SHIP: "_RJyydfzZXkL-Js8oOe592SS6MwDqgl01V60l6Ky-vg", // 商家发货通知
ORDER_RECEIPT: "7FD59HKMBa6y8AP61N9I-ui4Pm7EWy401_Ar_9hlpAw", // 订单签收通知
COUPON_RECEIPT: "6WP-LpbuJ_guHZsdU6nAnIDyf1h6VG5B66FWZPsZW18", // 优惠券到账通知
// 以下是新增的团购消息模板
GROUP_BUY_REFUND: "oF9UpxhnhRTWwmLTODHfXNou8uYZoB6tNRFLsYcdO10", // 退款通知
GROUP_SUCCESS: "vvsh-X1hqHOYvvKd-xE3YAXHt_62_he59iM-6n1Y91s", // 拼团成功
ACTIVITY_START: "eAx92dW4gcm-ZKnm9r_faz3ADopCvq65H5Zm6e615ZU", // 活动开始提醒
// 新增订阅节点
PAY_SUCCESS: "4tO9I3tRhIidvRd-E1i8Nh_r4ykz_NFWCSBP0oV_C8o", //支付成功
RESULT_NOTICE: "I3gcq3_jxn0Jvin_tnhwtVgRhzU2Q9cjqwBbejGMcJI", //审核结果通知
RECEIPT_OPEN_SUCCESS: "k9zsVBbSEmfBPcjN3TxcpDg_sesLnOm9zqROERicOJU" // 发票开具成功提醒
// NEWPRODUCT_NOTICE: "w-nI_Ycw2G36GfLBa0qe-11YAy3mpHNb79X_FwK-U8Y" // 新品上架通知
};
const REYUN_APP_KEY = "68a35d6d6e48de2c1cf8a9bb15215a71";
const SMAPPID = "YXM";
// const tdApiHost = "https://gw.yxmie.com";
// let tdApiHost = "https://talos.xyqb.com"; // 同盾上报服务
// /* #ifndef MP-WEIXIN */
// tdApiHost = "https://yxm-gateway.xyqb.com";
// /* #endif */
export default {
shenceUrl,
env,
talosApi,
kdspApi,
vccHost,
groupBuyHost,
VCC_CHANNEL,
SHARE_CHANNEL,
TERMINAL,
VERSION,
VCC_URL,
SUB_MSG_LIST,
MALL_URL,
REYUN_APP_KEY,
yxmGateway,
SMAPPID
// tdApiHost
};
import { TERMINAL, VCC_CHANNEL } from "@/utils/mpConfig/types";
const protocol = "https:";
const shenceUrl = protocol + "//bn.xyqb.com/sa?project=production";
const talosApi = protocol + "//talos.xyqb.com";
const kdspApi = protocol + "//kdsp-api.xyqb.com";
const vccHost = protocol + "//vcc-spider.xyqb.com/face-finished?h=0&vccToken=";
const groupBuyHost = protocol + "//group-buy.q-gp.com";
const yxmGateway = "https://gw.yxmie.com";
const VCC_URL = protocol + "//vcc.xyqb.com";
const MALL_URL = protocol + "//saas.91xr.cn";
const SHARE_CHANNEL = "159960"; //! 从分享、二维码进入小程序并下单时使用此渠道号
const VERSION = "7.7.01";
const env = "prod";
const SUB_MSG_LIST = {
SELLER_SHIP: "_RJyydfzZXkL-Js8oOe592SS6MwDqgl01V60l6Ky-vg", // 商家发货通知
ORDER_RECEIPT: "7FD59HKMBa6y8AP61N9I-ui4Pm7EWy401_Ar_9hlpAw", // 订单签收通知
COUPON_RECEIPT: "6WP-LpbuJ_guHZsdU6nAnIDyf1h6VG5B66FWZPsZW18", // 优惠券到账通知
// 以下是新增的团购消息模板
GROUP_BUY_REFUND: "oF9UpxhnhRTWwmLTODHfXNou8uYZoB6tNRFLsYcdO10", // 退款通知
GROUP_SUCCESS: "vvsh-X1hqHOYvvKd-xE3YAXHt_62_he59iM-6n1Y91s", // 拼团成功
ACTIVITY_START: "eAx92dW4gcm-ZKnm9r_faz3ADopCvq65H5Zm6e615ZU", // 活动开始提醒
// 新增订阅节点
PAY_SUCCESS: "4tO9I3tRhIidvRd-E1i8Nh_r4ykz_NFWCSBP0oV_C8o", //支付成功
RESULT_NOTICE: "I3gcq3_jxn0Jvin_tnhwtVgRhzU2Q9cjqwBbejGMcJI", //审核结果通知
RECEIPT_OPEN_SUCCESS: "k9zsVBbSEmfBPcjN3TxcpDg_sesLnOm9zqROERicOJU", // 发票开具成功提醒
// NEWPRODUCT_NOTICE: "w-nI_Ycw2G36GfLBa0qe-11YAy3mpHNb79X_FwK-U8Y" // 新品上架通知
// 新增
RECEIVE_COUPON: "hR8yGfIxb3YS8IIqbprydTFPfrhF0cxkfMFFR2F6nAs", // 优惠券领取提醒
ACTIVITY_OPEN: "9rukO-aQbnIDKd2bBEF3uohkoWHbplNWiBrc4ADlfgE", // 活动开始提醒
SPECIAL_PRODUCT: "n_loAZyLRfqNPpYUXZ0ZyilBCrPMnd_MXQxv9ZOd9kI" // 特价商品提醒
};
const tmplIdsList = {
SELLER_SHIP: "商家发货通知",
ORDER_RECEIPT: "订单签收通知",
COUPON_RECEIPT: "优惠券到账通知",
// 以下是新增的团购消息模板
GROUP_BUY_REFUND: "退款通知",
GROUP_SUCCESS: "拼团成功",
ACTIVITY_START: "活动开始提醒",
// 新增订阅节点
PAY_SUCCESS: "支付成功",
RESULT_NOTICE: "审核结果通知",
RECEIPT_OPEN_SUCCESS: "发票开具成功提醒",
// 新增
RECEIVE_COUPON: "优惠券领取提醒",
ACTIVITY_OPEN: "活动开始提醒",
SPECIAL_PRODUCT: "特价商品提醒"
};
const REYUN_APP_KEY = "68a35d6d6e48de2c1cf8a9bb15215a71";
const SMAPPID = "YXM";
// const tdApiHost = "https://gw.yxmie.com";
// let tdApiHost = "https://talos.xyqb.com"; // 同盾上报服务
// /* #ifndef MP-WEIXIN */
// tdApiHost = "https://yxm-gateway.xyqb.com";
/* #endif */
export default {
shenceUrl,
env,
talosApi,
kdspApi,
vccHost,
groupBuyHost,
VCC_CHANNEL,
SHARE_CHANNEL,
TERMINAL,
VERSION,
VCC_URL,
SUB_MSG_LIST,
MALL_URL,
REYUN_APP_KEY,
tmplIdsList,
// tdApiHost,
yxmGateway,
SMAPPID
};
<template>
<div class="item-container">
<div :class="['coupon-item', !isCannot && 'cannot-coupon']">
<div class="coupon-name"><img class="coupon-icon" :src="couponItem.iconUrl" alt="" /></div>
<div class="coupon-content">
<div class="info">
<div class="price-info">
<p class="price"><span class="symbol">¥</span>{{ couponItem.faceValue }}</p>
<span class="tip">{{ couponItem.limitDesc }}</span>
</div>
<div class="text">
<p class="title">{{ couponItem.name }}</p>
<text class="time">
{{ couponItem.couponValidTime || "-" }}
</text>
<p class="details-info-btn" @click="handleDetailsInfo">
详细信息
<text
class="change-info iconfont"
:class="showDetailsInfo ? 'icon-arrow-up' : 'icon-arrow-down'"
/>
</p>
</div>
</div>
<div class="coupon-right">
<button class="btn" type="primary" @click="toUse(couponItem.navUrl)">
{{ couponItem.notEffective === 1 ? "先逛逛" : "立即使用" }}
</button>
<div v-if="couponItem.notEffective === 2" class="overdueText">即将过期</div>
</div>
</div>
<div class="coupon-type">
<img v-if="getCouponTypeImg.length" class="img" :src="getCouponTypeImg" alt="info" />
</div>
</div>
<template v-if="showDetailsInfo">
<div class="bg" />
<div class="details-info">
{{ couponItem.description }}
</div>
</template>
</div>
</template>
<script>
import { jumpToUrl } from "@/mixins/common";
import { parseTime } from "@/utils/index";
const COUPON_IMAGE = {
0: "https://img.lkbang.net/tenant/notEffective.png",
1: "https://img.lkbang.net/tenant/gift-already.png",
2: "https://img.lkbang.net/tenant/gift-overdue.png"
};
export default {
filters: {
dateFormat(val) {
return parseTime(val.split(" ")[0], "{y}.{m}.{d}");
}
},
props: {
couponItem: {
type: Object,
default: () => {}
},
isCannot: {
type: Boolean,
default: true
},
isUse: {
type: Boolean,
default: true
},
currentTab: {
type: Number,
required: true
}
},
data() {
return {
showDetailsInfo: false
};
},
computed: {
getCouponTypeImg() {
const currentTab = this.currentTab;
if (currentTab === 0 && this.couponItem?.notEffective !== 1) {
return "";
}
return COUPON_IMAGE[currentTab];
}
},
methods: {
toUse(url) {
if (this.$config("yxm")) {
// 羊小咩
jumpToUrl(url);
return;
}
// 青海移动逻辑
uni.switchTab({
url: "/pages/index/index"
});
},
handleDetailsInfo() {
this.showDetailsInfo = !this.showDetailsInfo;
}
}
};
</script>
<style lang="scss" scoped>
.item-container {
margin-bottom: 20rpx;
}
.coupon-item {
position: relative;
font-size: 24rpx;
background: #fff;
overflow: hidden;
border-radius: 12rpx;
height: 180rpx;
}
.coupon-name {
position: absolute;
left: 0;
top: 0;
.coupon-icon {
width: 88rpx;
height: 32rpx;
display: block;
}
}
.coupon-type {
position: absolute;
right: 20rpx;
top: -30rpx;
// display: none;
.img {
width: 120rpx;
height: 120rpx;
display: block;
}
}
.coupon-content {
height: 100%;
display: flex;
align-items: center;
box-sizing: border-box;
padding: 0 20rpx 0 25rpx;
justify-content: space-between;
.info {
flex: 1;
display: flex;
align-items: center;
padding-right: 10rpx;
}
.price-info {
width: 140rpx;
margin-right: 34rpx;
text-align: center;
color: #ec3333;
.price {
text-align: center;
font-size: 40rpx;
/* #ifndef MP-ALIPAY */
margin-bottom: 14rpx;
/* #endif */
/* #ifdef MP-ALIPAY */
margin-top: 14rpx;
/* #endif */
font-weight: bold;
}
.symbol {
font-size: 24rpx;
}
}
.text {
.title {
font-size: 28rpx;
color: #333333;
/* margin-bottom: 7px; */
}
.time {
color: #666666;
/* margin-bottom: 7px; */
}
.details-info-btn {
color: #999999;
display: flex;
align-items: center;
}
.change-info {
color: $white;
font-size: 16rpx;
width: 20rpx;
display: inline-block;
line-height: 20rpx;
text-align: center;
margin-left: 10rpx;
background-color: #ccc;
border-radius: 50%;
}
}
}
.bg {
opacity: 0.04;
height: 20rpx;
background-image: linear-gradient(180deg, #000000 26%, rgba(0, 0, 0, 0) 100%);
}
.details-info {
background: #fff;
padding: 20rpx;
margin-top: -16rpx;
font-size: 24rpx;
color: #999999;
box-sizing: border-box;
box-sizing: border-box;
}
.btn {
width: 164rpx;
display: block;
height: 48rpx;
border-radius: 44rpx;
font-size: 24rpx;
line-height: 48rpx;
padding: 0 !important;
background: $background-primary;
z-index: 10;
border: 0;
}
.cannot-coupon {
color: #666666 !important;
.price-info {
color: #666666 !important;
}
.title {
color: #666666 !important;
}
.details-info-btn {
color: #666666 !important;
}
.coupon-type {
display: block;
}
.btn {
display: none;
}
}
.overdueText {
width: 88rpx;
height: 28rpx;
border-radius: 6rpx;
background-color: #fbe7e7;
color: #ee0a24;
font-size: 20rpx;
line-height: 28rpx;
margin-top: 15rpx;
text-align: center;
}
.coupon-right {
display: flex;
flex-direction: column;
align-items: center;
}
</style>
<template>
<view class="module">
<view class="head">
<view class="exchange">
<input
v-model="couponId"
class="exchangeField"
type="text"
placeholder="请输入优惠券券码"
placeholder-style="font-size: 28rpx; color: #c8c9cc"
/>
<div class="input-right">
<div class="clear">
<icon v-if="couponId" type="clear" size="16" @click="clearInput" />
</div>
<text class="iconfont icon-saoyisao right" @click="scanCode" />
</div>
</view>
</view>
<button class="btn" type="primary" @click="exchangeCoupon">兑换</button>
<view class="desc">
<view v-for="(item, index) in descList" :key="index">
<div>{{ item }}</div>
</view>
</view>
<uni-popup ref="scanFail" type="dialog" :mask-click="true">
<uni-popup-dialog
content="您扫描的二维码不正确,请重新扫描"
:show-title="false"
confirm-txt="重新扫码"
:mkclick="true"
hide-cancel-btn
@confirm="reScan"
/>
</uni-popup>
<uni-popup ref="receiveSuccess" type="dialog" :mask-click="true">
<uni-popup-dialog
content="兑换成功,可在“我的优惠券”中查看"
:show-title="false"
:before-close="true"
cancel-txt="继续兑换"
confirm-txt="查看优惠券"
@close="close"
@confirm="confirm"
/>
</uni-popup>
</view>
</template>
<script>
import uniPopup from "@/components/uni-popup/uni-popup";
import uniPopupDialog from "@/components/uni-popup/uni-popup-dialog";
import { exchange, getCouponDesc } from "@/api/coupon.api";
export default {
components: {
uniPopup,
uniPopupDialog
},
data() {
return {
couponId: "",
desc: "",
descList: []
};
},
watch: {
desc: {
deep: true,
immediate: true,
handler: function(val) {
if (val && val.desc) {
this.descList = val.desc.split("\n") || [];
}
}
}
},
onLoad() {
this.getCouponDesc();
},
methods: {
clearInput() {
this.couponId = "";
},
scanCode() {
uni.scanCode({
scanType: "qrCode",
success: res => {
const reg = new RegExp(/^[a-zA-Z0-9]/g);
if (res.result.length > 20 || !reg.test(res.result)) {
this.$refs.scanFail.open();
} else {
this.couponId = res.result || "";
}
},
fail: () => {
this.$refs.scanFail.open();
}
});
},
reScan() {
this.scanCode();
},
async getCouponDesc() {
const [res] = await getCouponDesc();
this.desc = res || "";
},
async exchangeCoupon() {
const params = {
couponCode: this.couponId
};
const [res] = await exchange(params);
if (res) {
this.couponId = "";
this.$refs.receiveSuccess.open();
}
},
close() {
this.$refs.receiveSuccess.close();
},
confirm() {
this.$refs.receiveSuccess.close();
uni.navigateTo({
url: "/pages/coupon/index"
});
}
}
};
</script>
<style lang="scss" scoped>
.module {
background-color: #fff;
height: 100%;
width: 100%;
}
.btn {
width: 670rpx;
display: block;
height: 80rpx;
border-radius: 40rpx;
font-size: 28rpx;
line-height: 80rpx;
padding: 0 !important;
background: $background-primary;
margin: 0 auto 48rpx auto;
border: 0;
}
.desc {
width: 658rpx;
margin: 0 auto;
font-size: 24rpx;
color: #999;
}
.exchange {
width: 670rpx;
height: 80rpx;
border: 1px solid #dcdcdc;
border-radius: 40rpx;
background-color: #f7f8fa;
margin: 0 auto;
margin-bottom: 24rpx;
padding-left: 40rpx;
display: flex;
align-items: center;
}
.exchangeField {
background-color: rgba(255, 255, 255, 0);
}
.head {
padding-top: 56rpx;
}
.input-right {
position: absolute;
width: 116rpx;
right: 84rpx;
display: flex;
align-items: baseline;
}
.clear {
position: relative;
left: 0;
width: 32rpx;
}
.right {
position: relative;
left: 40rpx;
font-size: 40rpx;
}
.title {
margin-bottom: 10px;
}
</style>
<template>
<view class="coupon-list">
<view class="coupon-list__list">
<template v-if="list.length">
<scroll-view :scroll-y="true" class="coupon-list__scroll">
<view
v-for="(info, index) in list"
:key="index"
class="coupon-list__item"
@click="handleSelectCoupon(info.pickupId)"
>
<image :src="info.iconUrl" class="coupon-list__tag" />
<view class="coupon-list__left">
<view class="coupon-list__amount">
<text>{{ currency }}</text>
{{ info.faceValue }}
</view>
<view class="coupon-list__limit">{{ info.limitDesc }}</view>
</view>
<view class="coupon-list__content">
<view class="coupon-list__desc">{{ info.name }}</view>
<view class="coupon-list__date">{{ info.couponValidTime }}</view>
</view>
<view class="coupon-list__right">
<radio
:value="info.pickupId"
color="#EC1500"
:checked="selectedCouponIndex === info.pickupId"
/>
</view>
</view>
</scroll-view>
</template>
<view v-else class="coupon-list__empty"><empty text="暂无优惠券"/></view>
</view>
<view v-if="list.length" class="coupon-list__bottom">
<button @click="handleRadioSubmit">确定</button>
</view>
</view>
</template>
<script>
// import { getCouponChooseList } from "../api/home.api";
import Empty from "@/components/empty";
export default {
name: "CouponList",
components: {
Empty
},
props: {
value: null,
currency: {
type: String,
default: "¥"
},
list: Array,
update: Number
},
data() {
return {
selectedCouponIndex: null
};
},
computed: {
selectedCoupon() {
return this.list.filter(item => item.pickupId === this.selectedCouponIndex);
}
},
watch: {
update: {
immediate: true,
handler(val) {
if (val) this.selectedCouponIndex = this.value;
}
},
value: {
immediate: true,
handler(val) {
if (val) this.selectedCouponIndex = val;
}
}
},
methods: {
handleSelectCoupon(index) {
this.selectedCouponIndex = this.selectedCouponIndex === index ? -1 : index;
this.$emit("selectCouponItem", this.selectedCouponIndex !== -1, this.selectedCoupon);
},
handleRadioSubmit() {
this.$emit("select", this.selectedCoupon);
}
}
};
</script>
<style lang="scss" scoped>
.coupon-list {
&__bottom {
padding: 20rpx 40rpx 30rpx;
position: relative;
button {
background-image: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
border-radius: 160rpx;
height: 80rpx;
font-size: 28rpx;
line-height: 80rpx;
color: #fff;
}
}
&__list {
padding: 20rpx 20rpx 0;
overflow-y: scroll;
overflow-x: hidden;
height: 70vh;
}
&__scroll {
height: 100%;
}
&__empty {
padding-top: 100rpx;
}
&__item {
position: relative;
display: flex;
align-items: center;
background: #ffece6;
border-radius: 12rpx;
padding: 37.5rpx 20rpx;
margin-bottom: 20rpx;
&--disabled {
-webkit-filter: grayscale(100%) opacity(0.8); /* Chrome, Safari, Opera */
filter: grayscale(100%) opacity(0.8);
.cr-coupon-list__right {
display: none;
}
}
}
&__tag {
position: absolute;
top: 0;
left: 0;
width: 88rpx;
height: 32rpx;
}
&__left {
text-align: center;
color: #ec3333;
width: 176rpx;
}
&__amount {
font-size: 60rpx;
font-weight: 500;
line-height: 72rpx;
margin: 0;
text {
font-size: 32rpx;
line-height: 44rpx;
}
}
&__limit {
font-size: 24rpx;
color: #ec3333;
line-height: 34rpx;
margin: 0;
}
&__content {
padding: 0 36rpx;
}
&__desc {
font-size: 28rpx;
line-height: 40rpx;
font-weight: 500;
color: #333;
margin-bottom: 6rpx;
}
&__date {
font-size: 24rpx;
color: #666666;
line-height: 34rpx;
}
&__right {
margin-left: auto;
&.wx-radio-input {
background-color: #ffece6 !important;
}
radio {
transform: scale(0.8);
}
}
}
</style>
<template>
<view v-if="couponList.length" class="banner-container">
<view class="banner-title">本单已享以下权益</view>
<swiper next-margin="25px">
<block v-for="(item, index) in couponList" :key="index">
<swiper-item class="banner-item">
<view class="banner-box">
<image src="https://img.lkbang.net/xcx/coupon_bg.13815473.png" class="banner-img" />
<view class="banner-left">
<view class="banner-left_left">
<text>{{ item.faceValue }}</text>
<view>{{ item.couponType }}</view>
</view>
<view class="banner-left_center">
<text>{{ item.name }} </text>
<view>{{ item.couponValidTime }}</view>
</view>
<view class="banner-right" @click="goHome(item)">
<button>立即查看</button>
</view>
</view>
</view>
</swiper-item>
</block>
</swiper>
</view>
</template>
<script>
// import { guideStream } from "@/api/pay.api.js";
import { saTrackEvent } from "@/utils/sa.js";
export default {
props: {
couponList: {
type: Array,
default: () => []
}
},
data() {
return {
// couponList: []
};
},
watch: {
couponList: {
immediate: true,
handler() {
this.coupon();
}
}
},
methods: {
goHome(data) {
uni.switchTab({
url: "/pages/index/index"
});
saTrackEvent("MINI_PaymentSuccessPageCouponClick", {
coupon_type: data.couponType,
coupon_value: data.faceValue,
coupon_name: data.name
});
},
async coupon() {
// const [data, error] = await guideStream(this.list);
// if (error || !data.couponList) return;
this.couponList.map(item => {
item.couponType = this.couponCate(item.couponCategory);
});
// this.couponList = data.couponList;
},
couponCate(type) {
// :1-满减券,2-运费券,3-现金券,21-享花券
let name = "";
switch (type) {
case 1:
name = "满减券";
break;
case 2:
name = "运费券";
break;
case 3:
name = "现金券";
break;
case 21:
name = "享花券";
break;
}
return name;
}
}
};
</script>
<style scoped lang="scss">
@import "@/style/var.scss";
.banner-container {
height: 276rpx;
background-color: #fff;
margin: $uni-spacing-col-md;
overflow: hidden;
padding-top: 20rpx;
padding: 24rpx 16rpx;
.banner-title {
font-size: 28rpx;
color: #ff4735;
padding-left: 20rpx;
padding-bottom: 10rpx;
}
.banner-item {
width: 100%;
display: flex;
justify-content: center;
}
.banner-box {
width: 606rpx;
height: 180rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
.banner-img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.banner-left {
z-index: 1;
display: flex;
align-items: center;
padding-right: 30rpx;
&_left {
margin-left: 70rpx;
margin-right: 30rpx;
color: $red-light;
font-size: 38rpx;
text-align: center;
text {
font-size: 40rpx;
}
view {
font-size: 24rpx;
}
}
&_center {
text-align: centet;
margin-right: 12rpx;
text {
display: inline-block;
font-size: 28rpx;
color: $black;
}
view {
font-size: 18rpx;
color: $gray-5;
}
}
}
.banner-right {
border-left: 1px dashed #fed7c5;
padding-left: 5rpx;
z-index: 1;
height: 70%;
display: flex;
align-items: center;
button {
background: $gradient-red;
font-size: 24rpx;
color: $white;
height: 50rpx;
line-height: 50rpx;
/* #ifndef MP-ALIPAY */
padding: 0 20rpx;
/* #endif */
margin-left: 14rpx;
width: 136rpx;
}
}
}
}
</style>
<template>
<view style="text-align: center" catchtouchmove="true" class="pop">
<scroll-view scroll-y class="head">
<!-- 百度小程序-preview Boolean 否 点击后是否预览图片。在不设置的情况下,若 image 未监听点击事件且宽度大于 1/4 屏宽,则默认开启 -->
<image
src="https://img.lkbang.net/xcx/cardBackground.png"
:preview="false"
class="cardBackground"
/>
<text class="text">恭喜您获得了一张礼品卡</text>
<view class="couponCard">
<image src="https://img.lkbang.net/xcx/fullRedu.png" class="fullRedu" />
<text class="price"><text style="font-size: 12px">¥</text>{{ denomination }}</text>
<text class="condition">{{ limitDesc }}</text>
<text class="indate">{{ cardValidPeriod }}</text>
<button class="btn"><text class="look" @click="giftCard">立即查看</text></button>
</view>
<view class="notice">
礼品卡已放入您的账户中,点击“
<text style="text-decoration: underline" @click="giftCard">礼品卡</text>
”即可查看
</view>
</scroll-view>
<view class="bottom">
<image src="https://img.lkbang.net/xcx/close.png" class="close" @click="closePopCard" />
</view>
</view>
</template>
<script>
export default {
props: {
denomination: {
type: [Number, String],
default: () => {
return 0;
}
},
limitDesc: {
type: String,
default: () => {
return "";
}
},
cardValidPeriod: {
type: String,
default: () => {
return "";
}
}
},
methods: {
closePopCard() {
this.$emit("closePopCard");
},
giftCard() {
uni.navigateTo({ url: "/pages/giftCardList/index" });
}
}
};
</script>
<style scoped>
.pop {
position: fixed;
top: 260rpx;
left: 39rpx;
z-index: 999;
}
.cardBackground {
width: 672rpx;
height: 686rpx;
}
.close {
width: 66rpx;
height: 66rpx;
margin-top: 32rpx;
}
.head {
height: 100%;
position: relative;
z-index: 101;
}
.bottom {
position: relative;
z-index: 101;
}
.text {
font-size: 44rpx;
color: #e11500;
/* z-index: 1; */
position: absolute;
top: 99.16rpx;
left: calc((100% - 636rpx) / 2 + 74.22rpx);
}
.notice {
width: 100%;
height: 34rpx;
line-height: 34rpx;
font-size: 24rpx;
color: #ffffff;
position: absolute;
top: 624rpx;
left: calc((100% - 636rpx) / 2 + 47rpx);
display: flex;
}
.couponCard {
width: 574rpx;
height: 166rpx;
background-color: #ffffff;
border-radius: 12rpx;
position: absolute;
top: 302rpx;
left: calc((100% - 636rpx) / 2 + 32rpx);
}
.fullRedu {
width: 88rpx;
height: 32rpx;
position: absolute;
left: calc((100% - 636rpx) / 2 + 32rpx);
}
.price {
width: 92rpx;
height: 84rpx;
font-size: 42rpx;
line-height: 84rpx;
position: absolute;
color: #ec3333;
top: 46rpx;
left: calc((100% - 636rpx) / 2 + 55rpx);
}
.condition {
/* width: 166rpx; */
height: 40rpx;
font-size: 28rpx;
color: #333333;
position: absolute;
top: 48rpx;
left: calc((100% - 636rpx) / 2 + 210rpx);
}
.indate {
/* width: 216rpx; */
height: 34rpx;
font-size: 24rpx;
color: #666666;
position: absolute;
top: 94rpx;
left: calc((100% - 636rpx) / 2 + 210rpx);
}
.btn {
width: 160rpx;
height: 50rpx;
line-height: 46rpx;
background-color: #ff2f28;
border-radius: 25rpx;
position: absolute;
top: 62rpx;
left: calc((100% - 636rpx) / 2 + 439rpx);
}
.look {
width: 96rpx;
font-size: 24rpx;
color: #ffffff;
}
</style>
<template>
<view class="app">
<view class="price-box">
<text class="price">{{ displayInfo.orderAmt }}</text>
<view v-if="!overtime" class="time"
>支付剩余时间:
<uni-countdown
:second="displayInfo.periodSeconds"
:show-day="false"
class="countdown"
@timeup="timeup"
/>
</view>
<text v-else>支付超时,订单关闭</text>
</view>
<payCard
:pay-type="payType"
:value="displayInfo"
:coupon-info="selectedCoupon"
:disabled="overtime"
:has-pwd="creditPayInfo.hasPwd"
:pay-text="text"
:show-coupon="showCoupon"
:risk-limit="riskLimit"
@changePayType="changePayType"
/>
<label v-if="showProtocol" class="protocol" @click="confirmProtocol">
<checkbox
class="protocol__chk"
:value="protocolChecked"
color="#EC1500"
:checked="protocolChecked === 1"
/>
<view class="protocol__txt">
勾选同意
<text
v-for="(item, index) in payContractInfo.contractInfos"
:key="index"
class="protocol__txt-item"
@click.stop="viewProtocol(item.contractVisitUrl)"
>
{{ item.contractName }}
</text>
</view>
</label>
<view v-if="isReady && !overtime" class="btn">
<button type="primary" class="btn-primary" :disabled="!!!payType" @click="nextAction">
{{ accountS.text }}
</button>
</view>
<view v-if="overtime" class="btn">
<button type="default" class="btn-default" @click="goOrderDetail">查看订单</button>
<button type="primary" class="btn-primary" @click="goHome">返回商城</button>
</view>
<pwd-modal
:modal="pwdModal"
:error-info="error"
:amount="
payType === 2 || !selectedCoupon.faceValueNew
? displayInfo.orderAmt
: (displayInfo.orderAmt - selectedCoupon.faceValueNew).toFixed(2)
"
:forget-pwd-jump-url="creditPayInfo.forgetPwdJumpUrl"
@close="pwdModal = false"
@submit="getPwd"
/>
<sms-modal
:modal="smsModal"
:error-info="error"
@close="smsModal = false"
@submit="getSms"
@send="sendSms"
/>
<tipModal :value="showTip" scene="pay" type="app" @change="changeTipStatus" />
<uni-popup
ref="commonPopup"
type="bottom"
:closeable="true"
title="选择优惠券"
@change="changePop"
>
<coupon-list
ref="couponList"
:value="selectedCoupon.pickupId"
:list="payCouponList"
:update="random"
@select="handleSelectCoupon"
@selectCouponItem="selectCouponItem"
/>
</uni-popup>
<tipModal :value="showGoFaceTip" type="appToFace" @change="changeTipStatus($event, true)" />
<uni-popup ref="cardPopup">
<uni-popup-dialog
type="base"
content="使用享花卡支付需要您绑定银行卡便于后续的还款哦~"
message=""
title=" "
:duration="2000"
:before-close="true"
cancel-txt="切换支付方式"
confirm-txt="去绑卡"
@cancel="switchPayType"
@confirm="openCard"
/>
</uni-popup>
</view>
</template>
<script>
import authApi from "@/api/address.api";
import { h5Mixin } from "@/utils/h5Mixin";
import payCard from "@/components/payCard";
import tipModal from "@/components/tip-modal";
import pwdModal from "@/components/pwd-modal";
import couponList from "./components/couponList";
import smsModal from "@/components/sms-modal";
import { uniCountdown } from "@dcloudio/uni-ui";
import { encryptByDESModeEBC } from "@/utils/encrypt";
import { saTrackEvent } from "@/utils/sa";
import { status, codeArr, payTypeE, payTypeText, creditStatus, creditPayStatusType } from "./data";
import { kaFlow } from "@/api/ka.api.js";
import config from "@/config";
import {
pay,
prepay,
sendSms,
queryPayInfo,
queryPayStatus,
getCoupon,
reissueContract,
getOrderType
} from "../../api/pay.api.js";
import UniPopup from "@/components/uni-popup/uni-popup.vue";
import uniPopupDialog from "@/components/uni-popup/uni-popup-dialog";
export default {
components: {
payCard,
tipModal,
pwdModal,
smsModal,
uniCountdown,
couponList,
UniPopup,
uniPopupDialog
},
mixins: [h5Mixin()],
provide() {
return {
pay: this
};
},
data() {
return {
showTip: false,
payType: null,
orderInfo: {},
overtime: false,
orderNo: "",
displayInfo: {},
creditPayInfo: {},
pwdModal: false,
smsModal: false,
flowOrderNo: null,
error: "",
forgetPwdJumpUrl: "",
downModal: true,
accountS: {
text: "确认支付",
fn: this.pay
},
openId: "",
text: "推荐支付方式",
payCouponList: [],
selectedCoupon: {},
showCoupon: false,
isReady: false,
showGoFaceTip: false,
random: "",
protocolChecked: 0,
payContractInfo: {
contractInfos: []
},
bindBankCardInfo: {}
};
},
onShow() {
this.setDatas();
this.queryPayInfo();
},
onLoad({ orderNo, showTip }) {
if (showTip === "true") {
// 从h5授信跳转回来的需要提示下载app
this.tip();
}
this.orderNo = orderNo || uni.getStorageSync("orderNo");
uni.setStorageSync("orderNo", this.orderNo);
// this.queryPayInfo();
this.getCouponList(this.orderNo);
},
computed: {
riskLimit() {
return this.isRiskLimit();
},
showProtocol() {
return (
this.payContractInfo?.payContractIsSign &&
this.payType === 1 &&
this.creditPayInfo.accountStatus === 5
);
}
},
watch: {
payType() {
this.getBtnStatus(this.isRiskLimit());
}
},
methods: {
// 切换支付方式
switchPayType() {
console.log("切换支付方式");
const info = this.displayInfo;
for (let item in info) {
const show = info[item].show;
if (show && info[item].payType !== 1) {
this.displayInfo.creditPayInfo.disabled = true;
this.changePayType(info[item].payType);
this.$refs["cardPopup"].close();
return;
}
}
},
// 绑定银行卡
openCard() {
if (this.bindBankCardInfo?.bindBankCardUrl) {
const url = `${this.bindBankCardInfo.bindBankCardUrl}&fromXcxPage=pay`;
uni.redirectTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
this.$refs["cardPopup"].close();
return;
}
},
setDatas() {
if (uni.getStorageSync("channlFlag") === "ka") {
this.kaFlowState();
}
this.openId =
(this.$store.state.userAuthInfo && this.$store.state.userAuthInfo.openid) ||
uni.getStorageSync("openid");
if (!this.openId) {
this.text = "推荐支付方式:";
}
},
// 是否授信
async kaFlowState() {
const [data] = await kaFlow();
if (data.value) {
uni.setStorageSync("vccChannel", "159913");
uni.setStorageSync("sonVccChannel", "");
}
},
isRiskLimit() {
const { accountStatus, riskManagementAmt } = this.creditPayInfo;
const { orderAmt } = this.displayInfo;
if (accountStatus === 5) {
const coupon = +this.selectedCoupon.faceValueNew || 0;
return +riskManagementAmt + coupon < +orderAmt;
} else {
return false;
}
},
async getCouponList(orderNo) {
const [data] = await getCoupon({ orderNo: orderNo });
if (data && data.coupons) {
this.payCouponList = data.coupons.filter(item => item.couponCategory === 21);
}
},
openCouponModal() {
saTrackEvent("PD_YXMMACP_UserClickCouponBanner");
this.random = Math.random();
this.$refs.commonPopup.open();
},
// 选取优惠券
handleSelectCoupon(selectedCoupon) {
saTrackEvent("PD_YXMMACP_UserClickCouponPopupWindowComfirmBtn");
this.selectedCoupon = selectedCoupon.length ? selectedCoupon.pop() : {};
if (!("faceValueNew" in this.selectedCoupon)) {
this.selectedCoupon.faceValueNew = this.selectedCoupon.faceValue;
}
if (!("limitAmountNew" in this.selectedCoupon)) {
this.selectedCoupon.limitAmountNew = this.selectedCoupon.limitAmount;
}
const status = this.checkStatus(this.creditPayInfo, this.displayInfo);
if (status) {
this.displayInfo.creditPayInfo.disabled = true;
this.payType = 2;
} else {
this.displayInfo.creditPayInfo.disabled = false;
}
this.getBtnStatus(this.isRiskLimit());
this.$refs.commonPopup.close();
},
//选择支付方式
changePayType(type) {
if (this.payType == 6) {
uni.showToast({ title: "请选择现金券支付!", icon: "none" });
type = 6;
}
this.payType = type;
},
getOpenid() {
// 获取openid
return new Promise(reslove => {
uni.login({
provider: "weixin",
success: async function(res) {
const [getData] = await authApi.login({
code: res.code
});
if (getData) {
reslove(getData.openid);
} else {
reslove();
}
}
});
});
},
//预支付
async pay(params) {
this.error = "";
if (!this.openId) {
this.openId = await this.getOpenid();
}
if (
!this.bindBankCardInfo?.isBindBankCard &&
this.bindBankCardInfo?.bindBankCardUrl &&
this.payType == 1
) {
this.$refs["cardPopup"].open();
return;
}
if (this.payType === 1 && !this.creditPayInfo.hasPwd) {
const url = `${this.creditPayInfo.pwdSetJumpUrl}&vccChannel={vccChannel}`;
this.goH5(url);
return;
}
const paramsData = {
...params,
orderNo: this.orderNo,
payMethod: !params ? this.payType : null,
openId: this.openId,
payCouponId: this.selectedCoupon.pickupId || "",
appMiniId: wx.getAccountInfoSync().miniProgram.appId || ""
};
const [data, error] = params ? await pay(paramsData) : await prepay(paramsData);
if (error) {
if (codeArr.indexOf(error.response.businessCode) < 0) {
this.payResult("Fail", error.msg);
return;
}
this.error = error.msg;
return;
}
const { creditPayInfo = {}, wxPayInfo, flowOrderNo } = data;
const creditPayStatus = creditPayInfo.creditPayStatus;
this.flowOrderNo = flowOrderNo;
if (!params && this.payType === 2) {
// 微信支付
console.log("微信支付");
this.wxPay(wxPayInfo);
return;
}
if (creditPayStatus === 3) {
//支付成功;
this.payResult("Success");
return;
}
if (creditPayStatus === 1 || creditPayStatus === 2) {
// 密码或者短信鉴权
this.close();
this[`${creditPayStatusType[creditPayStatus]}Modal`] = true;
}
if (this.payType === 6) {
!params && this.pay({ flowOrderNo: this.flowOrderNo });
params && this.payResult("Success");
}
},
async payResult(type, error) {
if (error && !this.openId) {
// 测试openId是否存在
error += "!";
}
const finalAmt =
this.payType === 2 || !this.showCoupon
? this.displayInfo.orderAmt || "0.00"
: (this.displayInfo.orderAmt - (this.selectedCoupon.faceValueNew || 0)).toFixed(2);
const freeAmount =
this.payType === 1 && this.showCoupon ? this.selectedCoupon.faceValueNew || "0.00" : "0.00";
const [res] = await getOrderType(this.orderNo);
const isHundredGroupOrder = res.hundredGroupOrder || false;
if (isHundredGroupOrder) {
// 拼团0元购要返回H5支付结果页
const token = uni.getStorageSync("token") || "";
const payStatus = error ? "payFail" : "paySuccess";
const url = `${config.groupBuyHost}/${payStatus}?vccToken=${token}&amount=${finalAmt}&reason=${error}&orderNo=${this.orderNo}&freeAmount=${freeAmount}&payType=${this.payType}`;
uni.redirectTo({
url: `/pages/groupbuy/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
return;
}
// 原有逻辑
uni.redirectTo({
url: `/pages/pay/pay${type}?amount=${finalAmt}&reason=${error}&orderNo=${this.orderNo}&freeAmount=${freeAmount}&payType=${this.payType}`
});
},
wxPay(params) {
uni.requestPayment({
...params,
complete: () => {
this.queryPayStatus();
}
});
},
close() {
this.pwdModal = false;
this.smsModal = false;
},
async queryPayInfo() {
const [data, error] = await queryPayInfo({ orderNo: this.orderNo });
if (error) return;
const { displayInfo = {}, payMethods, bindBankCardInfo } = data || {};
if (displayInfo.payCouponInfo && displayInfo.payCouponInfo.optimalPayCoupon) {
this.selectedCoupon = displayInfo.payCouponInfo.optimalPayCoupon;
this.showCoupon = displayInfo.payCouponInfo.optimalType === 3;
}
this.payContractInfo = displayInfo.payContractInfo;
this.bindBankCardInfo = bindBankCardInfo;
this.isReady = !!payMethods;
for (const key in displayInfo) {
const payType = displayInfo[key].payType;
if (payType) {
for (const p of payMethods) {
if (p.isDefault) {
this.payType = p.method;
}
if (p.method === payType) {
displayInfo[key] = {
...displayInfo[key],
...p,
show: true
};
break;
}
}
}
if (key === "creditPayInfo" && this.checkStatus(displayInfo[key], displayInfo)) {
displayInfo[key].disabled = true;
}
}
if (this.payType === 1 && displayInfo.creditPayInfo.disabled) {
this.payType = null;
}
this.payType &&
saTrackEvent(payTypeE[this.payType - 1], {
order_id: this.orderNo
});
this.displayInfo = displayInfo || {};
this.creditPayInfo = displayInfo.creditPayInfo || {};
// const { accountStatus, riskManagementAmt } = this.creditPayInfo;
// const { orderAmt } = this.displayInfo;
// if (accountStatus === 5 && riskManagementAmt && +riskManagementAmt < +orderAmt) {
// // 订单金额大于风控返回的可用额度,需引导进行活体认证并展示提示与
// this.displayInfo.creditPayInfo.isRiskLimit = true;
// }
this.overtime = displayInfo.periodSeconds <= 0;
this.getBtnStatus(this.isRiskLimit());
},
checkStatus({ accountStatus, canAmt }, { orderAmt }) {
// 开户成功已有额度小于订单额度和审核被拒
if (!this.selectedCoupon.faceValueNew) {
return (accountStatus === 5 && +orderAmt > +canAmt) || accountStatus === 3;
}
return (
(accountStatus === 5 && +orderAmt > +canAmt + +this.selectedCoupon.faceValueNew) ||
accountStatus === 3
);
},
timeup() {
this.overtime = true;
this.payType = null;
this.close();
},
async getPwd(e) {
this.pay({ flowOrderNo: this.flowOrderNo, password: await encryptByDESModeEBC(e) });
},
async sendSms(fn) {
const [, error] = await sendSms({ orderNo: this.orderNo, flowOrderNo: this.flowOrderNo });
if (!error) {
fn();
}
},
getSms(e) {
this.pay({ flowOrderNo: this.flowOrderNo, smsAuthorizationCode: e });
},
apply() {
this.goApply("pay");
},
tip() {
this.showGoFaceTip = true;
},
getBtnStatus(isRiskLimit) {
const { accountStatus } = this.creditPayInfo;
if (!accountStatus) return;
if (this.payType === 1) {
// payType=1--享花卡支付,payType=2微信支付
if (accountStatus === 4) {
this.accountS = {
text: "立即激活",
fn: this.apply
};
} else if (creditStatus.indexOf(accountStatus) > -1) {
this.accountS = {
text: "立即开通",
fn: this.apply
};
} else if (isRiskLimit) {
// 展示限额提示
this.accountS = {
text: "认证提额",
fn: () => {
this.tip("appToFace");
}
};
} else if (accountStatus === 5) {
const finalCount = this.showCoupon
? (this.displayInfo.orderAmt - (this.selectedCoupon.faceValueNew || 0)).toFixed(2)
: this.displayInfo.orderAmt;
const txt = `实际支付${finalCount || "0.00"}`;
this.accountS = {
text: txt,
fn: this.pay
};
}
} else {
const txt = `确认支付`;
this.accountS = {
text: txt,
fn: this.pay
};
}
},
async nextAction() {
try {
const [res] = await getOrderType(this.orderNo);
const isHundredGroupOrder = res.hundredGroupOrder || false;
if (isHundredGroupOrder) {
saTrackEvent("MINI_CheckOutCounterConfirmPayBtnClick", {
order_type: "0元购"
});
}
} catch (e) {
console.log(e);
}
saTrackEvent("PD_YXMMACP_UserClickCashierConfirmPaymentBtn", {
order_id: this.orderNo,
pay_method: payTypeText[this.payType - 1],
vcc_state: status[this.creditPayInfo.accountStatus - 1],
buttons_name: this.accountS.text
});
uni.reportAnalytics("c_cashierconfirmpaymentbtn", {
order_id: this.orderNo,
pay_method: payTypeText[this.payType - 1],
vcc_state: status[this.creditPayInfo.accountStatus - 1],
buttons_name: this.accountS.text
});
if (this.showProtocol) {
if (this.protocolChecked === 1) {
this.reissueContract();
this.accountS.fn();
} else {
this.$api.msg("请阅读并同意协议");
}
} else {
this.accountS.fn();
}
},
async queryPayStatus() {
const [{ payStatus }, error] = await queryPayStatus({ orderNo: this.orderNo });
if (error) {
this.payResult("Fail", error.msg);
return;
}
if (+payStatus === 3) {
this.payResult("Success");
}
},
goHome() {
uni.switchTab({
url: "/pages/index/index"
});
},
goOrderDetail() {
uni.redirectTo({
url: `/pages/order/orderDetail?orderNo=${this.orderNo}`
});
},
changeTipStatus(obj, isAppToFace) {
if (!isAppToFace) {
this.showTip = obj.show;
} else {
this.showGoFaceTip = obj.show;
}
},
selectCouponItem(isSelected, couponInfo) {
saTrackEvent("PD_YXMMACP_UserClickCouponPopupWindowCoupon", {
check_or_not: isSelected ? "勾选" : "取消",
coupon_id: couponInfo.pickupId
});
},
changePop(pop) {
if (pop?.show === false) {
saTrackEvent("PD_YXMMACP_UserClickCouponPopupWindowCloseBtn");
}
},
confirmProtocol() {
this.protocolChecked = this.protocolChecked ? 0 : 1;
},
viewProtocol(url) {
uni.redirectTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
},
async reissueContract() {
await reissueContract({
templateIdList: this.payContractInfo.contractInfos.map(item => item.contractId)
});
}
}
};
</script>
<style lang="scss">
@import "./index";
</style>
.app {
width: 100%;
padding: $padding-md;
}
.price-box {
background-color: #fff;
height: 218rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: $uni-font-size-sm;
color: #333333;
border-radius: $border-radius-md;
.price{
font-size: $font-1;
color: $font-color-red;
margin-top: $margin-md;
&:before{
content: '¥';
font-size: $uni-font-size-md;
font-weight: bold;;
}
}
.time{
display: flex;
align-items: center;
.countdown{
width: 140rpx;
}
}
}
.btn{
height:120rpx;
width: 100%;
position: fixed;
padding: 0 $padding-lg;
box-sizing: border-box;
bottom: 0;
left:0;
background-color:#fff;
display: flex;
align-items: center;
justify-content: center;
button{
flex:1;
color: $white;
font-size: $line-height-md;
border-radius: $uni-border-radius-xl;
}
button[disabled] {
color: rgba(255,255,255,.6);
}
&-primary {
@include primary-bg;
border: 0;
}
&-default{
border: 1px solid $uni-color-error;
color: $uni-color-error !important;
margin-right: $margin-base;
background-color: $white !important;
display: flex;
align-items: center;
justify-content: center;
}
}
.placeholder {
width: 100%;
height: 220rpx;
}
.protocol {
width: 100%;
position: fixed;
padding: $padding-md - 4 $padding-lg 0;
box-sizing: border-box;
bottom: 120rpx;
left:0;
background-color:#fff;
display: flex;
align-items: baseline;
&__chk {
.wx-checkbox-input {
margin-top: 0;
width: 28rpx;
height: 28rpx;
border-radius: 50%;
&.wx-checkbox-input-checked {
background: #ec1500;
border-color: #ec1500;
&::before {
width: 28rpx;
height: 28rpx;
line-height: 28rpx;
text-align: center;
font-size: 20rpx;
color: #fff;
background: transparent;
transform: translate(-50%, -50%) scale(1);
-webkit-transform: translate(-50%, -50%) scale(1);
}
}
}
}
&__txt {
font-size: 24rpx;
font-weight: 400;
color: #666666;
line-height: 34rpx;
&-item {
color: #ec1500;
}
}
}
\ No newline at end of file
<template>
<likeGood :page-type="4">
<view class="card">
<view class="info">
<image class="info__image" src="https://img.lkbang.net/xcx/pay-fail.png" />
<text class="info__text">订单支付失败!</text>
</view>
<view class="tips">
<text>{{ reason }}</text>
</view>
<button plain="true" type="primary" hover-class="none" @click="goPay">重新支付</button>
</view>
<!-- #ifdef MP-WEIXIN -->
<view v-if="showDivert && guideUrl" class="priv-divert" @click="navToDivert">
<image class="priv-divert-img" :src="guideUrl" mode="widthFix" />
</view>
<!-- #endif -->
<tougdunCanvas />
</likeGood>
</template>
<script>
import { guideStream } from "@/api/pay.api.js";
import likeGood from "@/components/likeGood";
import { saTrackEvent } from "@/utils/sa";
import tougdunCanvas from "@/components/tougdunCanvas.vue";
import { paymentConfig } from "@/utils/mpConfig/types";
import { smTrackEvent } from "@/utils/shumei";
export default {
async onLoad({ reason, orderNo, payType }) {
smTrackEvent({
eventId: "finishOrder",
orderId: orderNo,
orderResult: "1",
passThrough: {
payErrorReason: reason || ""
}
});
this.showDivert = uni.getStorageSync("tenantId") == 560761 ? true : false; // 羊小咩租户展示私域导流入口
this.reason = reason || "";
this.orderNo = orderNo;
/* #ifdef MP-WEIXIN */
this.list = {
payType: payType || 1,
paySuccess: false,
orderNo: this.orderNo
};
const [data, err] = await guideStream(this.list);
if (!err) {
const [guideItem] = (data?.guideList || []).filter(item => item.type === 1);
console.log(guideItem);
if (guideItem) {
this.guideUrl = guideItem.image;
this.jumpUrl = guideItem.jumpUrl || "";
}
}
/* #endif */
},
components: {
likeGood,
tougdunCanvas
},
data() {
return {
guideUrl: "",
jumpUrl: "",
reason: "",
orderNo: "",
list: {},
showDivert: false
};
},
methods: {
goPay() {
saTrackEvent("PD_YXMMAEC_UserClickCashierPaymentAgainBtn", {
order_id: this.orderNo
});
uni.reportAnalytics("c_cashierpaymentagainbtn", {
order_id: this.orderNo
});
uni.redirectTo({
url: `${paymentConfig.payUrl}?orderNo=${this.orderNo}`
});
},
navToDivert() {
saTrackEvent("PD_YXMMAEC_UserClickPaymentPageExtensionBanner", {
page_name: "支付失败"
});
const activityType = this.jumpUrl.split("activityType=")[1];
uni.navigateTo({
url: `/pages/activity/divertPrivDomain?activityType=${activityType}`
});
}
}
};
</script>
<style lang="scss" scoped>
.card {
margin: $uni-spacing-col-md;
background-color: white;
border-radius: $uni-border-radius-lg;
padding: 56rpx $uni-spacing-col-md $uni-spacing-col-md $uni-spacing-col-md;
.info {
display: flex;
justify-content: center;
align-items: center;
&__image {
width: 100px;
height: 100px;
}
&__text {
margin-left: $uni-spacing-row-lg;
font-size: $font-lg;
}
}
.tips {
margin-top: $uni-spacing-col-lg;
text-align: center;
font-size: $font-sm;
color: $font-color-light;
}
button {
margin-top: 40rpx;
border-radius: $uni-border-radius-xl;
font-size: $line-height-md;
color: #ec1500;
border: 1px solid #ec1500;
}
}
.priv-divert {
padding: 0 20rpx;
margin-bottom: 6rpx;
&-img {
border-radius: 16rpx;
overflow: hidden;
width: 100%;
}
}
</style>
<template>
<likeGood :page-type="4">
<view class="card">
<view class="info">
<image class="info__image" src="https://img.lkbang.net/paying.eu72a2f.png" />
<view class="info__desc">
<text v-if="time" class="info__text">{{ time }}s)支付中...</text>
<text v-else class="info__text">系统处理中!</text>
</view>
</view>
<view class="tips">
<text>稍后返回支付结果,请留心查看!</text>
</view>
<view class="actions">
<button
class="actions__back"
plain="true"
hover-class="none"
type="primary"
@click="goHome"
>
返回首页
</button>
<button
class="actions__order"
plain="true"
hover-class="none"
type="primary"
@click="setSubMsg"
>
查看订单
</button>
</view>
</view>
<!-- #ifdef MP-WEIXIN -->
<view v-if="showDivert && guideUrl" class="priv-divert" @click="navToDivert">
<image class="priv-divert-img" :src="guideUrl" mode="widthFix" />
</view>
<!-- #endif -->
</likeGood>
</template>
<script>
import { guideStream } from "@/api/pay.api.js";
import likeGood from "@/components/likeGood";
import { queryPayStatus } from "@/api/pay.api.js";
import { saTrackEvent } from "@/utils/sa";
import { getVaildSubTmplIds } from "@/api/home.api";
import cfg from "@/config/index";
import { h5Mixin } from "@/utils/h5Mixin";
import { getVaildTmplIds, submitSubcribeInfo, getAcceptList } from "@/utils/subscribe";
import { redirectLocation, isHundredGroup } from "./payRedirect.js";
const tmplIds = [
cfg.SUB_MSG_LIST.SELLER_SHIP,
cfg.SUB_MSG_LIST.ORDER_RECEIPT,
cfg.SUB_MSG_LIST.COUPON_RECEIPT
];
let vaildTmplIds = [];
export default {
components: {
likeGood
},
mixins: [h5Mixin()],
data() {
return {
orderNo: null,
timer: null,
time: 10,
init: false,
amount: 0,
freeAmount: 0,
payType: 0,
showDivert: false,
guideUrl: "",
jumpUrl: ""
};
},
async onLoad({ amount, orderNo, freeAmount, payType }) {
this.showDivert = uni.getStorageSync("tenantId") == 560761 ? true : false; // 羊小咩租户展示私域导流入口
this.amount = amount;
this.freeAmount = freeAmount;
this.payType = payType;
this.orderNo = orderNo;
this.init = true;
this.loop();
// #ifdef MP-WEIXIN
const [data, err] = await guideStream({
payType: payType || 1,
paySuccess: false,
orderNo: orderNo
});
if (!err) {
const [guideItem] = (data?.guideList || []).filter(item => item.type === 1);
if (guideItem) {
this.guideUrl = guideItem.image;
this.jumpUrl = guideItem.jumpUrl || "";
}
}
vaildTmplIds = await getVaildSubTmplIds(tmplIds);
// #endif
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
navToDivert() {
const activityType = this.jumpUrl.split("activityType=")[1];
uni.navigateTo({
url: `/pages/activity/divertPrivDomain?activityType=${activityType}`
});
},
goHome() {
uni.switchTab({
url: "/pages/index/index"
});
},
setSubMsg() {
if (!this.$config("yxm")) {
this.goOrderDetail();
return;
}
// #ifdef MP-WEIXIN
// 非羊小咩不触发订阅消息
if (!vaildTmplIds.length) return;
wx.requestSubscribeMessage({
tmplIds: vaildTmplIds,
success: res => {
this.submitInfo(res);
this.goOrderDetail();
const vaildIds = getVaildTmplIds(res);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "点击支付成功页查看订单",
check_content: vaildIds,
buttons_name: "允许"
});
},
fail: err => {
console.error("requestSubscribeMessage", err);
this.goOrderDetail();
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "点击支付成功页查看订单",
check_content: "商家发货通知,优惠券到账通知,优惠券过期通知",
buttons_name: "取消"
});
}
});
// #endif
/* #ifndef MP-WEIXIN */
this.goOrderDetail();
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "点击支付成功页查看订单",
check_content: [],
buttons_name: "允许"
});
/* #endif */
},
submitInfo(res) {
const acceptList = getAcceptList(res);
submitSubcribeInfo(acceptList);
},
goOrderDetail() {
saTrackEvent("PD_YXMMAEC_UserClickCashierCheckOrderBtn", {
order_id: this.orderNo
});
uni.reportAnalytics("c_cashiercheckorderbtn", {
order_id: this.orderNo
});
this.isGotoGroup();
},
loop() {
this.query();
this.timer = setInterval(() => {
this.time -= 1;
if (this.time % 2 === 0) {
this.query();
}
if (this.time < 1) {
clearInterval(this.timer);
}
}, 2000);
},
async isGotoGroup() {
/* #ifdef MP-WEIXIN */
if (await isHundredGroup(this.orderNo)) {
const url = `${cfg.groupBuyHost}/orderList/0?vccToken={token}`;
uni.redirectTo({
url: `/pages/groupbuy/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
return;
}
/* #endif */
uni.redirectTo({
url: `/pages/order/orderList?state=0`
});
},
async payResult(type, error) {
// eslint-disable-next-line prettier/prettier
if (await redirectLocation(this.orderNo, error, this.amount, this.freeAmount, this.payType)) return;
uni.redirectTo({
url: `/pages/pay/pay${type}?amount=${this.amount}&reason=${error}&orderNo=${this.orderNo}&freeAmount=${this.freeAmount}&payType=${this.payType}`
});
},
async query() {
const [data, error] = await queryPayStatus({ orderNo: this.orderNo });
if (error) {
this.payResult("Fail", error.msg);
return;
}
if (+data?.payStatus === 3) {
this.payResult("Success");
}
}
}
};
</script>
<style lang="scss" scoped>
.card {
margin: $uni-spacing-col-md;
background-color: white;
border-radius: $uni-border-radius-lg;
padding: 56rpx $uni-spacing-row-base $uni-spacing-row-base $uni-spacing-row-base;
.info {
display: flex;
justify-content: center;
align-items: center;
&__image {
width: 100px;
height: 100px;
}
&__text {
margin-left: $uni-spacing-row-lg;
font-size: $font-lg;
}
&__desc {
display: flex;
flex-direction: column;
}
&__money {
margin-top: $uni-spacing-col-base;
}
&__free {
color: $font-color-light;
font-size: $font-md;
margin-top: $uni-spacing-col-base;
}
}
.tips {
margin-top: $uni-spacing-col-lg;
text-align: center;
font-size: $font-sm;
color: $font-color-light;
}
.actions {
display: flex;
flex-direction: row;
margin-top: 42rpx;
&__back {
border: 1px solid $uni-text-color-grey;
color: $uni-text-color-grey;
}
&__order {
margin-left: $uni-spacing-row-base;
color: #ec1500;
border: 1px solid #ec1500;
}
button {
flex: 1;
border-radius: $uni-border-radius-xl;
font-size: $line-height-md;
}
}
}
.priv-divert {
padding: 0 20rpx;
margin-bottom: 10rpx;
&-img {
border-radius: 16rpx;
overflow: hidden;
width: 100%;
}
}
</style>
import {
status,
payTypeE,
payTypeText,
CREDIT_PAY,
IS_THIRD_PAY,
IS_CREDIT_PAY,
IS_GROUP_PAY
} from "./STATIC_DATA";
import { getOrderType, reissueContract } from "@/api/pay.api.js";
import { saTrackEvent } from "@/utils/sa";
import { isHundredGroup } from "./payRedirect.js";
import config from "@/config";
export default {
data() {
return {
configPopup: {},
popupConfig: {
// 未开通享花卡时,推荐开通享花卡
freeQuota: {
content: "您有一笔免费额度可以使用,40天免息等你拿",
cancelTxt: "继续支付",
confirmTxt: "立即开通",
cancel: "pay",
confirm: "apply"
},
// 已经开通享花卡时,使用其他方式支付时推荐组合支付
detention: {
content: "使用组合支付部分金额可免息使用40天哦!",
cancelTxt: "继续支付",
confirmTxt: "组合支付",
cancel: "pay",
confirm: "detentionConfirm"
},
// 已经开通享花卡,但没有组合支付时推荐使用享花卡支付
jcardPay: {
content: "使用享花卡支付可免息使用40天哦",
cancelTxt: "继续支付",
confirmTxt: "享花卡支付",
cancel: "pay",
confirm: "jcardPayConfirm"
},
// 用享花卡支付额度不足
insufficient: {
content: "您的消费额度不足,请更换支付方式!",
confirmTxt: "其他方式支付",
hideCancelBtn: true
},
cardPopup: {
content: "使用享花卡支付需要您绑定银行卡便于后续的还款哦~",
cancelTxt: "其他支付方式",
confirmTxt: "立即绑卡",
cancel: "switchPayType",
confirm: "openCard"
},
canUseAmt: {
conent: "抱歉,您的本笔订单暂不支持享花卡支付,请您使用其他支付方式~",
confirmTxt: "知道了",
hideCancelBtn: true
},
freezeCred: {
content: "您有未完成支付的订单占用额度,需要先支付完成该笔订单哦!",
cancelTxt: "继续支付",
confirmTxt: "查看订单",
confirm: "viewOrder"
},
isPaySuccess: {
content: "请确认订单已完成支付!",
cancelTxt: "重新支付",
confirmTxt: "已完成支付",
confirm: "isPayOrderSuccess"
}
}
};
},
methods: {
closeConfigModal() {
this.$refs["configPopup"].close();
},
openConfigModal(conkey, modalContent) {
const defaultValue = this.popupConfig[conkey];
const configPopup = {
...defaultValue
};
configPopup.content = modalContent ? modalContent : configPopup.content;
this.configPopup = configPopup;
this.$refs["configPopup"].open();
},
configEvent(eventKey) {
this[eventKey] && this[eventKey]();
},
// 推荐使用组合支付
detentionConfirm() {
for (let key in this.creditPayList.payList) {
if (this.creditPayList.payList[key].isRecommend) {
const type = this.creditPayList.payList[key].payType;
this.changePayType(type, this.creditPayList.payList[key].mergePayPretreatmentInfo);
this.protocolChecked = 1;
this.pay();
return;
}
}
},
jcardPayConfirm() {
// 切换享花卡支付
console.log("================>切换享花卡支付");
this.changePayType(CREDIT_PAY);
this.protocolChecked = 1;
},
async viewOrder() {
if (await isHundredGroup(this.orderNo)) {
// 判断是否是百人团
const url = `${config.groupBuyHost}/orderList/0?vccToken={token}`;
uni.redirectTo({
url: `/pages/groupbuy/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
return;
}
uni.redirectTo({
url: "/pages/order/orderList"
});
},
isPayOrderSuccess() {
const payType = this.payType;
const showCoupon = this.showCoupon;
const { orderAmt } = this.displayInfo;
const { faceValueNew } = this.selectedCoupon;
// eslint-disable-next-line prettier/prettier
const finalAmt = payType === 2 || !showCoupon ? orderAmt || "0.00" : (orderAmt - (faceValueNew || 0)).toFixed(2);
let freeAmount = payType === 1 && showCoupon ? faceValueNew || "0.00" : "0.00";
if (IS_GROUP_PAY(payType)) {
freeAmount = faceValueNew;
}
uni.redirectTo({
url: `/pages/pay/payLoading?amount=${finalAmt}&orderNo=${this.orderNo}&freeAmount=${freeAmount}&payType=${this.payType}`
});
},
filterPayMethods(payMethods, displayInfo) {
// const miniFace = displayInfo?.creditPayInfo?.miniFace;
// 是否需要认证提额,如果需要认证提额 默认选中享花卡选项
// if (miniFace) {
// payMethods = payMethods.map(item => {
// item.isDefault = item.method === CREDIT_PAY;
// return item;
// });
// }
for (const p of payMethods) {
// 默认支付方式
if (p.isDefault) {
this.payType = p.method;
}
for (const key in displayInfo) {
const payType = displayInfo[key].payType;
if (!payType) {
continue;
}
/* 三方支付 */
/* 过滤出微信数据 */
if (IS_THIRD_PAY(p.method) && p.method === payType) {
this.$set(this.thirdPayList.payList, key, {
...displayInfo[key],
...p,
show: true,
isCheck: p.isDefault || false
});
break;
}
/* 信用支付 */
if (
IS_CREDIT_PAY(p.method) &&
(p.method === payType || (p.method > 3 && p.method - 2 === payType))
) {
console.log("key========>", key, p.method);
this.creditPayList.isGroupPay = IS_GROUP_PAY(p.method);
if (p.isDefault) {
this.mergePayPretreatmentInfo = p.mergePayPretreatmentInfo;
}
if (key === "creditPayInfo" && this.checkStatus(displayInfo[key], displayInfo)) {
displayInfo[key].disabled = true;
}
this.$set(this.creditPayList.payList, key, {
...displayInfo[key],
...p,
show: true,
payType: p.method,
isCheck: p.isDefault || false,
isGroupPay: IS_GROUP_PAY(p.method)
});
if (!("creditPayInfo" in this.creditPayList.payList)) {
this.$set(this.creditPayList.payList, "creditPayInfo", {
...displayInfo["creditPayInfo"],
show: true,
isCheck: false
});
}
break;
}
}
}
},
sendPayTrack() {
this.payType &&
saTrackEvent(payTypeE[this.payType - 1], {
order_id: this.orderNo
});
},
async sendNextAction() {
try {
const [res] = await getOrderType(this.orderNo);
const isHundredGroupOrder = res.hundredGroupOrder || false;
if (isHundredGroupOrder) {
saTrackEvent("MINI_CheckOutCounterConfirmPayBtnClick", {
order_type: "0元购"
});
}
} catch (e) {
console.log(e);
}
saTrackEvent("PD_YXMMACP_UserClickCashierConfirmPaymentBtn", {
order_id: this.orderNo,
pay_method: payTypeText[this.payType - 1],
vcc_state: status[this.creditPayInfo.accountStatus - 1],
buttons_name: this.accountS.text
});
uni.reportAnalytics("c_cashierconfirmpaymentbtn", {
order_id: this.orderNo,
pay_method: payTypeText[this.payType - 1],
vcc_state: status[this.creditPayInfo.accountStatus - 1],
buttons_name: this.accountS.text
});
},
selectCouponItem(isSelected, couponInfo) {
saTrackEvent("PD_YXMMACP_UserClickCouponPopupWindowCoupon", {
check_or_not: isSelected ? "勾选" : "取消",
coupon_id: couponInfo.pickupId
});
},
changePop(pop) {
pop?.show === false && saTrackEvent("PD_YXMMACP_UserClickCouponPopupWindowCloseBtn");
},
viewProtocol(url) {
// 查看合同链接
uni.redirectTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
},
async reissueContract() {
// 发送合同协议
await reissueContract({
templateIdList: this.payContractInfo.contractInfos.map(item => item.contractId)
});
}
}
};
import { getOrderType } from "@/api/pay.api.js";
import config from "@/config";
export async function isHundredGroup(orderNo) {
try {
const [res] = await getOrderType(orderNo);
return res?.hundredGroupOrder || false;
} catch (err) {
return false;
}
}
export async function redirectLocation(orderNo, error, finalAmt, freeAmount, payType) {
try {
const isGroup = await isHundredGroup(orderNo);
if (isGroup) {
const token = uni.getStorageSync("token") || "";
const payStatus = error ? "payFail" : "paySuccess";
const url = `${config.groupBuyHost}/${payStatus}?vccToken=${token}&amount=${finalAmt}&reason=${error}&orderNo=${orderNo}&freeAmount=${freeAmount}&payType=${payType}`;
uni.redirectTo({
url: `/pages/groupbuy/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
return true;
}
return false;
} catch (err) {
return false;
}
}
<template>
<likeGood :page-type="4" :is-show="isShow">
<view class="card">
<view class="info">
<image class="info__image" src="https://img.lkbang.net/xcx/pay-success.png" />
<view class="info__desc">
<text class="info__text">订单支付成功!</text>
<text class="info__text info__money">实付¥{{ money }}</text>
<text v-if="freeAmount > 0" class="info__text info__free">已优惠¥{{ freeAmount }}</text>
</view>
</view>
<!-- **会员权益2.0版本去掉了** -->
<!-- <view class="tips">
<text>您可在“我的-我的订单”中查看详情</text>
</view> -->
<view v-if="$config('yxm') && eventPoint" class="growth">
<view class="growth__leftdesc">
<!-- <image class="growth__image" src="https://img.lkbang.net/xcx/growth.png" /> -->
<image class="growth__image" :src="icon" />
<text class="growth__growtext">{{ text }}</text>
</view>
<view class="growth__rightdesc">
<text class="growth__text growth__color">+{{ eventPoint }}</text>
<text class="growth__text">成长值</text>
</view>
</view>
<view class="actions">
<button
class="actions__back"
plain="true"
hover-class="none"
type="primary"
@click="goHome"
>
返回首页
</button>
<button
class="actions__order"
plain="true"
hover-class="none"
type="primary"
@click="setSubMsg"
>
查看订单
</button>
</view>
</view>
<couponSwiper :coupon-list="couponList" />
<!-- #ifdef MP-WEIXIN -->
<view v-if="showDivert && guideUrl" class="priv-divert" @click="navToDivert">
<image class="priv-divert-img" :src="guideUrl" mode="widthFix" />
</view>
<!-- #endif -->
<popCard
v-if="isShow"
:denomination="denomination"
:limit-desc="limitDesc"
:card-valid-period="cardValidPeriod"
class="pop"
@closePopCard="closePopCard"
/>
<tougdunCanvas />
</likeGood>
</template>
<script>
import { guideStream } from "@/api/pay.api.js";
import likeGood from "@/components/likeGood";
import popCard from "./components/popCard.vue";
import { payTypeMap } from "./STATIC_DATA";
import couponSwiper from "./components/couponSwiper";
import { saTrackEvent } from "@/utils/sa";
import { h5Mixin } from "@/utils/h5Mixin";
import { getVaildTmplIds, submitSubcribeInfo, getAcceptList } from "@/utils/subscribe";
import { getVaildSubTmplIds } from "@/api/home.api";
import tougdunCanvas from "@/components/tougdunCanvas.vue";
import cfg from "@/config/index";
import { smTrackEvent } from "@/utils/shumei";
const tmplIds = [
cfg.SUB_MSG_LIST.SELLER_SHIP,
cfg.SUB_MSG_LIST.ORDER_RECEIPT,
cfg.SUB_MSG_LIST.COUPON_RECEIPT
];
let vaildTmplIds = [];
export default {
components: {
likeGood,
couponSwiper,
popCard,
tougdunCanvas
},
mixins: [h5Mixin()],
data() {
return {
guideUrl: "",
jumpUrl: "",
couponList: [],
money: "00.00",
orderNo: null,
freeAmount: null,
list: {},
showDivert: false,
isShow: false,
denomination: "",
limitDesc: null,
cardValidPeriod: null,
eventPoint: null,
text: "",
icon: ""
};
},
async onLoad({ amount, orderNo, freeAmount, payType }) {
this.showDivert = uni.getStorageSync("tenantId") == 560761 ? true : false; // 羊小咩租户展示私域导流入口
console.log({ amount, orderNo, freeAmount, payType });
smTrackEvent({
eventId: "finishOrder",
orderId: orderNo,
orderResult: "2",
passThrough: {
payErrorReason: ""
}
});
this.money = amount;
this.orderNo = orderNo;
this.freeAmount = freeAmount;
console.log(this.isShow, "11111");
this.list = {
payType: payType,
paySuccess: true,
orderNo: this.orderNo
};
const [data, err] = await guideStream(this.list);
if (!err) {
if (data.cardInfo) {
this.denomination = data.cardInfo.denomination;
this.limitDesc = data.cardInfo.limitDesc;
this.cardValidPeriod = data.cardInfo.cardValidPeriod;
}
/* #ifdef MP-WEIXIN */
data.guideList.forEach(item => {
if (item.type === 1) {
this.guideUrl = item.image;
this.jumpUrl = item.jumpUrl || "";
}
});
/* #endif */
this.eventPoint = data?.eventPointInfo?.eventPoint;
this.icon = data?.eventPointInfo?.icon;
this.text = data?.eventPointInfo?.text;
this.couponList = data?.couponList;
this.isShow = !!(this.denomination && this.limitDesc && this.cardValidPeriod);
this.$ry?.payment(orderNo, amount, "CNY", payTypeMap[payType]);
// #ifdef MP-WEIXIN
vaildTmplIds = await getVaildSubTmplIds(tmplIds);
// #endif
}
},
methods: {
goHome() {
uni.switchTab({
url: "/pages/index/index"
});
},
closePopCard() {
this.isShow = false;
},
setSubMsg() {
if (!this.$config("yxm")) {
this.goOrderDetail();
return;
}
// #ifdef MP-WEIXIN
// 非羊小咩不触发订阅消息
if (!vaildTmplIds.length) return;
wx.requestSubscribeMessage({
tmplIds: vaildTmplIds,
success: res => {
this.submitInfo(res);
this.goOrderDetail();
const vaildIds = getVaildTmplIds(res);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "点击支付成功页查看订单",
check_content: vaildIds,
buttons_name: "允许"
});
},
fail: err => {
console.error("requestSubscribeMessage", err);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "点击支付成功页查看订单",
check_content: "商家发货通知,优惠券到账通知,优惠券过期通知",
buttons_name: "取消"
});
this.goOrderDetail();
}
});
// #endif
/* #ifndef MP-WEIXIN */
this.goOrderDetail();
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "点击支付成功页查看订单",
check_content: [],
buttons_name: "允许"
});
/* #endif */
},
submitInfo(res) {
const acceptList = getAcceptList(res);
submitSubcribeInfo(acceptList);
},
goOrderDetail() {
saTrackEvent("PD_YXMMAEC_UserClickCashierCheckOrderBtn", {
order_id: this.orderNo
});
uni.reportAnalytics("c_cashiercheckorderbtn", {
order_id: this.orderNo
});
uni.redirectTo({
url: `/pages/order/orderList?state=0`
});
// uni.redirectTo({
// url: `/pages/order/orderDetail?orderNo=${this.orderNo}`
// });
},
navToDivert() {
const activityType = this.jumpUrl.split("activityType=")[1];
uni.navigateTo({
url: `/pages/activity/divertPrivDomain?activityType=${activityType}`
});
}
}
};
</script>
<style lang="scss" scoped>
.card {
margin: $uni-spacing-col-md;
background-color: white;
border-radius: $uni-border-radius-lg;
padding: 56rpx $uni-spacing-row-base $uni-spacing-row-base $uni-spacing-row-base;
.info {
display: flex;
justify-content: center;
align-items: center;
&__image {
width: 100px;
height: 100px;
}
&__text {
margin-left: $uni-spacing-row-lg;
font-size: $font-lg;
}
&__desc {
display: flex;
flex-direction: column;
}
&__money {
margin-top: $uni-spacing-col-base;
}
&__free {
color: $font-color-light;
font-size: $font-md;
margin-top: $uni-spacing-col-base;
}
}
// .tips {
// margin-top: $uni-spacing-col-lg;
// text-align: center;
// font-size: $font-sm;
// color: $font-color-light;
// }
.growth {
display: flex;
width: 654rpx;
height: 88rpx;
background-color: #fffbf2;
align-items: center;
justify-content: space-between;
margin-top: 18rpx;
border-radius: 16rpx;
&__image {
width: 43px;
height: 54px;
opacity: 0.5;
}
&__growtext {
color: #282828;
font-size: $font-sm;
position: absolute;
top: 10rpx;
left: calc((100% - 232rpx) / 2 + 40rpx);
}
&__text {
// margin-left: $uni-spacing-row-lg;
color: #282828;
font-size: $font-sm;
}
&__color {
color: #ffa130;
margin-right: 10rpx;
}
&__leftdesc {
width: 344rpx;
height: 50rpx;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
&__rightdesc {
margin: 22rpx 20rpx 26rpx 0;
}
}
.actions {
display: flex;
flex-direction: row;
margin-top: 42rpx;
&__back {
border: 1px solid $uni-text-color-grey;
color: $uni-text-color-grey;
}
&__order {
margin-left: $uni-spacing-row-base;
color: #ec1500;
border: 1px solid #ec1500;
}
button {
flex: 1;
border-radius: $uni-border-radius-xl;
font-size: $line-height-md;
}
}
}
.priv-divert {
padding: 0 20rpx;
margin-bottom: 10rpx;
&-img {
border-radius: 16rpx;
overflow: hidden;
width: 100%;
}
}
// .mark {
// position: absolute;
// height: 100%;
// color: #fff;
// background: rgba(0, 0, 0, 0.5);
// left: 0%;
// right: 0%;
// font-size: 26rpx;
// text-align: center;
// box-shadow: 2px -3px 100px -5px #ffffff;
// z-index: 99;
// }
/* .pop {
position: fixed;
top: 260rpx;
left: 39rpx;
z-index: 999;
} */
</style>
<template>
<view class="noneStock">
抱歉,当前商品无库存,可查看相似商品
</view>
</template>
<style lang="scss" scoped>
@import "@/style/var.scss";
.noneStock {
position: fixed;
bottom: calc(env(safe-area-inset-bottom) + 150rpx);
width: 100%;
padding: 20rpx;
background: $pink;
color: $red;
@include text-size(28);
}
</style>
@mixin button() {
position: fixed;
left: 40rpx;
right: 40rpx;
bottom: 0;
padding: $padding-md 0;
display: flex;
justify-content: space-between;
align-items: center;
button {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 80rpx;
font-size: $font-base;
font-weight: bold;
border-radius: $border-radius-2;
&:first-child {
border: $border-sm solid $border-red;
background: $bg-color;
color: $font-color-search;
}
&:last-child {
color: $white;
background-image: $background-primary;
}
}
}
.btnGroup {
position: absolute;
bottom: 0rpx;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
width: 93%;
button {
width: 48%;
height: 80rpx;
font-size: $font-base;
font-weight: bold;
border-radius: $border-radius-2;
&.goods-bottom-buy{
color: $white;
background-image: $background-primary;
&.disabled{
opacity: 0.7;
}
}
&.goods-bottom-car {
border: $border-sm solid $border-color-search;
background: $white;
color: $font-color-search;
}
&.goods-bottom-confirm{
width: 95%;
color: $white;
background-image: $background-primary;
&.disabled{
opacity: 0.7;
}
}
}
}
.goods {
height: 100vh;
padding-bottom: calc(150rpx + env(safe-area-inset-bottom));
box-sizing: border-box;
&-container {
height: calc(100% - 60px);
// height: 800rpx;
&-lose {
&-container {
background: #fff;
padding: 90rpx 30rpx;
text-align: center;
image {
width: 300rpx;
}
}
}
}
&-wrapper {
padding-bottom: 70rpx;
}
&-carousel {
position: relative;
width: 100%;
height: 750rpx;
swiper{
height: 100%;
&-item {
width: 100%;
height: 100%;
image {
width: 100%;
height: 100%;
}
}
}
&-dots {
position: absolute;
right: 30rpx;
bottom: 20rpx;
line-height: $line-height-md;
text-align: center;
width: 60rpx;
height: 34rpx;
background: rgba(0, 0, 0, 0.4);
border-radius: $border-radius-3;
font-size: $font-sm;
color: $white;
}
}
&-info {
padding: 0 30rpx;
&.activity {
width: 100%;
padding: 0;
.goods-info-max{
padding: 0 30rpx;
}
}
background: $white;
margin-bottom: $margin-base;
&-price {
position: relative;
.new-user-price-info{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
.new-user-price{
flex: 1;
flex-shrink: 0;
height: 100%;
display: flex;
align-items: flex-end;
padding-bottom: 22rpx;
padding-left: 24rpx;
&-sale{
// margin-right: 16rpx;
color: $white;
.desc{
opacity: 0.8;
font-size: 22rpx;
margin-bottom: 8rpx;
}
.info{
display: flex;
align-items: baseline;
.symbol{
font-size: 26rpx;
}
.num{
line-height: 60rpx;
font-size: 60rpx;
padding-right: 16rpx;
}
}
}
&-market{
display: flex;
align-items: baseline;
color: $white;
.desc{
opacity: 0.8;
font-size: 22rpx;
margin-right: 8rpx;
}
.symbol{
opacity: 0.95;
font-weight: 500;
font-size: 24rpx;
}
.num{
opacity: 0.95;
line-height: 36rpx;
font-size: 36rpx;
font-weight: 500;
}
}
}
.new-user-limit-count{
width: 300rpx;
padding-left: 24rpx;
flex-shrink: 0;
height: 100%;
display: flex;
align-items: flex-end;
&-content{
text-align: center;
width: 100%;
height: 40%;
opacity: 0.8;
font-size: 24rpx;
color: #FE1132;
}
}
}
&.activity {
padding: 0;
}
padding: $padding-sm 0;
display: flex;
justify-content: space-between;
align-items: center;
min-height: 105rpx;
.Gi-price-noactivity {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
.Gi-price-activity {
width: 100%;
position: relative;
image {
width: 100%;
height: 100rpx;
}
&-price {
position: absolute;
left: 100rpx;
top: 20rpx;
text {
color: #fff;
&:nth-child(1) {
font-size: $font-lg;
line-height: 44rpx;
font-weight: bold;
}
&:nth-child(2) {
margin-right: $margin-sm;
font-size: $font-1;
font-weight: bold;
}
&:nth-child(3) {
text-decoration: line-through;
font-size: $font-base;
line-height: 40rpx;
color: #fff;
}
}
}
}
.Gi-price-left {
text {
color: $font-color-red;
&:nth-child(1) {
font-size: $font-lg;
line-height: 44rpx;
font-weight: bold;
}
&:nth-child(2) {
margin-right: $margin-sm;
font-size: $font-1;
font-weight: bold;
}
&:nth-child(3) {
text-decoration: line-through;
font-size: $font-base;
line-height: 40rpx;
color: $text-color-n1;
}
}
}
.Gi-price-right {
bottom: 0;
font-size: $font-md;
line-height: 36rpx;
color: $text-color-n1;
}
.Gi-price-maxactivity{
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
// padding: 0 30rpx;
.iconfont{
margin-left: 16rpx;
color: $bg-color-gray;
}
}
// max会员
.Gi-price-maxprice{
color: #33374B !important;
text-decoration: none !important;
font-size: $font-lg !important;
margin-right: 8rpx;
}
// .Gi-price-maxImage{
// width: 88rpx !important;
// height: 24rpx !important;
// }
}
&-name {
font-size: $font-base;
line-height: 44rpx;
color: $text-color-n5;
font-weight: bold;
padding-bottom: 14rpx;
&.activity {
padding: 0 30rpx ;
margin-bottom: $padding-md;
}
}
&-max{
&-img{
width: 100%;
height: auto;
}
padding-bottom: 14rpx;
}
&-subtitle {
padding: 0 30rpx 0;
box-sizing: border-box;
margin-bottom: 16rpx;
&-activity {
// padding-bottom: 20rpx;
font-size: 12px;
color: #999;
&-subfix {
margin-left: 2rpx;
font-size: 12px;
color: #ec1500;
cursor: pointer;
}
}
&-notice {
margin-bottom: 16rpx;
font-size: 12px;
color: #333;
}
}
}
&-activity {
// padding: 20rpx;
padding: 0 35rpx;
background: $white;
margin-bottom: 20rpx;
.activity-info{
display: flex;
align-items: center;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
height: 38rpx;
.content{
width: 100%;
height: 100%;
display: flex;
align-items: center;
.newComersIcon{
margin-right: 8rpx;
height: 26rpx;
width: auto;
}
.newComersLabel{
flex: 1;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
}
}
// padding-left: 11rpx;
&-button {
// box-sizing: content-box;
// margin-right: 10rpx;
min-width: 60rpx;
height: 32rpx;
border-radius: 6rpx;
line-height: 30rpx;
text-align: center;
border: $border-sm solid $border-color-search;
// font-size: $font-sm;
font-size: 22rpx;
color: $font-color-search;
margin-right: 15rpx;
}
&-content {
overflow: hidden;
text-overflow: ellipsis;
display:-webkit-box;
-webkit-line-clamp:2;
-webkit-box-orient:vertical;
}
}
&-sale {
// padding: 20rpx;
padding: 0 35rpx;
background: $white;
margin-bottom: 20rpx;
// padding-left: 11rpx;
&-button {
box-sizing: content-box;
margin-right: 10rpx;
width: 70rpx;
height: 30rpx;
border-radius: 6rpx;
line-height: 30rpx;
text-align: center;
border: $border-sm solid $border-color-search;
font-size: $font-sm;
color: $font-color-search;
}
&-content {
width: 518rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: $font-md;
line-height: 36rpx;
color: $text-color-n5;
}
&-contents {
width: 518rpx;
overflow: hidden;
text-overflow: ellipsis;
// white-space: nowrap;
margin-right: 4rpx;
font-size: $font-md;
line-height: 36rpx;
color: $text-color-n5;
}
}
&-param {
padding: 0 35rpx;
background: $white;
&-text {
max-width:450rpx;
overflow: hidden;
text-overflow: ellipsis;
display:-webkit-box;
-webkit-line-clamp:1;
-webkit-box-orient:vertical;
}
&-area {
text {
overflow: hidden;
text-overflow: ellipsis;
display:-webkit-box;
-webkit-line-clamp:1;
-webkit-box-orient:vertical;
&:nth-child(1) {
font-size: $font-base;
margin-left: -4rpx;
margin-right: 10rpx;
color: $font-color-search;
width: 36rpx;
}
&.noAddr {
color: $text-color-n1;
}
}
}
&-service {
text {
&:after {
// display: inline-block;
margin: 0 10rpx;
content: '';
// border-right: 2rpx solid #EBEBEB;
height: 22rpx;
vertical-align: middle;
}
&:last-child {
&:after {
height: 0;
}
}
}
}
}
&-divider {
display:flex;
align-items:center;
justify-content: center;
margin: 30rpx 0;
width: 100%;
font-size: $font-sm;
color: $text-color-n1;
text-align: center;
&:before, &:after{
display: inline-block;
content: '';
width: 100rpx;
height: 0;
border-top: 2rpx solid #D8D8D8;
margin-right: 10rpx;
}
&:after{
margin-left: 10rpx;
margin-right: 0;
}
}
&-list {
// background: #D8D8D8;
padding: 0rpx 30rpx;
overflow: hidden;
}
&-popup {
position: relative;
padding: 32rpx;
&-selected{
display: flex;
align-items: flex-end;
margin-bottom: 60rpx;
image{
width: 200rpx;
height: 200rpx;
border-radius: 8rpx;;
}
.Gp-selected-right{
display: flex;
flex-direction: column;
padding-left: 20rpx;
.Gps-right-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.Gpsr-header-price{
margin-right: 10rpx;
text {
color: $font-color-red;
font-weight: bold;
&:first-child {
font-size: $font-sm;
}
&:last-child {
font-size: 36rpx;
}
}
}
.Gpsr-header-discount {
font-size: $font-sm;
color: $text-color-n1;
text {
&:last-child {
text-decoration: line-through; }
}
}
}
.Gps-right-selected {
font-size: $font-md;
color: $text-color-n5;
}
}
}
&-param{
display: flex;
flex-direction: column;
margin-bottom: 40rpx;
.Gp-param-name {
margin-bottom: 20rpx;
font-size: $font-md;
color: #A3A3A3;
}
.Gp-param-list{
padding: 20upx 0 0;
display: flex;
flex-wrap: wrap;
text{
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
padding: 0 30rpx;
background: #F7F7F7;
border-radius: 6rpx;
height: 52rpx;
font-size: $font-md;
color: $text-color-n5;
margin-bottom: 25rpx;
}
.Gpp-list-selected{
border: $border-sm solid $border-color-search;
font-size: $font-md;
background: $bg-color-pink;
color: $font-color-search;
}
.Gpp-list-disabled {
border: $border-sm solid $font-color-disabled;
font-size: $font-md;
background: #F7F7F7;
color: $font-color-disabled;
}
}
}
&-num {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 300rpx;
position: relative;
&-limit {
position: absolute;
right: 0;
top: 55rpx;
font-size: 27rpx;
color: #EE0A24;
width: 180rpx;
text-align: right;
}
.Gp-num-name {
font-size: $font-md;
color: $font-color-dark;
&-limit{
font-size: $font-sm;
color: $font-color-light;
}
}
}
&-button {
position: fixed;
left: 40rpx;
right: 40rpx;
bottom: 0;
padding: 20rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
button {
display: flex;
justify-content: center;
align-items: center;
width: 324rpx;
height: 80rpx;
font-size: $font-base;
font-weight: bold;
border-radius: $border-radius-2;
&:first-child {
border: $border-sm solid $border-color-search;
background: $white;
color: $font-color-search;
}
&:last-child {
color: $white;
background-image: $background-primary;
}
}
}
}
&-area {
height: 65vh;
overflow: scroll;
padding: 32rpx;
&-item {
display: flex;
align-items: flex-start;
margin-bottom: $margin-lg;
text {
font-size: $font-md;
color: $text-color-n1;
&:first-child {
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
font-size: $font-lg;
}
&:second-child {
flex: 1;
}
}
&_selected {
text {
&:first-child {
color: $font-color-search;
// color: #e4e;
}
&.secondText {
color: $font-color-dark;
}
}
}
}
&-none {
display: inline-block;
width: 100%;
line-height: 55vh;
font-size: $font-lg;
color: $text-color-n5;
text-align: center;
}
&-button {
@include button;
}
}
&-service {
height: 65vh;
overflow: scroll;
padding: 32rpx;
&-item {
display: flex;
align-items: flex-start;
margin-bottom: $margin-1;
image {
margin: 4rpx $margin-sm 0 0;
width: 28rpx;
height: 28rpx;
}
.Gs-item-right {
flex: 1;
display: flex;
flex-direction: column;
text {
line-height: 36rpx;
&:first-child {
margin-bottom: $margin-sm;
font-size: $font-md;
color: $text-color-n4;
}
&:last-child {
font-size: $font-md;
color: $text-color-n6;
}
}
}
}
&-max{
overflow-y: scroll;
height: 400rpx;
&:first-child{
padding: 0 44rpx;
}
text{
color: $font-color-dark;
font-size: $font-md;
white-space: pre-wrap;
}
}
&-button {
@include button;
}
}
&-buoy {
position: fixed;
right: 20rpx;
display: flex;
align-items: center;
justify-content: center;
width: 80rpx;
height: 80rpx;
background: #fff;
border-radius: 50rpx;
border: 1rpx solid #EBEBEB;
// box-shadow: rgba(0, 0, 0, 0.4);
}
&-share {
bottom: 325rpx;
// position: absolute;
image {
width: 90rpx;
height: 90rpx;
position: absolute;
&::after {
border: none;
}
}
button {
width: 100%;
border: none;
background: transparent;
display: flex;
justify-content: center;
position: relative;
z-index: 10;
&::after {
border: none;
}
}
}
&-like {
bottom: 430rpx;
image {
width: 90rpx;
height: 90rpx;
position: absolute;
&::after {
border: none;
}
}
}
}
.memberImg {
width: 132.68rpx;
// height: 28rpx;
}
// .goods-info-price .Gi-price-activity image.memberImg {
// width: 132.68rpx;
// height: 28rpx;
// }
.price-wrap {
padding: 12px 12px 18px 12px;
color: #333;
line-height: 1.6;
background: #fff;
border-radius: 8px;
margin: 10px;
font-size: 13px;
}
.price-wrap h3 {
margin-bottom: 12px;
font-size: 16px;
font-weight: bold;
}
.price-wrap .title {
margin: 12px 0 10px 0;
font-size: 13px;
display: block;
position: relative;
color: #333;
font-weight: bold;
}
.price-wrap .title::after {
content: '';
display: block;
width: 2px;
height: 2px;
position: absolute;
left: -8px;
top: 9px;
background: #333;
}
.price-content {
color: #666;
}
.price-content text {
display: block;
font-size: 13px;
color: #333;
}
.price-wrap ul {
padding: 0;
}
.price-wrap li {
margin-left: 8px;
}
\ No newline at end of file
import { createNamespacedHelpers } from 'vuex';
const { mapState, mapActions, mapGetters, mapMutations } = createNamespacedHelpers('shopCart');
export { mapState, mapActions, mapGetters, mapMutations };
<template>
<div class="gift-container">
<div class="gift-button">
<div class="gift-button-left" @click="handleToPage('/pages/giftCardList/index')">
<view class="gift-button-title">礼品卡余额</view>
<view class="gift-button-price">
<text class="price-lg">{{ formatPrice(giftInfo.cardAmount)[0] }}.</text>
<text class="price-sm">{{ formatPrice(giftInfo.cardAmount)[1] }}</text>
</view>
</div>
<div class="gift-button-right" @click="handleToPage('/pages/coupon/index')">
<view class="gift-button-title">优惠劵</view>
<view class="gift-button-price">
<text class="price-lg">{{ giftInfo.couponCount || 0 }} </text>
<text class="price-sm"></text>
</view>
</div>
</div>
</div>
</template>
<script>
const NAV_TO = "nav-to";
export default {
props: {
giftInfo: {
type: Object,
default: () => ({})
}
},
methods: {
handleToPage(url) {
this.$emit(NAV_TO, url);
},
formatPrice(balance) {
let price = !isNaN(balance) ? +balance : 0;
return price.toFixed(2).split(".");
}
}
};
</script>
<style lang="scss" scoped>
.gift-container {
/* margin-top: 24rpx; */
transform: translateY(24rpx);
}
.gift-button {
position: relative;
color: $white;
height: 108rpx;
text-align: center;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 24rpx;
&::after {
position: absolute;
content: "";
width: 100%;
height: 100%;
opacity: 0.26;
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0%,
#ffffff 18%,
#ffffff 46%,
#ffffff 72%,
rgba(255, 255, 255, 0) 100%
);
}
&-left {
position: relative;
&::after {
content: "";
width: 1px;
height: 36rpx;
position: absolute;
top: 30%;
right: 0;
background-color: $white;
opacity: 0.2;
}
}
&-left,
&-right {
flex: 1;
position: relative;
z-index: 1;
}
&-price {
font-weight: bold;
.price-lg {
font-size: $uni-font-size-lg;
}
.price-sm {
font-size: $uni-font-size-sm;
}
}
}
</style>
<template>
<view v-if="!showMaxMember" class="member-container">
<view v-if="normalMember" class="member-box" :class="{ normalMemeber: !showMaxMember }">
<view class="benefits" @click="navigateUrl(3)">
<view class="content">
<view v-for="(item, index) in memberInfo.benefitsList" :key="index" class="item">
<view class="icon" :style="{ backgroundImage: `url(${item.levelSignPic})` }" />
<view class="text">{{ item.desc }}</view>
</view>
</view>
</view>
<view class="line" />
<view class="statistics" @click="navigateUrl(4)">
<view class="desc">累积权益已省</view>
<view class="info">
<text class="number">{{ memberInfo.saveMoney || 0 }}</text>
<text class="unit"></text>
</view>
</view>
</view>
</view>
<view v-else class="member-container">
<view class="max-member-box">
<view
class="max-member-box-scroll-view"
:class="swipeClass"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
>
<!-- <view style="padding: 0 30rpx; display: flex;"> -->
<view
v-if="maxMember"
id="max-member"
class="max-member"
:style="{
backgroundImage: `url(${maxMemberInfo.imgUrl})`
}"
@click="toMaxMember(maxMemberInfo.jumpUrl, maxMemberInfo.status)"
>
<view v-if="maxMemberInfo.status && maxMemberInfo.status == 3" class="time">{{
maxMemberInfo.expireTime
}}</view>
<view v-if="maxMemberInfo.text" class="textSlide">
<view class="slideContent">
<swiper class="textSwiper" vertical autoplay circular interval="5000">
<swiper-item v-for="(item, index) in maxMemberInfo.text" :key="index">
<view class="textContent">{{ item }}</view>
</swiper-item>
</swiper>
</view>
</view>
</view>
<view v-if="normalMember" id="normal-member" class="member-box member-box-in-max">
<view
class="benefits"
style="-webkit-overflow-scrolling: touch;"
@click.stop="navigateUrl(3)"
>
<view class="content">
<swiper style="width: 100%; height: 120rpx;">
<swiper-item
v-for="(item, index) in memberInfo.benefitsList"
:key="index"
class="item inSwiper"
>
<view class="icon" :style="{ backgroundImage: `url(${item.levelSignPic})` }" />
<view class="text">{{ item.desc }}</view>
</swiper-item>
</swiper>
</view>
</view>
<view class="line" />
<view class="statistics in-max" @click="navigateUrl(4)">
<view class="desc">累积权益已省</view>
<view class="info">
<text class="number in-max">{{ memberInfo.saveMoney || 0 }}</text>
<text class="unit"></text>
</view>
</view>
</view>
<!-- </view> -->
</view>
</view>
</view>
</template>
<script>
import { jumpToUrl } from "@/mixins/common";
import { saTrackEvent } from "@/utils/sa.js";
export default {
props: {
showMaxMember: {
type: Boolean,
default: false
},
userInfo: {
type: Object,
default: () => {}
},
memberInfo: {
type: Object,
default: () => {}
},
maxMemberInfo: {
type: Object,
default: () => {}
}
},
data() {
return {
touchStart: [0, 0],
touchEnd: [0, 0],
swipeClass: ""
};
},
computed: {
normalMember() {
return this.$config("yxm") && this.userInfo.hasLogin && Object.keys(this.memberInfo).length;
},
maxMember() {
return (
this.$config("yxm") && this.userInfo.hasLogin && Object.keys(this.maxMemberInfo).length
);
}
},
methods: {
touchstart(e) {
let x = e.touches[0].pageX;
let y = e.touches[0].pageY;
this.touchStart = [x, y];
},
touchmove(e) {
let x = e.touches[0].pageX;
let y = e.touches[0].pageY;
this.touchEnd = [x, y];
},
touchend() {
let start = this.touchStart;
let end = this.touchEnd;
if (start[0] < end[0] - 20) {
console.log("向右滑了");
this.swipeClass = "swipeLeft";
this.$emit("changeBg", "maxMember");
} else if (start[0] > end[0] + 20) {
console.log("向左滑了");
this.swipeClass = "swipeRight";
this.$emit("changeBg", "normal");
} else {
console.log("滑动太短 不做处理");
}
},
navigateUrl(type) {
this.$emit("navigateUrl", type);
},
toMaxMember(url, status) {
saTrackEvent("MINI_MaxMemberEntryBtnClick", {
entry_btn_status: status,
page_name: "我的页面",
commodity_id: ""
});
jumpToUrl(url);
}
}
};
</script>
<style scoped lang="scss">
.max-member-box-scroll-view {
position: absolute;
left: 30rpx;
top: 0;
display: flex;
transition: left 0.5s;
&.swiperLeft {
left: 30rpx;
}
&.swipeRight {
left: -420rpx;
}
}
.member-container {
margin-top: -210rpx;
position: relative;
}
.max-member-box {
position: relative;
width: 100vw;
height: 176rpx;
background-size: cover;
margin-bottom: 24rpx;
overflow: hidden;
}
.max-member {
margin-right: 20rpx;
flex-shrink: 0;
width: 560rpx;
height: 176rpx;
background-size: 100%;
background-repeat: no-repeat;
position: relative;
.time {
position: absolute;
right: 24rpx;
top: 40rpx;
font-size: 20rpx;
color: #788aff;
letter-spacing: -0.29px;
}
.textSlide {
width: 350rpx;
display: flex;
height: 40rpx;
// background: rgba(10, 66, 253, 0.2);
position: absolute;
bottom: 10rpx;
left: 190rpx;
padding: 0 12rpx;
border-radius: 20rpx;
font-size: 24rpx;
display: flex;
align-items: center;
.desc {
color: #ffdcae;
padding-right: 18rpx;
}
.slideContent {
width: 100%;
height: 40rpx;
.textSwiper {
width: 100%;
height: 100%;
.textContent {
line-height: 44rpx;
display: flex;
width: 100%;
flex-wrap: nowrap;
align-items: center;
color: $white;
height: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
}
}
}
}
.member-box {
width: 690rpx;
height: 176rpx;
background-image: url("http://img.lkbang.net/maxMember/20220413/normal-1.png");
background-repeat: no-repeat;
background-size: 100% 100%;
margin-bottom: 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
&.normalMemeber {
margin: 0 auto 24rpx;
}
&-in-max {
width: 560rpx;
background-image: url("http://img.lkbang.net/maxMember/20220413/normal-2.png");
}
.line {
width: 0;
height: 90rpx;
border-right: 1px dashed #773e1d;
opacity: 0.59;
}
.benefits {
padding: 0 20rpx;
width: 384rpx;
height: 120rpx;
overflow: hidden;
.content {
width: 100%;
height: 146rpx;
padding-bottom: 20rpx;
display: flex;
// justify-content: center;
align-items: center;
overflow-x: auto;
.item {
width: 50% !important;
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: center;
padding: 0 10rpx;
&.inSwiper {
height: 120rpx !important;
}
.icon {
background-size: cover;
width: 72rpx;
height: 72rpx;
margin-bottom: 4rpx;
}
.text {
text-align: center;
width: 100%;
font-size: 24rpx;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
// background: #000;
}
.statistics {
width: 296rpx;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&.in-max {
width: 206rpx;
}
// opacity: 0.43;
.desc {
font-size: 24rpx;
color: #773e1d;
margin-bottom: 8rpx;
}
.info {
display: flex;
align-items: baseline;
font-weight: 600;
color: #cd4b00;
.number {
line-height: 52rpx;
font-size: 52rpx;
&.in-max {
font-size: 36rpx;
line-height: 36rpx;
}
}
.unit {
line-height: 24rpx;
font-size: 24rpx;
}
}
}
}
</style>
<template name="skeleton">
<view class="sk-container">
<view class="container">
<view class="user-section">
<image class="bg sk-image" />
<view class="user-info-box">
<view class="user-info" data-event-opts="tap,loginPopupFn">
<view class="portrait-box">
<image class="portrait sk-image" />
</view>
<view class="info-box">
<view class="username">
<view class="sk-transparent sk-text-14-2857-897 sk-text">176</view>
<view class="middle sk-transparent sk-text-14-2857-993 sk-text">****</view>
<view class="sk-transparent sk-text-14-2857-413 sk-text">8468</view>
</view>
</view>
</view>
<view class="user-config" data-event-opts="tap,navTo,/subPackages/common/set/set">
<image class="config sk-image" />
</view>
</view>
</view>
<view class="cover-container">
<view class="main-list">
<view class="card-box card-box-top">
<view class="card-title" style="border: none;">
<text class="sk-transparent sk-text-33-3333-534 sk-text">我的订单</text>
<view class="card-info sk-transparent" />
</view>
<view class="card-main">
<view class="order-section">
<view class="order-item">
<image class="paid-order sk-image" />
<text class="sk-transparent sk-text-14-2857-804 sk-text">待付款</text>
</view>
<view class="order-item">
<image class="goods-order sk-image" />
<text class="sk-transparent sk-text-14-2857-866 sk-text">待收货</text>
</view>
<view class="order-item">
<image class="completed-order sk-image" />
<text class="sk-transparent sk-text-14-2857-785 sk-text">已完成</text>
</view>
<view class="order-item">
<image class="service-order sk-image" />
<text class="sk-transparent sk-text-14-2857-290 sk-text">退款/售后</text>
</view>
</view>
</view>
</view>
<view class="card-box">
<view class="card-title" style="border: none;">
<text class="sk-transparent sk-text-33-3333-510 sk-text">综合应用服务</text>
</view>
<view class="card-main">
<view class="order-section">
<view class="order-item">
<image class="paid-order sk-image" />
<text class="sk-transparent sk-text-14-2857-282 sk-text">关注微信</text>
</view>
<view class="order-item">
<image class="goods-order sk-image" />
<text class="sk-transparent sk-text-14-2857-405 sk-text">在线客服</text>
</view>
<view class="order-item">
<image class="completed-order sk-image" />
<text class="sk-transparent sk-text-14-2857-287 sk-text">我的地址</text>
</view>
<view class="order-item">
<text />
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.sk-transparent {
color: transparent !important;
}
.sk-text-14-2857-897 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 47.6rpx;
position: relative !important;
}
.sk-text {
background-origin: content-box !important;
background-clip: content-box !important;
background-color: transparent !important;
color: transparent !important;
background-repeat: repeat-y !important;
}
.sk-text-14-2857-993 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 47.6rpx;
position: relative !important;
}
.sk-text-14-2857-413 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 47.6rpx;
position: relative !important;
}
.sk-text-33-3333-534 {
background-image: linear-gradient(
transparent 33.3333%,
#eeeeee 0%,
#eeeeee 66.6667%,
transparent 0%
) !important;
background-size: 100% 84rpx;
position: relative !important;
}
.sk-text-14-2857-804 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 33.6rpx;
position: relative !important;
}
.sk-text-14-2857-866 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 33.6rpx;
position: relative !important;
}
.sk-text-14-2857-785 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 33.6rpx;
position: relative !important;
}
.sk-text-14-2857-290 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 33.6rpx;
position: relative !important;
}
.sk-text-33-3333-510 {
background-image: linear-gradient(
transparent 33.3333%,
#eeeeee 0%,
#eeeeee 66.6667%,
transparent 0%
) !important;
background-size: 100% 84rpx;
position: relative !important;
}
.sk-text-14-2857-282 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 33.6rpx;
position: relative !important;
}
.sk-text-14-2857-405 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 33.6rpx;
position: relative !important;
}
.sk-text-14-2857-287 {
background-image: linear-gradient(
transparent 14.2857%,
#eeeeee 0%,
#eeeeee 85.7143%,
transparent 0%
) !important;
background-size: 100% 33.6rpx;
position: relative !important;
}
.sk-button {
color: #efefef !important;
background: #efefef !important;
border: none !important;
box-shadow: none !important;
}
.sk-image {
background: #efefef !important;
}
.sk-pseudo::before,
.sk-pseudo::after {
background: #efefef !important;
background-image: none !important;
color: transparent !important;
border-color: transparent !important;
}
.sk-pseudo-rect::before,
.sk-pseudo-rect::after {
border-radius: 0 !important;
}
.sk-pseudo-circle::before,
.sk-pseudo-circle::after {
border-radius: 50% !important;
}
.sk-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: transparent;
}
</style>
<template>
<view class="container">
<view
v-if="$config('yxm')"
class="user-section"
:class="{
unlogin: !userInfo.hasLogin
}"
>
<image
v-show="bgType == 'normal'"
class="bg"
src="https://img.lkbang.net/xcx/user-bg-v1.png"
/>
<!-- #ifdef MP-WEIXIN -->
<image
v-show="bgType == 'maxMember'"
class="bg"
src="https://img.lkbang.net/xcx/user-bg-v2.png"
/>
<!-- #endif -->
<user-info-box
:member-info="memberInfo"
:user-base-info="userBaseInfo"
:user-info="userInfo"
:show-max-member="showMaxMember"
:max-member-icon-url="maxMemberIconUrl"
@nav-to="navTo"
@open-login="loginPopupFn"
/>
</view>
<view v-else class="user-qinghai" :style="{ paddingTop: `${navHeight}px` }">
<view class="user-qinghai-content">
<user-info-box
:user-base-info="userBaseInfo"
:user-info="userInfo"
@nav-to="navTo"
@open-login="loginPopupFn"
/>
<gift-button
v-if="userInfo.hasLogin"
class="user-gift"
:gift-info="giftInfo"
@nav-to="navTo"
/>
</view>
</view>
<!-- 会员中心 只有羊小咩且登录状态下展示-->
<member
v-if="userInfo.hasLogin"
:show-max-member="showMaxMember"
:member-info="memberInfo"
:user-info="userInfo"
:max-member-info="maxMemberInfo"
@navigateUrl="navigateToPage"
@changeBg="changeBg"
/>
<view class="cover-container">
<view
class="main-list"
:class="{ 'main-qinghai': $config('qinghai'), yxm: $config('yxm') && userInfo.hasLogin }"
>
<!-- 青海移动不展示 2021.11.21 -->
<template v-if="xhkInfo.show && $config('yxm')">
<view v-if="xhkOpened" class="card-box xhk-state">
<image class="xhk-icon" src="https://img.lkbang.net/xcx/xhk-icon.png" />
<view v-if="parseInt(xhkInfo.accountStatus) === 4" class="xhk-title">
<view class="xhk-bold">激活享花卡</view>
<text class="display-block"
>已获得消费额度:¥{{ xhkInfo.creditTotalAmount || 0 }}</text
>
<text class="color-gray">激活享花卡,即可使用额度,享最高40天免息</text>
</view>
<view v-else class="xhk-title">
<view class="xhk-bold">开通享花卡</view>
<text>使用享花卡支付,享最高40天免息!</text>
</view>
<button
:class="[xhkBtnState ? '' : 'disabled']"
class="card-xhk-btn btn-position"
@click="handleOpen('xhk-btn-popup')"
>
{{ xhkBtnText }}
</button>
</view>
<view v-else class="card-box">
<view class="card-title">
<text>我的享花卡</text>
<!-- <view class="card-info" @click="open('xhk-popup')">查看卡片信息&nbsp; <text class="cell-right iconfont icon-arrow arrows"></text></view> -->
</view>
<view class="card-main">
<view class="tj-sction">
<view class="tj-item" @click="handleToPayBack">
<text class="num">{{ xhkInfo.canUseAmt }}</text>
<text>可用额度(元)</text>
</view>
<view class="tj-item" @click="handleToPayBack">
<text class="num">{{ xhkInfo.repayAmt }}</text>
<text>待还款(元)</text>
</view>
</view>
<view v-if="!xhkInfo.faced" class="face-recognition">
<view class="face-recognition-txt"
>因您尚未完成活体认证,最高累计可使用<text>200</text>额度</view
>
<button @click="xhkRepayment('appToFace')">
去认证<text class="cell-right iconfont icon-arrow arrows" />
</button>
</view>
</view>
<view class="card-footer">
<view v-if="xhkInfo.overdue" class="xhk-txt" style="color: #ec1500"
>您已逾期,以免造成不良影响请尽快还款!</view
>
<view v-else-if="parseInt(xhkInfo.repayAmt) > 0" class="xhk-txt">{{
xhkInfo.repayDesc
}}</view>
<view v-else class="xhk-txt">使用享花卡支付,享最高40天免息!</view>
<button
v-if="parseInt(xhkInfo.repayAmt) !== 0"
class="card-xhk-btn"
:class="!xhkInfo.overdue && parseInt(xhkInfo.repayAmt) == 0 ? 'disabled' : ''"
@click="handleToPayBack"
>
立即还款
</button>
</view>
</view>
</template>
<!-- 订单 -->
<view class="card-box" :class="[xhkInfo.show ? '' : 'card-box-top']">
<view class="card-title">
<text>我的订单</text>
<view class="card-info" @click="setSubMsg('/pages/order/orderList?state=0')"
>全部订单 &nbsp; <text class="cell-right iconfont icon-arrow arrows"
/></view>
</view>
<view class="card-main">
<view class="order-section">
<view class="order-item" @click="setSubMsg('/pages/order/orderList?state=1')">
<text v-if="paidOrderNum !== 0" class="num">{{ paidOrderNum }}</text>
<image class="paid-order" src="https://img.lkbang.net/xcx/paid-order.png" />
<text>待付款</text>
</view>
<view class="order-item" @click="setSubMsg('/pages/order/orderList?state=3')">
<text v-if="goodsOrderNum !== 0" class="num">{{ goodsOrderNum }}</text>
<image class="goods-order" src="https://img.lkbang.net/xcx/goods-order.png" />
<text>待收货</text>
</view>
<view class="order-item" @click="setSubMsg('/pages/order/orderList?state=4')">
<image
class="completed-order"
src="https://img.lkbang.net/xcx/completed-order.png"
/>
<text>已完成</text>
</view>
<!--青海移动不展示 2021.11.19 -->
<view v-if="$config('yxm')" class="order-item" @click="toRefund">
<image class="service-order" src="https://img.lkbang.net/xcx/service-order.png" />
<text>退款/售后</text>
</view>
</view>
</view>
</view>
<view v-if="$config('yxm')" class="card-box">
<view class="card-main">
<view class="coupon-info">
<view class="coupon-info-item" @click="navigateToPage(1, couponInfo.jumpUrl)">
<view class="detail">
<text class="detail-number">{{
userInfo.hasLogin ? couponInfo.count || 0 : 0
}}</text>
<text class="detail-unit">{{ couponInfo.unit || "张" }}</text>
</view>
<text class="desc">{{ couponInfo.name || "优惠券" }}</text>
</view>
<view class="coupon-info-item" @click="navigateToPage(2, giftCardInfo.jumpUrl)">
<view class="detail">
<template v-if="userInfo.hasLogin">
<template v-if="giftCardInfo.count && giftCardInfo.count.indexOf('.') > -1">
<text class="detail-number">{{ giftCardInfo.count.split(".")[0] }}</text>
<text class="detail-unit">.{{ giftCardInfo.count.split(".")[1] }}</text>
</template>
<template v-else>
<text class="detail-number">0</text>
</template>
</template>
<template v-else>
<text class="detail-number">0</text>
</template>
<text class="detail-unit">{{ giftCardInfo.unit || "元" }}</text>
</view>
<text class="desc">{{ giftCardInfo.name || "礼品卡" }}</text>
</view>
<view
v-if="cardBagInfo.type === 'cardbag'"
class="coupon-info-item"
@click="navigateToPage(5)"
>
<view class="detail">
<view
v-if="cardBagInfo.bubbleView && !cardBagInfo.angleMark && showPoint"
class="point"
/>
<view v-if="cardBagInfo.angleMark" class="text-desc">
{{ cardBagInfo.angleMark }}
</view>
<image style="width: 48rpx; height: 48rpx;" :src="cardBagInfo.icon" />
</view>
<text class="desc">{{ cardBagInfo.name || "我的卡包" }}</text>
</view>
</view>
</view>
</view>
<!-- 提现 -->
<!-- <template v-if="xhkInfo.show">
<view
v-if="(userInfo.nickname || userBaseInfo.nickName) && $config('yxm')"
class="card-box"
:class="[xhkInfo.show ? '' : 'card-box-top']"
>
<view class="card-title">
<text>我的返现</text>
<view class="card-info" @click="xhkRepayment"
>全部返现记录 &nbsp; <text class="cell-right iconfont icon-arrow arrows"
/></view>
</view>
<view class="card-main">
<view class="order-section cash-out">
<view class="cash-out-text">
<image src="https://img.lkbang.net/xcx/gold.png" />
<view class="cash-out-txt">
<view class="cash-out-raise"
>您的可提现金额<text>{{ cashOutRaise || 0 }}</text
>元</view
>
<view class="cash-out-return"
>待返现(元)<text>{{ cashOutReturn || 0 }}</text></view
>
</view>
</view>
<button class="card-xhk-btn" @click="xhkRepayment('cashOutRaise')">
去提现
</button>
</view>
</view>
</view>
</template> -->
<!-- 综合应用服务 -->
<view class="card-box">
<view class="card-title">
<text>综合应用服务</text>
<!-- <view class="card-info">全部订单></view> -->
</view>
<view class="card-main">
<view class="order-section">
<!-- #ifdef MP-WEIXIN -->
<view v-if="$config('yxm')" class="order-item" @click="tip()">
<image class="paid-order" src="https://img.lkbang.net/xcx/weChat.png" />
<text>关注微信</text>
</view>
<!-- #endif -->
<view
class="order-item"
@click="$config('yxm') ? navToCustomer() : callPhone('400-010-0017')"
>
<!-- <view v-if="!authState" class="auth-info__mask" @click.stop="showAuthModal" />
<button
v-if="$config('yxm')"
class="contact-service"
:session-from="sessionFrom"
open-type="contact"
>
联系客服
</button> -->
<image class="goods-order" src="https://img.lkbang.net/xcx/IM.png" />
<text v-if="$config('yxm')">在线客服</text>
<text v-if="$config('qinghai')">电话客服</text>
</view>
<view class="order-item" @click="navTo('/subPackages/common/address/address')">
<image class="completed-order" src="https://img.lkbang.net/xcx/address.png" />
<text>我的地址</text>
</view>
<view class="order-item">
<qa-selector @clear="loginPopupFn" />
</view>
</view>
</view>
<!-- <view class="card-footer">
<text>使用享花卡支付,享最高40天免息!</text>
<button class="card-xhk-btn disabled">立即还款</button>
</view> -->
</view>
</view>
</view>
<login-popup ref="login-popup" type="center" title="用户授权登录" />
<uni-popup ref="xhk-popup" type="center">
<uni-popup-dialog
type="info"
title="我的享花卡"
confirm-txt="知道了"
stay-style
:duration="2000"
hide-cancel-btn
@confirm="confirm"
>
<view class="xhk-popup">
<view>享花卡&上海银行储蓄卡</view>
<view>卡号:{{ xhkInfo.cardNo }}</view>
<view class="declare">本卡仅限于在羊小咩APP或小程序使用</view>
</view>
</uni-popup-dialog>
</uni-popup>
<!--uni-app-->
<uni-popup ref="xhk-btn-popup" type="center">
<uni-popup-dialog
type="info"
content="您可以下载“羊小咩”APP,在APP内完成激活即可享最高40天购物免息!"
:duration="2000"
hide-cancel-btn
@close2="close2"
@confirm="confirm"
/>
</uni-popup>
<tipModal :value="showTip" :type="qrFrom" @change="changeTipStatus" />
<user-info-popup
ref="authPopup"
@auth-state="handleAuthState"
@get-user-info="handleUserInfo"
/>
<!-- <uni-popup ref="order-service" type="center">
<uni-popup-dialog
type="info"
content="您可以下载“羊小咩”APP,在APP内完成订单退款及售后!"
:duration="2000"
hide-cancel-btn
@close2="close2"
@confirm="confirm"
/>
</uni-popup> -->
<skeleton v-if="allLoading" />
<activityModal
v-if="Object.keys(activityModalData).length > 0"
:modal-data="activityModalData"
page-name="我的"
@close="closeActivityModal"
@goto="jumpToWebView(activityModalData)"
/>
</view>
</template>
<script>
const status = ["未申请", "审核中", "审核失败", "已有额度未激活", "开户成功"];
import loginPopup from "@/components/loginPopup";
import userInfoPopup from "@/components/userInfoPopup";
import uniPopup from "@/components/uni-popup/uni-popup.vue";
import uniPopupDialog from "@/components/uni-popup/uni-popup-dialog.vue";
import skeleton from "./user.skeleton";
import authApi from "@/api/address.api";
import { queryMemberAndCouponInfo } from "@/api/member.api";
import {
getVaildSubTmplIds,
uploadPopup,
getGiftCard,
getWalletInfo,
getFincialData
} from "@/api/home.api";
import { h5Mixin } from "@/utils/h5Mixin";
import { getVaildTmplIds, submitSubcribeInfo, getAcceptList } from "@/utils/subscribe";
import tipModal from "@/components/tip-modal";
import { saTrackEvent, saDeviceId } from "@/utils/sa";
import { getCartCountVal } from "../../mixins/common.js";
import activityModal from "@/components/activityModal";
import QaSelector from "@/components/qaTool/qaSelector";
import userInfoBox from "./userInfoBox.vue";
import giftButton from "./giftButton.vue";
import member from "./member.vue";
import config from "@/config";
import { parseTime } from "@/utils/index";
const tmplIds = [
config.SUB_MSG_LIST.SELLER_SHIP,
config.SUB_MSG_LIST.ORDER_RECEIPT,
config.SUB_MSG_LIST.COUPON_RECEIPT
];
let vaildTmplIds = [];
const newTmplIds = [
config.SUB_MSG_LIST.RESULT_NOTICE,
config.SUB_MSG_LIST.RECEIPT_OPEN_SUCCESS
// config.SUB_MSG_LIST.NEWPRODUCT_NOTICE
];
const tenantBasicInfo = uni.getStorageSync("tenantBasicInfo");
let startY = 0,
moveY = 0,
pageAtTop = true;
export default {
components: {
loginPopup,
userInfoPopup,
uniPopup,
uniPopupDialog,
tipModal,
skeleton,
activityModal,
QaSelector,
userInfoBox,
giftButton,
member
},
mixins: [h5Mixin()],
data() {
return {
navHeight: 70,
allLoading: true,
showTip: false,
coverTransform: "translateY(0px)",
coverTransition: "0s",
moving: false,
paidOrderNum: 0,
goodsOrderNum: 0,
authState: false,
userBaseInfo: {},
userInfo: {
nickname: "",
hasLogin: false
},
xhkBtnText: "立即开通",
xhkBtnState: true,
xhkOpened: true,
xhkInfo: {},
xhkPopupTxt: "您可以下载“羊小咩”APP,在APP内完成激活即可享最高40天购物免息!",
qrFrom: "wx",
telReg: /^(\d{3})\d{4}(\d{4})$/,
cashOutRaise: "",
cashOutReturn: "",
activityModalData: {},
activityJumpUrl: "",
giftInfo: {},
memberInfo: {}, // 会员信息
giftCardInfo: {
// 礼品卡信息
count: "0"
},
couponInfo: {}, // 优惠券信息
cardBagInfo: {},
showMaxMember: true, // 是否展示和max会员相关元素
maxMemberIconUrl: "", // max会员icon
maxMemberInfo: {},
bgType: "normal",
showPoint: true,
changedBg: false // 是否已经切换过背景图
};
},
async onLoad(option) {
const vm = this;
uni.$on("login", usnerInfo => {
if (usnerInfo) {
vm.getUserInfo();
if (this.activityJumpUrl) {
const url = this.activityJumpUrl;
this.activityJumpUrl = "";
uni.redirectTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
}
// #ifdef MP-WEIXIN
getVaildSubTmplIds(tmplIds).then(res => {
vaildTmplIds = res;
});
// #endif
}
});
if (uni.getStorageSync("token")) {
this.setUserInfo();
// #ifdef MP-WEIXIN
vaildTmplIds = await getVaildSubTmplIds(tmplIds);
// #endif
}
if (option && option.login == 1) {
vm.loginPopupFn();
}
this.getUserPopup();
process.env.NODE_ENV !== "production" &&
uni.$on("qaEnvChange", () => {
this.xhkInfo = {};
this.userInfo = {};
this.userBaseInfo = {};
this.init();
});
// 注销登录清空数据
uni.$on("logout", () => {
this.userInfo.nickname = "";
this.userInfo.hasLogin = false;
});
const date = parseTime(new Date(), "{y}-{m}-{d}");
if (uni.getStorageSync("date")) {
const lastDate = uni.getStorageSync("date");
if (date > lastDate) {
uni.setStorageSync("date", date);
this.showPoint = true;
} else {
this.showPoint = false;
}
} else {
uni.setStorageSync("date", date);
this.showPoint = true;
}
},
onTabItemTap() {
saTrackEvent("MINI_BottomTabsClick", { tab_name: "我的" });
},
onShow() {
const vccToken = uni.getStorageSync("token") || "";
this.init();
this.getNavBarHeight();
if (vccToken) {
this.getMemberAndCouponInfo();
this.getWalletInfo();
} else {
this.userInfo.hasLogin = false;
}
},
onReady() {
this.allLoading = false;
},
onUnload() {
// 移除监听事件
uni.$off("login");
uni.$off("logout");
uni.$off("qaEnvChange");
},
// #ifndef MP
onNavigationBarButtonTap(e) {
const index = e.index;
if (index === 0) {
this.navTo("/subPackages/common/set/set");
} else if (index === 1) {
// #ifdef APP-PLUS
const pages = getCurrentPages();
const page = pages[pages.length - 1];
const currentWebview = page.$getAppWebview();
currentWebview.hideTitleNViewButtonRedDot({
index
});
// #endif
uni.navigateTo({
url: "/subPackages/common/notice/notice"
});
}
},
// #endif
computed: {
customField() {
const xhkInfo = JSON.parse(JSON.stringify(this.xhkInfo || {}));
delete xhkInfo.repayDesc;
delete xhkInfo.creditTotalAmountDesc;
return JSON.stringify({
...this.userInfo,
...xhkInfo,
...tenantBasicInfo
});
},
sessionFrom() {
return `我的-在线客服|${this.userBaseInfo.nickName}|${this.userBaseInfo.avatarUrl}|${this.customField}`;
}
},
methods: {
init() {
getCartCountVal();
this.userBaseInfo = uni.getStorageSync("userBaseInfo") || {};
this.authState = !!this.userBaseInfo.nickName;
if (uni.getStorageSync("token")) {
this.setUserInfo();
this.getOrderInfo();
this.getXhkInfo();
// 20220402 发现获取返现信息的接口有时会提示异常,而这块功能已在小程序下线,为此注释掉相关代码
// this.getCashOut();
this.getGiftCard();
}
},
changeBg(type) {
// max会员和普通会员滑动后切换背景颜色
this.changedBg = true;
this.bgType = type;
},
getNavBarHeight() {
if (this.$config("qinghai")) {
const sysInfo = wx.getSystemInfoSync();
const cubeInfo = wx.getMenuButtonBoundingClientRect();
const statusBarHeight = sysInfo.statusBarHeight;
const navbarHeight = (cubeInfo.top - sysInfo.statusBarHeight) * 2 + cubeInfo.height;
this.navHeight = statusBarHeight + navbarHeight;
}
},
async getMemberAndCouponInfo() {
// 查询会员信息及优惠券信息
const [data, err] = await queryMemberAndCouponInfo();
if (err) return;
const { memberInfo, maxMemberInfo } = data;
this.maxMemberInfo = maxMemberInfo || {};
this.memberInfo = memberInfo && memberInfo.constructor === Object ? data.memberInfo : {};
this.maxMemberIconUrl = maxMemberInfo && maxMemberInfo.iconUrl ? maxMemberInfo.iconUrl : "";
/* #ifdef MP-WEIXIN */
this.showMaxMember =
maxMemberInfo &&
maxMemberInfo.status &&
(maxMemberInfo.status == 2 || maxMemberInfo.status == 3)
? true
: false;
if (!this.changedBg) {
this.bgType =
maxMemberInfo &&
maxMemberInfo.status &&
(maxMemberInfo.status == 2 || maxMemberInfo.status == 3)
? "maxMember"
: "normal";
}
/* #endif */
/* #ifndef MP-WEIXIN */
this.showMaxMember = false;
this.bgType = "normal";
/* #endif */
},
async getWalletInfo() {
// 查询优惠券、礼品卡、和卡包信息
const [data, err] = await getWalletInfo();
if (err) return;
const serviceList = data.serviceList || [];
const couponInfoArr = serviceList.filter(v => v.type === "coupon");
const giftCardInfoArr = serviceList.filter(v => v.type === "giftcard");
const cardBagInfoArr = serviceList.filter(v => v.type === "cardbag");
this.couponInfo = couponInfoArr.length ? couponInfoArr[0] : {};
this.giftCardInfo = giftCardInfoArr.length ? giftCardInfoArr[0] : {};
this.cardBagInfo = cardBagInfoArr.length ? cardBagInfoArr[0] : {};
},
toRefund() {
if (!this.userInfo.hasLogin) {
this.$refs["login-popup"].open();
return;
}
const vccToken = uni.getStorageSync("token") || "";
const vccChannel = uni.getStorageSync("vccChannel") || "";
const urlpj = `${config.MALL_URL}/refundList?vccChannel=${vccChannel}&vccToken=${vccToken}`;
uni.navigateTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(urlpj))}`
});
},
async getGiftCard() {
if (this.$config("qinghai") && this.userInfo.hasLogin) {
const [res, err] = await getGiftCard();
if (!err) {
this.giftInfo = res || {};
}
}
},
async closeActivityModal() {
const data = JSON.parse(JSON.stringify(this.activityModalData));
const token = uni.getStorageSync("token") || "";
this.activityModalData = {};
if (data?.exposureType == 3 && token) {
const uid = data.uid;
const exposureType = data.exposureType;
await uploadPopup({
uid,
exposureType
});
}
},
async getUserPopup() {
const [data] = await authApi.getUserPopup();
const token = uni.getStorageSync("token") || "";
this.activityModalData = data || {};
if (data?.exposureType == 1 && token) {
// 每天仅弹出一次 进行上报
const uid = data.uid;
const exposureType = data.exposureType;
await uploadPopup({
uid,
exposureType
});
}
},
async jumpToWebView(data) {
saTrackEvent("MINI_PagePopupWindowClick", {
popupwindow_id: data.uid,
popupwindow_name: data.componentName,
page_name: "我的"
});
data = data || {};
const token = uni.getStorageSync("token") || "";
const url = data.jumpUrl || "";
this.activityJumpUrl = url;
if (data?.needLogin && !token) {
this.activityModalData = {};
this.$refs["login-popup"].open();
return;
}
if (data?.exposureType == 2 && token) {
const uid = data.uid;
const exposureType = data.exposureType;
await uploadPopup({
uid,
exposureType
});
}
this.activityModalData = {};
if (url.indexOf("http://") === 0 || url.indexOf("https://") === 0) {
uni.navigateTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(url))}`
});
return;
}
uni.navigateTo({
url
});
},
setUserInfo() {
const phone = uni.getStorageSync("phone");
this.userInfo.nickname = phone.replace(this.telReg, "$1****$2");
this.userInfo.hasLogin = true;
},
getUserInfo() {
const vm = this;
vm.setUserInfo();
vm.getOrderInfo();
vm.getXhkInfo();
// vm.getCashOut();
vm.getGiftCard();
vm.getWalletInfo();
vm.getMemberAndCouponInfo();
},
config() {
uni.redirectTo({
url: `/subPackages/common/set/set`
});
},
tip() {
this.qrFrom = "wx";
this.showTip = true;
},
changeTipStatus() {
this.showTip = false;
},
clearData() {
this.paidOrderNum = 0;
this.goodsOrderNum = 0;
this.userInfo.hasLogin = false;
},
loginPopupFn(isclear) {
if (isclear) this.clearData(); // 切换环境之后重置一些数据
if (!uni.getStorageSync("token")) {
this.$refs["login-popup"].open();
}
},
close2() {
// TODO 做一些其他的事情,before-close 为true的情况下,手动执行 done 才会关闭对话框
// ...
// done()
},
/**
* 点击确认按钮触发
* @param {Object} done
* @param {Object} value
*/
confirm() {
// 输入框的值
// console.log(value)
// TODO 做一些其他的事情,手动执行 done 才会关闭对话框
// ...
// done()
},
open(ref) {
this.$refs[ref].open();
},
close(ref) {
this.$refs[ref].close();
},
setSubMsg(url) {
if (!this.userInfo.hasLogin) {
this.$refs["login-popup"].open();
} else if (!vaildTmplIds.length) {
this.navTo(url);
} else {
// 非羊小咩不触发订阅消息
if (this.$config("yxm")) {
// #ifdef MP-WEIXIN
wx.requestSubscribeMessage({
tmplIds: vaildTmplIds,
success: res => {
this.submitInfo(res);
this.navTo(url);
const vaildIds = getVaildTmplIds(res);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "我的页,点击订单相关按钮",
check_content: vaildIds,
buttons_name: "允许"
});
},
fail: err => {
console.error("requestSubscribeMessage", err);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "我的页,点击订单相关按钮",
check_content: "商家发货通知,优惠券到账通知,优惠券过期通知",
buttons_name: "取消"
});
this.navTo(url);
}
});
// #endif
} else {
this.navTo(url);
}
}
},
submitInfo(res) {
const acceptList = getAcceptList(res);
submitSubcribeInfo(acceptList);
},
/**
* 统一跳转接口,拦截未登录路由
* navigator标签现在默认没有转场动画,所以用view
*/
navTo(url) {
if (!this.userInfo.hasLogin) {
// url = '/pages/public/login';
this.$refs["login-popup"].open();
} else if (url == "open-popup") {
this.qrFrom = "gzh"; // 退款售后
this.showTip = true;
} else {
uni.navigateTo({
url
});
}
},
navToCustomer() {
const account = uni.getStorageSync("userAuthInfo").uuid || saDeviceId;
const customerH5Url = `https://kefu.q-gp.com/H5/#/chat?skillGroupId=398&enterpriseId=216&headline=%E7%BE%8A%E5%B0%8F%E5%92%A9%E5%95%86%E5%9F%8E&tel=400-666-0873&account=${account}`;
const customerUrlEncode = `/pages/webview/webview?url=${encodeURIComponent(
JSON.stringify(customerH5Url)
)}`;
/* #ifdef MP-ALIPAY */
// 如果是支付宝时未登录下 使用神策设备id代替 uuid
if (!this.userInfo.hasLogin) {
return uni.navigateTo({
url: customerUrlEncode
});
}
/* #endif */
this.navTo(customerUrlEncode);
},
xhkRepayment(val) {
// cashOutRaise
// if (!this.xhkInfo.overdue && parseInt(this.xhkInfo.repayAmt) == 0) return
if (val === "appToFace") {
saTrackEvent("PD_YXMMACP_UserClickMyPageGoToConfirmBtn");
this.qrFrom = "appToFace";
} else if (val === "cashOutRaise") {
// 去提现
saTrackEvent("PD_YXMMACP_UserClickMyPageGetCash");
this.qrFrom = "app";
} else {
this.qrFrom = "app";
}
this.showTip = true;
},
handleToPayBack() {
const vccToken = uni.getStorageSync("token") || "";
const jumpUrl = `${config.VCC_URL}/bill?vccToken=${vccToken}&vccChannel=${config.VCC_CHANNEL}`;
saTrackEvent("PD_YXMMACP_UserClickMyToRepay");
uni.navigateTo({
url: `/pages/webview/webview?url=${encodeURIComponent(JSON.stringify(jumpUrl))}`
});
},
handleOpen() {
const vm = this;
if (!vm.xhkBtnState) return;
saTrackEvent("PD_YXMMACP_UserClickMyVccCardButton", {
vcc_state: status[this.xhkInfo.accountStatus - 1],
buttons_name: this.xhkBtnText
});
// vm.open('xhk-btn-popup')
// if (vm.xhkBtnText == '立即激活') {
// vm.qrFrom = 'app'
// vm.showTip = true
// } else {
// this.goApply();
// }
wx.requestSubscribeMessage({
tmplIds: newTmplIds,
success: res => {
this.goApply();
const vaildIds = getVaildTmplIds(res);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "我的-点击 立即开通",
check_content: vaildIds,
buttons_name: "允许"
});
},
fail: err => {
console.error("requestSubscribeMessage", err);
saTrackEvent("MINI_MessageSubscriptionPopupBtnClick", {
trigger_node: "我的-点击 立即开通",
check_content: "审核结果通知,发票开具成功提醒",
buttons_name: "取消"
});
this.goApply();
}
});
},
handleAuthState(e) {
this.authState = !!e.nickName;
},
showAuthModal() {
this.$refs["authPopup"].open();
},
handleUserInfo(e) {
this.authState = !!e.nickName;
this.userBaseInfo = e;
},
async getXhkInfo() {
// 获取信用钱包用户信息
const vm = this;
const [getData] = await authApi.xhkInfo();
if (getData) {
vm.xhkInfo = getData;
// getData.accountStatus = '5'
switch (parseInt(getData.accountStatus)) {
case 1: // 未申请
vm.xhkBtnText = "立即开通";
break;
case 2: // 审核中
vm.xhkBtnText = "正在审核";
vm.xhkBtnState = false;
break;
case 3: // 审核失败
vm.xhkBtnText = "立即开通";
vm.xhkBtnState = true;
vm.$forceUpdate();
break;
case 4: // 审核成功未开户(包含开户失败)
vm.xhkBtnText = "立即激活";
vm.xhkBtnState = true;
break;
case 5: // 已开户
vm.xhkOpened = false;
break;
}
// vm.xhkInfo.show = false
// vm.xhkOpened = false; // 提交前删除
}
},
// async getCashOut() {
// if (this.$config("qinghai")) return false;
// // 获取提现
// const vm = this;
// const [getData] = await authApi.cashOut();
// if (getData) {
// vm.cashOutRaise = getData.accountAmount;
// vm.cashOutReturn = getData.waitReturnCashAmount;
// }
// },
async getOrderInfo() {
// 我的 查询各状态订单数量
const [getData] = await authApi.orderInfo();
let arrTemp = null;
// console.log(getData.statusNumList)
if (getData) {
arrTemp = getData.statusNumList;
for (let i = 0; i < arrTemp.length; i++) {
if (arrTemp[i].status == 11) {
this.paidOrderNum =
parseInt(arrTemp[i].number) <= 99
? (this.paidOrderNum = arrTemp[i].number)
: (this.paidOrderNum = "99+");
}
if (arrTemp[i].status == 31) {
parseInt(arrTemp[i].number) <= 99
? (this.goodsOrderNum = arrTemp[i].number)
: (this.goodsOrderNum = "99+");
}
}
// paidOrderNum: '', // 待付款 statusNumList[0].number
// goodsOrderNum: '' // 待收货 statusNumList[1].number
}
},
/**
* 会员卡下拉和回弹
* 1.关闭bounce避免ios端下拉冲突
* 2.由于touchmove事件的缺陷(以前做小程序就遇到,比如20跳到40,h5反而好很多),下拉的时候会有掉帧的感觉
* transition设置0.1秒延迟,让css来过渡这段空窗期
* 3.回弹效果可修改曲线值来调整效果,推荐一个好用的bezier生成工具 http://cubic-bezier.com/
*/
coverTouchstart(e) {
if (pageAtTop === false) {
return;
}
this.coverTransition = "transform .1s linear";
startY = e.touches[0].clientY;
},
coverTouchmove(e) {
moveY = e.touches[0].clientY;
let moveDistance = moveY - startY;
if (moveDistance < 0) {
this.moving = false;
return;
}
this.moving = true;
if (moveDistance >= 80 && moveDistance < 100) {
moveDistance = 80;
}
if (moveDistance > 0 && moveDistance <= 80) {
this.coverTransform = `translateY(${moveDistance}px)`;
}
},
coverTouchend() {
if (this.moving === false) {
return;
}
this.moving = false;
this.coverTransition = "transform 0.3s cubic-bezier(.21,1.93,.53,.64)";
this.coverTransform = "translateY(0px)";
},
/**
* 拨打电话
*/
callPhone(tel) {
uni.makePhoneCall({
phoneNumber: tel
});
},
/**
* 跳转到优惠券或者礼品卡
*/
async navigateToPage(type, url) {
// type 1:优惠券 2:礼品卡 3:会员中心, 4:会员权益明细
const token = uni.getStorageSync("token") || "";
if (!token) {
uni.removeStorageSync("token");
this.$refs["login-popup"].open();
// uni.navigateTo({
// url: "/pages/user/login"
// });
return;
}
const urlMap = {
1: "/pages/coupon/index",
2: "/pages/giftCardList/index",
3: "/subPackages/common/member/index",
4: "/subPackages/common/member/detail",
5: ""
};
console.log("url :>> ", url);
const query = url ? { url } : { url: urlMap[type] };
if ([1, 2].indexOf(type) > -1) {
// 优惠券 礼品卡点击埋点
const eventName = "MINI_MyPageAccountColumnBtnClick";
const eventData =
type === 1
? { type: "coupon", buttons_name: "优惠券" }
: { type: "giftcard", buttons_name: "礼品卡" };
saTrackEvent(eventName, eventData);
}
// #ifdef MP-WEIXIN
if (type === 5) {
this.showPoint = false;
const [res] = await getFincialData();
uni.navigateToMiniProgram({
appId: "wx7c92f8bed76ea778",
path: "/pages/vccCardBag/index",
extraData: {
fromAPPID: uni.getAccountInfoSync().miniProgram.appId,
fromPage: "pages/user/user",
params: {
appName: "yxm",
token: res.token || "",
bind: res.bind,
code: res.code || "",
phoneNo: res.phoneNo || "",
uuid: res.uuid || "",
userId: res.userId || "",
tenantId: uni.getStorageSync("tenantId"),
channel: res.vccChannel || ""
},
needQuery: ["phoneNo", "token"]
},
envVersion: "trial"
});
return;
}
// #endif
const method = "navigateTo";
if (query.url) {
uni[method](query);
}
}
}
};
</script>
<style lang="scss">
@keyframes fadeinout {
0% {
opacity: 0.3;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
.face-recognition {
display: flex;
justify-content: space-between;
font-size: 22rpx;
color: #ed6a0c;
background: #fffbe8;
margin: 10rpx 20rpx 0;
height: 60rpx;
line-height: 60rpx;
margin-bottom: 26rpx;
padding-left: 10rpx;
border-radius: 10rpx;
button {
margin-top: 10rpx;
margin-right: 10rpx;
width: 120rpx;
height: 40rpx;
display: inline-block;
line-height: 34rpx;
font-size: 20rpx;
padding: 0;
color: #ed6a0c;
background: #fffbe8;
border: 1px solid #ed6a0c;
border-radius: 10rpx;
text {
font-size: 22rpx;
}
}
}
.btn-position {
position: absolute;
right: 20rpx;
top: 20rpx;
}
.color-gray {
color: #999;
}
.display-block {
display: block;
}
.user-info {
display: flex;
align-items: center;
}
.user-config {
margin-top: 35rpx;
.config {
width: 48rpx;
height: 48rpx;
font-size: 48rpx;
color: #fff;
}
}
.order-section.cash-out {
padding: 25rpx 20rpx;
}
.cash-out {
&-text image {
vertical-align: 30rpx;
display: inline-block;
width: 48rpx;
height: 40rpx;
}
.card-xhk-btn {
margin-top: 22rpx;
}
&-txt {
color: #666;
line-height: 1.6;
font-size: 24rpx;
display: inline-block;
margin-left: 20rpx;
}
&-raise text {
color: #333;
font-size: 40rpx;
margin: 0 10rpx;
font-weight: 700;
}
&-return {
color: #999;
text {
color: #333;
margin-left: 10rpx;
}
}
}
%flex-center {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
%section {
display: flex;
justify-content: space-around;
align-content: center;
background: #fff;
border-radius: 10rpx;
}
.contact-service {
opacity: 0;
position: absolute;
z-index: 9;
display: block;
height: 110rpx;
padding: 0;
}
.xhk-popup {
font-size: 28rpx;
text-align: center;
.declare {
margin-top: 40rpx;
}
button {
width: 526rpx;
height: 80rpx;
line-height: 80rpx;
border: none;
color: #fff;
background-image: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
border-radius: 40rpx;
margin: 32rpx 0;
}
}
.card {
&-box {
background: #fff;
border-radius: 12rpx;
margin-bottom: 24rpx;
}
&-title {
display: flex;
justify-content: space-between;
height: 85rpx;
line-height: 85rpx;
padding: 0 24rpx;
border-bottom: 1rpx solid rgba(216, 216, 216, 0.3);
text {
font-size: 28rpx;
align-self: center;
color: $font-color-dark;
font-weight: 700;
}
}
&-info {
font-size: 24rpx;
color: #999;
.arrows {
font-size: 24rpx;
color: #ccc;
}
}
&-xhk-btn {
width: 180rpx;
height: 60rpx;
line-height: 58rpx;
border-radius: 40rpx;
border: 1rpx solid #ec1500;
font-size: 14px;
color: #ec1500;
text-align: center;
background: #fff;
margin-top: 11rpx;
margin-right: 0;
}
&-xhk-btn.disabled {
opacity: 0.7;
background: #fff;
color: rgba(236, 21, 0, 0.7);
border: 1rpx solid rgba(236, 21, 0, 0.7);
}
&-footer {
display: flex;
justify-content: space-between;
padding: 0 20rpx;
height: 84rpx;
line-height: 84rpx;
border-top: 1rpx solid rgba(216, 216, 216, 0.3);
text {
font-size: 24rpx;
color: #666;
}
}
}
.xhk {
&-state {
position: relative;
display: flex;
padding: 0 20rpx 20rpx;
}
&-icon {
width: 52rpx;
height: 36rpx;
margin-top: 45rpx;
}
&-title {
margin-top: 26rpx;
margin-left: 16rpx;
font-size: 24rpx;
color: #666;
width: 500rpx;
text {
line-height: 1.7;
}
}
&-txt {
font-size: 24rpx;
color: #666666;
}
&-bold {
font-weight: 400;
color: #333;
font-size: 32rpx;
}
}
.main-list {
position: relative;
margin-top: -50rpx;
&.yxm {
margin-top: 0;
}
}
.user-section {
height: 548rpx;
padding: 186rpx 24rpx 0;
position: relative;
&.unlogin {
height: 440rpx;
}
.bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
animation: fadeinout 0.3s linear forwards;
// filter: blur(1px);
// opacity: .7;
}
}
.vip-card-box {
display: flex;
flex-direction: column;
color: #f7d680;
// height: 240rpx;
// background: linear-gradient(to left, rgba(0,0,0,.7), rgba(0,0,0,.8));
background: #fff;
border-radius: 12rpx;
overflow: hidden;
position: relative;
padding: 20rpx 24rpx;
.card-bg {
position: absolute;
top: 20rpx;
right: 0;
width: 380rpx;
height: 260rpx;
}
.b-btn {
position: absolute;
right: 20rpx;
top: 16rpx;
width: 132rpx;
height: 40rpx;
text-align: center;
line-height: 40rpx;
font-size: 22rpx;
color: #36343c;
border-radius: 20px;
background: linear-gradient(to left, #f9e6af, #ffd465);
z-index: 1;
}
.tit {
font-size: $font-base + 2rpx;
color: #f7d680;
margin-bottom: 28rpx;
.yticon {
color: #f6e5a3;
margin-right: 16rpx;
}
}
.e-b {
font-size: $font-sm;
color: #d8cba9;
margin-top: 10rpx;
}
}
.cover-container {
background: $page-color-base;
padding: 0 30rpx;
padding-bottom: 20rpx;
.arc {
position: absolute;
left: 0;
top: -34rpx;
width: 100%;
height: 36rpx;
}
}
.tj-sction {
@extend %section;
.tj-item {
@extend %flex-center;
flex-direction: column;
height: 140rpx;
font-size: $font-sm;
color: #75787d;
}
.num {
font-size: $font-lg + 8;
color: $font-color-dark;
margin-bottom: 8rpx;
font-weight: 700;
}
}
.order-section {
@extend %section;
padding: 25rpx 0;
.order-item {
@extend %flex-center;
position: relative;
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
font-size: $font-sm;
color: $font-color-dark;
image {
width: 80rpx;
height: 80rpx;
display: block;
}
.num {
min-width: 32rpx;
// height: 16px;
height: 36rpx;
background: red;
box-sizing: border-box;
color: #fff;
border: 1rpx solid #fff;
font-size: 20rpx;
text-align: center;
// line-height: 14px;
line-height: 28rpx;
padding: 0 10rpx;
border-radius: 20rpx;
display: inline-block;
position: absolute;
top: 3rpx;
right: 14rpx;
border: 4rpx solid #fff;
}
}
.yticon {
font-size: 48rpx;
margin-bottom: 18rpx;
color: #fa436a;
}
.icon-shouhoutuikuan {
font-size: 44rpx;
}
}
.history-section {
padding: 30rpx 0 0;
margin-top: 20rpx;
background: #fff;
border-radius: 10rpx;
.sec-header {
display: flex;
align-items: center;
font-size: $font-base;
color: $font-color-dark;
line-height: 40rpx;
margin-left: 30rpx;
.yticon {
font-size: 44rpx;
color: #5eba8f;
margin-right: 16rpx;
line-height: 40rpx;
}
}
.h-list {
white-space: nowrap;
padding: 30rpx 30rpx 0;
image {
display: inline-block;
width: 160rpx;
height: 160rpx;
margin-right: 20rpx;
border-radius: 10rpx;
}
}
}
.auth-info__mask {
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
// background: rgba(0, 255, 255, 0.288);
}
.user-qinghai {
/* padding-top: 120rpx; */
.user-qinghai-content {
position: relative;
/* height: 286rpx; */
/* margin: 140rpx 30rpx 30rpx 30rpx; */
margin: 20rpx 30rpx 30rpx;
padding: 46rpx 24rpx 24rpx;
/* background: #5371E0; */
background-image: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
border-radius: 8px;
border-radius: 16rpx;
overflow: hidden;
&::before {
content: "";
background-color: $white;
width: 517px;
height: 473px;
position: absolute;
left: -210px;
top: -410px;
border-radius: 50%;
overflow: hidden;
opacity: 0.12;
background: $white;
}
}
}
.main-qinghai {
margin-top: 0;
}
// 新增优惠券、礼品卡模块
.coupon-info {
width: 100%;
height: 172rpx;
background: #fff;
border-radius: 12rpx;
display: flex;
&-item {
width: 50%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.detail {
position: relative;
display: flex;
align-items: baseline;
// margin-bottom: 12rpx;
height: 60rpx;
.point {
position: absolute;
top: -12rpx;
right: -12rpx;
width: 12rpx;
height: 12rpx;
background: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
border-radius: 50%;
}
.cardbag-icon {
position: absolute;
top: -28rpx;
right: -28rpx;
width: 28rpx;
}
.text-desc {
position: absolute;
top: -30rpx;
right: -50rpx;
height: 28rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 6rpx;
background: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
border-radius: 14rpx 14rpx 14rpx 0;
font-size: 20rpx;
color: $white;
text-align: center;
word-break: keep-all;
}
&-number {
font-size: 36rpx;
color: #333;
font-weight: 600;
}
&-unit {
font-size: 20rpx;
color: #333;
}
}
.desc {
font-size: 24rpx;
color: #666;
}
}
}
// .auth-info {
// width: 622rpx;
// padding: 0 40rpx;
// &__mask {
// position: absolute;
// top: 0;
// left: 0;
// z-index: 10;
// width: 100%;
// height: 100%;
// // background: rgba(0, 255, 255, 0.288);
// }
// &__tip {
// color: #666;
// font-size: 28rpx;
// line-height: 40rpx;
// text-align: center;
// padding: 24rpx 0 48rpx;
// }
// &__agree {
// background: linear-gradient(270deg, #ff5d00 0%, #ff1900 100%);
// height: 72rpx;
// border-radius: 36rpx;
// color: #fff;
// font-size: 28rpx;
// line-height: 72rpx;
// }
// &__cancel {
// font-size: 28rpx;
// color: #ec1500;
// line-height: 40rpx;
// text-align: center;
// padding: 24rpx 0 36rpx;
// }
// }
</style>
<template>
<view class="user-info-box">
<view class="user-info" @click="openLogin">
<view class="portrait-box">
<image
class="portrait"
:src="
userInfo.portrait ||
userBaseInfo.avatarUrl ||
'https://img.lkbang.net/xcx/missing-face.png'
"
/>
</view>
<view class="info-box">
<view
v-if="$config('yxm')"
class="username"
:class="{
username_v1: $config('yxm')
}"
>
<view v-if="userInfo.nickname || userBaseInfo.nickName" class="userInfo">
<view class="content-item">
<text class="phone">{{ userInfo.nickname || userBaseInfo.nickName }}</text>
<view v-if="showMaxMember && maxMemberIconUrl" class="maxMemberIcon">
<image :src="maxMemberIconUrl" mode="widthFix" style="width: 100%;height: auto;" />
</view>
<view class="icon">
<image
:src="memberInfo.userLevelPic"
style="width:100%; height: auto"
mode="widthFix"
/>
</view>
</view>
<view
v-if="memberInfo && Object.keys(memberInfo).length"
class="content-item column"
@click="toDetail"
>
<view class="progress-text">
<text>{{ memberInfo.pointTextName }}</text>
<text class="current">{{ memberInfo.currentPoint }}</text>
<text>/{{ memberInfo.nextLevelPoint }}</text>
<!-- #ifdef MP-WEIXIN -->
<text class="iconfont icon-arrow" />
<!-- #endif -->
</view>
<view class="progress-container">
<view class="progress" />
<view
class="actual"
:style="{
width: progressWidth
}"
/>
</view>
</view>
</view>
<text v-else class="desc">{{ "点击登录/注册" }}</text>
</view>
<view v-else class="username">
<text v-if="userInfo.nickname || userBaseInfo.nickName">{{
userInfo.nickname || userBaseInfo.nickName
}}</text>
<text v-else>{{ "点击登录/注册" }}</text>
</view>
</view>
</view>
<view
class="user-config"
:class="{ yxm: $config('yxm') }"
@click="navTo('/subPackages/common/set/set')"
>
<i class="iconfont icon-setting-line config" />
</view>
</view>
</template>
<script>
const OPEN_LOGIN = "open-login";
const NAV_TO = "nav-to";
export default {
props: {
userInfo: {
type: Object,
default: () => ({})
},
userBaseInfo: {
type: Object,
default: () => ({})
},
memberInfo: {
type: Object,
default: () => ({})
},
showMaxMember: {
type: Boolean,
default: false
},
maxMemberIconUrl: {
type: String,
default: ""
}
},
data() {
return {};
},
computed: {
progressWidth() {
const { currentPoint, nextLevelPoint } = this.memberInfo;
const currentPointFloat = parseFloat(currentPoint);
const nextLevelPointFloat = parseFloat(nextLevelPoint);
if (
currentPoint &&
nextLevelPoint &&
!isNaN(currentPointFloat) &&
!isNaN(nextLevelPointFloat)
) {
const percent = Math.floor((currentPointFloat / nextLevelPointFloat) * 100);
return percent < 1
? "1%"
: `${Math.floor((currentPointFloat / nextLevelPointFloat) * 100)}%`;
} else {
return "1%";
}
}
},
methods: {
openLogin() {
this.$emit(OPEN_LOGIN);
},
navTo(url) {
this.$emit(NAV_TO, url);
},
toDetail() {
// #ifdef MP-WEIXIN
uni.navigateTo({
url: "/subPackages/common/member/growStrategy"
});
/* #endif */
}
}
};
</script>
<style lang="scss" scoped>
@import "@/style/var.scss";
.user-info-box {
// height: 180rpx;
display: flex;
// align-items: center;
justify-content: space-between;
position: relative;
z-index: 1;
.info-box {
height: 112rpx;
display: flex;
align-items: center;
}
.portrait-box {
width: 112rpx;
height: 112rpx;
margin-left: 20rpx;
}
.portrait {
width: 112rpx;
height: 112rpx;
// border:5rpx solid #fff;
border-radius: 50%;
}
.username {
font-size: $font-lg + 2rpx;
color: #fff;
margin-left: 20rpx;
&.username_v1 {
height: 112rpx;
display: flex;
align-items: center;
}
.desc {
@include text-size(32);
color: $black;
}
view {
display: inline-block;
}
.middle {
position: relative;
top: 4rpx;
}
// 以下是会员改动,仅限羊小咩
.userInfo {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
.content-item {
display: flex;
flex-direction: row;
align-items: center;
&.column {
flex-direction: column;
align-items: flex-start;
.progress-text {
@include text-size(24);
color: $black;
display: flex;
align-items: center;
align-content: center;
.current {
margin-left: $padding-unit;
font-weight: $font-weight-bold;
font-size: 28rpx;
}
.iconfont {
margin-left: 20rpx;
font-size: 18rpx;
}
}
.progress-container {
position: relative;
width: 240rpx;
height: 8rpx;
.progress {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #e5b4c1;
border-radius: 6rpx;
}
.actual {
z-index: 2;
position: absolute;
top: 0;
left: 0;
border-radius: 6rpx;
height: 8rpx;
background-image: linear-gradient(269deg, #ff1900 12%, #ff651f 85%);
}
}
}
.phone {
font-weight: $font-weight-bold;
@include text-size(32);
color: $black;
margin-right: 20rpx;
}
.maxMemberIcon {
width: 82rpx;
margin-right: 8rpx;
}
.icon {
width: 120rpx;
height: 56rpx;
}
}
}
}
}
.user-config.yxm {
.config {
color: $black;
}
}
</style>
/*
* @Description: 数据加密,aes加密数据主体,rsa加密aes密钥,aes密钥前端自己存储
* @Date: 2020-12-08 11:08:28
* @LastEditors: gzw
* @LastEditTime: 2021-11-18 17:17:27
*/
import { cipher as AES, util as UTIL, pki as PKI, md as SHA1 } from 'node-forge';
import uuidv1 from 'uuid/v1';
import { parseTime } from './utils.service';
import { APP_ID, PUBLIC_KEY, PRIVATE_KEY } from '@/config/encrypt.config';
/**
* @description: 数据加密
* @param {String} data 数据源
* @return {String} 加密后的数据base64
*/
export function encryption(data = '') {
if (!data) return null;
const key = generateRandomStr(16);
const iv = key; // 后台约定iv与key一致
const plaintext = typeof data === 'object' ? JSON.stringify(data) : data;
const body = encryptDataByAes(plaintext, key, iv); // AES加密数据
const encryptKey = encryptDataByPb(key); // RSA公钥加密AES密钥
const signData = generateSign(plaintext);
return {
appId: APP_ID,
body,
encryptKey,
...signData
};
}
/**
* @description: AES加密数据,默认CBC, Pki#cs7
* @param {String} txt 数据源
* @param {String} key 密钥,16位字符串
* @param {String} iv 初始化向量
* @return {String} 加密后的数据base64
*/
function encryptDataByAes(txt, key, iv) {
const cipher = AES.createCipher('AES-CBC', key);
cipher.start({ iv });
cipher.update(UTIL.createBuffer(txt, 'utf8'));
cipher.finish();
const ciphertext = cipher.output.getBytes();
return buffer2Base64(ciphertext);
}
/**
* @description: 使用RSA公钥加密数据
* @param {String} txt 数据源
* @return {String} 加密后的数据base64
*/
function encryptDataByPb(txt) {
const publicKey = PKI.publicKeyFromPem(PUBLIC_KEY);
const pbData = publicKey.encrypt(txt);
return buffer2Base64(pbData);
}
/**
* @description: RSA私钥+SHA1生成签名
* 签名组成结构nonce+appid+timestamp+body
* @param {String} txt 数据源
* @return {Object} 生成的sign数据,时间戳、Nonce
*/
function generateSign(txt) {
const timestamp = parseTime('');
const nonce = generateNonce();
const privateKey = PKI.privateKeyFromPem(PRIVATE_KEY);
const md = SHA1.sha1.create();
md.update(nonce + APP_ID + timestamp + txt, 'utf8');
let sign = privateKey.sign(md);
sign = buffer2Base64(sign);
return {
timestamp,
nonce,
sign
};
}
/**
* @description: buffer转base64
* @param {Buffer} buf buffer源数据
* @return {String} base64 字符串
*/
function buffer2Base64(buf) {
return UTIL.encode64(buf);
}
/**
* @description: 生成nonce(uuid)
* 规则:以当前时间的uuid作为name,以随机生成的uuid作为namespace,生成最终的uuid
* @return {String} 生成的uuid
*/
function generateNonce() {
return uuidv1();
}
/**
* @description: 生成随机字符串
* @param {Number} n 位数
* @return {String} 生成的字符串
*/
function generateRandomStr(n) {
const len = n || 32;
const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789';
const maxPos = chars.length;
let pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
rm -rf dist/
rm -rf node_modules/
rm -rf yarn-lock.json
# rm -rf package-lock.json
rm -rf src/config/config.json
rm -rf src/manifest.json
npm ci
# npm run 'init' projectIndex=4 && npm run 'dev:mp-weixin'
npm run 'init' projectIndex=4 && npm run 'build:mp-weixin' && node ./wxCI.js type=preview appid=wxe16bf9293671506c version=1.0.1 desc="" buildId=43
# cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build
# cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize
# cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize
#src/config/config.json
#src/manifest.json
\ No newline at end of file
const ci = require("miniprogram-ci");
const path = require("path");
/**
* 获取环境参数
* type 操作类型 preview | publish
* version:版本号 上传操作必填
* desc:版本描述 上传操作必填
* appid:应用id,测试人员有时需要切换应用Id
* buildId: 构建id
*/
let { type="preview", version = "", desc = "", appid = "wxe16bf9293671506c", buildId = "43", env = "prod" } = getEnvParams(
process.argv
);
console.log(process.argv);
const ENVMAP = {
prod: "build",
dev: "dev"
};
const build = ENVMAP[env];
// 请求参数
const reqParams = {
appid,
type: "miniProgram",
projectPath: path.resolve(__dirname, `./dist/${build}/mp-weixin`), //项目路径
privateKeyPath: path.resolve(__dirname, `./build/key/private.${appid}.key`), //小程序后台的上传密匙
ignores: ["node_modules/**/*"]
};
// 上传文件处理设置参数
const uploadParams = {
urlCheck: true,
postcss: true,
minified: true,
babelSetting: {
ignore: [],
disablePlugins: [],
outputPath: ""
}
};
const project = new ci.Project({ ...reqParams });
// 任何时候都生成二维码
(async() => {
const previewResult = await ci.preview({
project,
desc: "预览", // 此备注将显示在“小程序助手”开发版列表中
setting: uploadParams,
qrcodeFormat: "image",
qrcodeOutputDest: `./build/qrcode-${buildId}.jpg`
// onProgressUpdate: console.log,
// pagePath: 'pages/index/index', // 预览页面
// searchQuery: 'a=1&b=2', // 预览参数 [注意!]这里的`&`字符在命令行中应写成转义字符`\&`
});
console.log(previewResult);
})();
if (type === "publish") {
(async () => {
const uploadResult = await ci.upload({
project,
version,
desc,
setting: uploadParams
// onProgressUpdate: console.log,
});
console.log(uploadResult);
})();
}
/**
* 获取node命令行参数
* @param {array} options 命令行数组
*/
function getEnvParams(options) {
let envParams = {};
// 从第三个参数开始,是自定义参数
for (let i = 2, len = options.length; i < len; i++) {
let arg = options[i].split("=");
envParams[arg[0]] = arg[1];
}
return envParams;
}
Markdown is supported
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