Compare commits
No commits in common. "63a7f0ccf4d8708174b5dde16361991f0628f7eb" and "5b37d7962d339bdc77dfad009e0dbae1a1484058" have entirely different histories.
63a7f0ccf4
...
5b37d7962d
@ -1,2 +1,2 @@
|
|||||||
VITE_API_URL = "https://m.taigurun.cn"
|
VITE_API_URL = "https://m.taigurun.cn"
|
||||||
VITE_OSS_URL = "https://m.taigurun.cn/uploads"
|
VITE_OSS_URL = "https://m.taigurun.cn"
|
||||||
@ -1,2 +1,2 @@
|
|||||||
VITE_API_URL = "https://m.taigurun.cn"
|
VITE_API_URL = "https://m.taigurun.cn"
|
||||||
VITE_OSS_URL = "https://m.taigurun.cn/uploads"
|
VITE_OSS_URL = "https://m.taigurun.cn"
|
||||||
@ -12,6 +12,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="app" v-cloak></div>
|
<div id="app" v-cloak></div>
|
||||||
<script src="/js/echarts.min.js"></script>
|
<script src="/js/echarts.min.js"></script>
|
||||||
|
<script src="/js/html2canvas.min.js"></script>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
<style>
|
<style>
|
||||||
[v-cloak] {
|
[v-cloak] {
|
||||||
|
|||||||
57
package-lock.json
generated
@ -10,8 +10,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vant/area-data": "^2.1.0",
|
"@vant/area-data": "^2.1.0",
|
||||||
"@zxing/library": "^0.21.3",
|
"@zxing/library": "^0.21.3",
|
||||||
"html-to-image": "^1.11.13",
|
|
||||||
"html2canvas": "^1.4.1",
|
|
||||||
"image-conversion": "^2.1.1",
|
"image-conversion": "^2.1.1",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
||||||
@ -666,15 +664,6 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/base64-arraybuffer": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/birpc": {
|
"node_modules/birpc": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz",
|
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz",
|
||||||
@ -721,15 +710,6 @@
|
|||||||
"url": "https://github.com/sponsors/mesqueeb"
|
"url": "https://github.com/sponsors/mesqueeb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/css-line-break": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"utrie": "^1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
|
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
|
||||||
@ -842,25 +822,6 @@
|
|||||||
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
|
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/html-to-image": {
|
|
||||||
"version": "1.11.13",
|
|
||||||
"resolved": "https://registry.npmmirror.com/html-to-image/-/html-to-image-1.11.13.tgz",
|
|
||||||
"integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/html2canvas": {
|
|
||||||
"version": "1.4.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz",
|
|
||||||
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"css-line-break": "^2.1.0",
|
|
||||||
"text-segmentation": "^1.0.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
"resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
@ -1675,15 +1636,6 @@
|
|||||||
"url": "https://github.com/sponsors/mesqueeb"
|
"url": "https://github.com/sponsors/mesqueeb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/text-segmentation": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"utrie": "^1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.16",
|
"version": "0.2.16",
|
||||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.16.tgz",
|
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.16.tgz",
|
||||||
@ -1866,15 +1818,6 @@
|
|||||||
"node": "^20.19.0 || >=22.12.0"
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/utrie": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"base64-arraybuffer": "^1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/vant": {
|
"node_modules/vant": {
|
||||||
"version": "4.9.24",
|
"version": "4.9.24",
|
||||||
"resolved": "https://registry.npmmirror.com/vant/-/vant-4.9.24.tgz",
|
"resolved": "https://registry.npmmirror.com/vant/-/vant-4.9.24.tgz",
|
||||||
|
|||||||
@ -11,8 +11,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vant/area-data": "^2.1.0",
|
"@vant/area-data": "^2.1.0",
|
||||||
"@zxing/library": "^0.21.3",
|
"@zxing/library": "^0.21.3",
|
||||||
"html-to-image": "^1.11.13",
|
|
||||||
"html2canvas": "^1.4.1",
|
|
||||||
"image-conversion": "^2.1.1",
|
"image-conversion": "^2.1.1",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
BIN
public/img/agri_bg.png
Normal file
|
After Width: | Height: | Size: 593 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 649 B |
|
Before Width: | Height: | Size: 68 KiB |
235
public/js/canvas2image.js
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* Canvas2Image v0.1
|
||||||
|
* Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk
|
||||||
|
* MIT License [http://www.opensource.org/licenses/mit-license.php]
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Canvas2Image = (function() {
|
||||||
|
|
||||||
|
// check if we have canvas support
|
||||||
|
var bHasCanvas = false;
|
||||||
|
var oCanvas = document.createElement("canvas");
|
||||||
|
if (oCanvas.getContext("2d")) {
|
||||||
|
bHasCanvas = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no canvas, bail out.
|
||||||
|
if (!bHasCanvas) {
|
||||||
|
return {
|
||||||
|
saveAsBMP : function(){},
|
||||||
|
saveAsPNG : function(){},
|
||||||
|
saveAsJPEG : function(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var bHasImageData = !!(oCanvas.getContext("2d").getImageData);
|
||||||
|
var bHasDataURL = !!(oCanvas.toDataURL);
|
||||||
|
var bHasBase64 = !!(window.btoa);
|
||||||
|
|
||||||
|
var strDownloadMime = "image/octet-stream";
|
||||||
|
|
||||||
|
// ok, we're good
|
||||||
|
var readCanvasData = function(oCanvas) {
|
||||||
|
var iWidth = parseInt(oCanvas.width);
|
||||||
|
var iHeight = parseInt(oCanvas.height);
|
||||||
|
return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// base64 encodes either a string or an array of charcodes
|
||||||
|
var encodeData = function(data) {
|
||||||
|
var strData = "";
|
||||||
|
if (typeof data == "string") {
|
||||||
|
strData = data;
|
||||||
|
} else {
|
||||||
|
var aData = data;
|
||||||
|
for (var i=0;i<aData.length;i++) {
|
||||||
|
strData += String.fromCharCode(aData[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return btoa(strData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates a base64 encoded string containing BMP data
|
||||||
|
// takes an imagedata object as argument
|
||||||
|
var createBMP = function(oData) {
|
||||||
|
var aHeader = [];
|
||||||
|
|
||||||
|
var iWidth = oData.width;
|
||||||
|
var iHeight = oData.height;
|
||||||
|
|
||||||
|
aHeader.push(0x42); // magic 1
|
||||||
|
aHeader.push(0x4D);
|
||||||
|
|
||||||
|
var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes
|
||||||
|
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
||||||
|
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
||||||
|
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
||||||
|
aHeader.push(iFileSize % 256);
|
||||||
|
|
||||||
|
aHeader.push(0); // reserved
|
||||||
|
aHeader.push(0);
|
||||||
|
aHeader.push(0); // reserved
|
||||||
|
aHeader.push(0);
|
||||||
|
|
||||||
|
aHeader.push(54); // dataoffset
|
||||||
|
aHeader.push(0);
|
||||||
|
aHeader.push(0);
|
||||||
|
aHeader.push(0);
|
||||||
|
|
||||||
|
var aInfoHeader = [];
|
||||||
|
aInfoHeader.push(40); // info header size
|
||||||
|
aInfoHeader.push(0);
|
||||||
|
aInfoHeader.push(0);
|
||||||
|
aInfoHeader.push(0);
|
||||||
|
|
||||||
|
var iImageWidth = iWidth;
|
||||||
|
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
||||||
|
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
||||||
|
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
||||||
|
aInfoHeader.push(iImageWidth % 256);
|
||||||
|
|
||||||
|
var iImageHeight = iHeight;
|
||||||
|
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
||||||
|
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
||||||
|
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
||||||
|
aInfoHeader.push(iImageHeight % 256);
|
||||||
|
|
||||||
|
aInfoHeader.push(1); // num of planes
|
||||||
|
aInfoHeader.push(0);
|
||||||
|
|
||||||
|
aInfoHeader.push(24); // num of bits per pixel
|
||||||
|
aInfoHeader.push(0);
|
||||||
|
|
||||||
|
aInfoHeader.push(0); // compression = none
|
||||||
|
aInfoHeader.push(0);
|
||||||
|
aInfoHeader.push(0);
|
||||||
|
aInfoHeader.push(0);
|
||||||
|
|
||||||
|
var iDataSize = iWidth*iHeight*3;
|
||||||
|
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
||||||
|
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
||||||
|
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
||||||
|
aInfoHeader.push(iDataSize % 256);
|
||||||
|
|
||||||
|
for (var i=0;i<16;i++) {
|
||||||
|
aInfoHeader.push(0); // these bytes not used
|
||||||
|
}
|
||||||
|
|
||||||
|
var iPadding = (4 - ((iWidth * 3) % 4)) % 4;
|
||||||
|
|
||||||
|
var aImgData = oData.data;
|
||||||
|
|
||||||
|
var strPixelData = "";
|
||||||
|
var y = iHeight;
|
||||||
|
do {
|
||||||
|
var iOffsetY = iWidth*(y-1)*4;
|
||||||
|
var strPixelRow = "";
|
||||||
|
for (var x=0;x<iWidth;x++) {
|
||||||
|
var iOffsetX = 4*x;
|
||||||
|
|
||||||
|
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);
|
||||||
|
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);
|
||||||
|
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);
|
||||||
|
}
|
||||||
|
for (var c=0;c<iPadding;c++) {
|
||||||
|
strPixelRow += String.fromCharCode(0);
|
||||||
|
}
|
||||||
|
strPixelData += strPixelRow;
|
||||||
|
} while (--y);
|
||||||
|
|
||||||
|
var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);
|
||||||
|
|
||||||
|
return strEncoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// sends the generated file to the client
|
||||||
|
var saveFile = function(strData) {
|
||||||
|
document.location.href = strData;
|
||||||
|
}
|
||||||
|
|
||||||
|
var makeDataURI = function(strData, strMime) {
|
||||||
|
return "data:" + strMime + ";base64," + strData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates a <img> object containing the imagedata
|
||||||
|
var makeImageObject = function(strSource) {
|
||||||
|
var oImgElement = document.createElement("img");
|
||||||
|
oImgElement.src = strSource;
|
||||||
|
return oImgElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scaleCanvas = function(oCanvas, iWidth, iHeight) {
|
||||||
|
if (iWidth && iHeight) {
|
||||||
|
var oSaveCanvas = document.createElement("canvas");
|
||||||
|
oSaveCanvas.width = iWidth;
|
||||||
|
oSaveCanvas.height = iHeight;
|
||||||
|
oSaveCanvas.style.width = iWidth+"px";
|
||||||
|
oSaveCanvas.style.height = iHeight+"px";
|
||||||
|
|
||||||
|
var oSaveCtx = oSaveCanvas.getContext("2d");
|
||||||
|
|
||||||
|
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);
|
||||||
|
return oSaveCanvas;
|
||||||
|
}
|
||||||
|
return oCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
|
||||||
|
if (!bHasDataURL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
|
||||||
|
var strData = oScaledCanvas.toDataURL("image/png");
|
||||||
|
if (bReturnImg) {
|
||||||
|
return makeImageObject(strData);
|
||||||
|
} else {
|
||||||
|
saveFile(strData.replace("image/png", strDownloadMime));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
|
||||||
|
if (!bHasDataURL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
|
||||||
|
var strMime = "image/jpeg";
|
||||||
|
var strData = oScaledCanvas.toDataURL(strMime);
|
||||||
|
|
||||||
|
// check if browser actually supports jpeg by looking for the mime type in the data uri.
|
||||||
|
// if not, return false
|
||||||
|
if (strData.indexOf(strMime) != 5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bReturnImg) {
|
||||||
|
return makeImageObject(strData);
|
||||||
|
} else {
|
||||||
|
saveFile(strData.replace(strMime, strDownloadMime));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
|
||||||
|
if (!(bHasImageData && bHasBase64)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
|
||||||
|
|
||||||
|
var oData = readCanvasData(oScaledCanvas);
|
||||||
|
var strImgData = createBMP(oData);
|
||||||
|
if (bReturnImg) {
|
||||||
|
return makeImageObject(makeDataURI(strImgData, "image/bmp"));
|
||||||
|
} else {
|
||||||
|
saveFile(makeDataURI(strImgData, strDownloadMime));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
22
public/js/html2canvas.min.js
vendored
Normal file
20
src/App.vue
@ -1,19 +1,3 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-view v-slot="{ Component, route }">
|
<router-view />
|
||||||
<keep-alive :include="cacheList">
|
</template>
|
||||||
<component :is="Component" :key="route.name" />
|
|
||||||
</keep-alive>
|
|
||||||
</router-view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'App',
|
|
||||||
computed: {
|
|
||||||
cacheList() {
|
|
||||||
const routes = this.$router.getRoutes()
|
|
||||||
return routes.filter(r => r.meta.cache).map(r => r.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -5,15 +5,15 @@
|
|||||||
const BASE_URL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:3001';
|
const BASE_URL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:3001';
|
||||||
|
|
||||||
// 默认超时时间 15 秒
|
// 默认超时时间 15 秒
|
||||||
const DEFAULT_TIMEOUT = 30000;
|
const DEFAULT_TIMEOUT = 15000;
|
||||||
|
|
||||||
// 错误码定义
|
// 错误码定义
|
||||||
const ERR_CODE = {
|
const ERR_CODE = {
|
||||||
SUCCESS: 200,
|
SUCCESS: 200,
|
||||||
UNAUTHORIZED: 401,
|
UNAUTHORIZED: 401,
|
||||||
FORBIDDEN: 403,
|
FORBIDDEN: 403,
|
||||||
NOT_FOUND: 404,
|
NOT_FOUND: 404,
|
||||||
SERVER_ERROR: 500,
|
SERVER_ERROR: 500,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getHeaders(contentType = 'application/json') {
|
function getHeaders(contentType = 'application/json') {
|
||||||
@ -63,11 +63,6 @@ function handleResponse(response) {
|
|||||||
* 处理 token 失效
|
* 处理 token 失效
|
||||||
*/
|
*/
|
||||||
function handleUnauthorized() {
|
function handleUnauthorized() {
|
||||||
// 如果 localStorage 中本来就没有 token,说明是未登录状态,不做处理
|
|
||||||
if (!localStorage.getItem('member_token')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清除登录状态
|
// 清除登录状态
|
||||||
localStorage.removeItem('member_token');
|
localStorage.removeItem('member_token');
|
||||||
localStorage.removeItem('member_username');
|
localStorage.removeItem('member_username');
|
||||||
|
|||||||
@ -5,10 +5,8 @@ export function isLogin() {
|
|||||||
export function formatGMT(t, format) {
|
export function formatGMT(t, format) {
|
||||||
// 传入的格式 "2026-04-01T14:06:56.5879258"
|
// 传入的格式 "2026-04-01T14:06:56.5879258"
|
||||||
if (!t)
|
if (!t)
|
||||||
return ''
|
return
|
||||||
const index = t.indexOf('T');
|
const index = t.indexOf('T');
|
||||||
if (index === -1)
|
|
||||||
return t
|
|
||||||
const date = t.substring(0, index).split('-')
|
const date = t.substring(0, index).split('-')
|
||||||
const time = t.substring(index + 1).split(':')
|
const time = t.substring(index + 1).split(':')
|
||||||
|
|
||||||
@ -22,7 +20,7 @@ export function formatGMT(t, format) {
|
|||||||
const sctime = time[2].split('.')
|
const sctime = time[2].split('.')
|
||||||
|
|
||||||
const second = sctime[0].padStart(2, '0')
|
const second = sctime[0].padStart(2, '0')
|
||||||
const millisecond = sctime[1] ? sctime[1].substring(0, 2).padStart(2, '0') : '00'
|
const millisecond = sctime[1].substring(0, 2).padStart(2, '0')
|
||||||
return format
|
return format
|
||||||
.replace('yyyy', year)
|
.replace('yyyy', year)
|
||||||
.replace('MM', month)
|
.replace('MM', month)
|
||||||
|
|||||||
@ -25,7 +25,6 @@ export default {
|
|||||||
pageSize: { type: Number, default: 10 },
|
pageSize: { type: Number, default: 10 },
|
||||||
finishedText: { type: String, default: '没有更多了' },
|
finishedText: { type: String, default: '没有更多了' },
|
||||||
parseData: { type: Function, default: (res) => res.data.items },
|
parseData: { type: Function, default: (res) => res.data.items },
|
||||||
cacheKey: { type: String, default: '' },
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -35,8 +34,6 @@ export default {
|
|||||||
page: 1,
|
page: 1,
|
||||||
requestId: 0,
|
requestId: 0,
|
||||||
observer: null,
|
observer: null,
|
||||||
_cacheKey: null,
|
|
||||||
_dataCache: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['update:list', 'load', 'refresh'],
|
emits: ['update:list', 'load', 'refresh'],
|
||||||
@ -53,19 +50,6 @@ export default {
|
|||||||
deep: true
|
deep: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
|
||||||
if (this.cacheKey) {
|
|
||||||
const cached = sessionStorage.getItem(this.cacheKey)
|
|
||||||
if (cached) {
|
|
||||||
try {
|
|
||||||
const { list, page, finished, params } = JSON.parse(cached)
|
|
||||||
if (JSON.stringify(this.params) === JSON.stringify(params)) {
|
|
||||||
this._dataCache = { list, page, finished }
|
|
||||||
}
|
|
||||||
} catch (e) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.observer = new IntersectionObserver((entries) => {
|
this.observer = new IntersectionObserver((entries) => {
|
||||||
@ -82,14 +66,6 @@ export default {
|
|||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
this.observer?.disconnect()
|
this.observer?.disconnect()
|
||||||
window.removeEventListener('scroll', this.onWindowScroll)
|
window.removeEventListener('scroll', this.onWindowScroll)
|
||||||
if (this.cacheKey && this.list.length > 0) {
|
|
||||||
sessionStorage.setItem(this.cacheKey, JSON.stringify({
|
|
||||||
list: this.list,
|
|
||||||
page: this.page,
|
|
||||||
finished: this.finished,
|
|
||||||
params: this.params
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onWindowScroll() {
|
onWindowScroll() {
|
||||||
@ -103,13 +79,6 @@ export default {
|
|||||||
},
|
},
|
||||||
loadMore() {
|
loadMore() {
|
||||||
if (this.loading) return
|
if (this.loading) return
|
||||||
if (this._dataCache && this._dataCache.params && JSON.stringify(this.params) === JSON.stringify(this._dataCache.params)) {
|
|
||||||
this.list = this._dataCache.list
|
|
||||||
this.page = this._dataCache.page
|
|
||||||
this.finished = this._dataCache.finished
|
|
||||||
this.loading = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const currentRequestId = this.requestId
|
const currentRequestId = this.requestId
|
||||||
this.loading = true
|
this.loading = true
|
||||||
const request = this.method === 'get' ? this.$get : this.$post
|
const request = this.method === 'get' ? this.$get : this.$post
|
||||||
@ -154,8 +123,6 @@ export default {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.base-list {
|
.base-list {
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-wrap {
|
.loading-wrap {
|
||||||
@ -163,20 +130,6 @@ export default {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-wrap :deep(.van-loading) {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: row;
|
|
||||||
white-space: nowrap;
|
|
||||||
float: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-wrap :deep(.van-loading__text) {
|
|
||||||
float: none !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.finished-text,
|
.finished-text,
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- -->
|
<!-- $isWechat() ? '' : title || -->
|
||||||
<van-nav-bar fixed :title="$isWechat() ? '' : title || $route.meta.title" :safe-area-inset-top="true" placeholder
|
<van-nav-bar fixed :title="title || $route.meta.title" :safe-area-inset-top="true" placeholder left-arrow left-text="返回"
|
||||||
left-arrow left-text="返回" @click-left="back ? back() : $router.back();"
|
@click-left="back ? back() : $router.back();" :class="$isWechat() ? 'wechat-nav' : ''">
|
||||||
:class="$isWechat() ? 'wechat-nav' : ''">
|
|
||||||
<template #right>
|
<template #right>
|
||||||
<slot v-if="$slots.right" name="right" />
|
<slot v-if="$slots.right" name="right" />
|
||||||
<van-icon v-else-if="!hideHome" name="wap-home-o" size="18" @click="$router.replace('/')" />
|
<van-icon v-else-if="!hideHome" name="wap-home-o" size="18" @click="$router.replace('/')" />
|
||||||
|
|||||||
@ -87,11 +87,6 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
getPermissions() {
|
getPermissions() {
|
||||||
if (!this.$isLogin()) {
|
|
||||||
// this.$showFailToast('登录状态异常,请重新登录')
|
|
||||||
// location.replace('#/Login')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$get('/v1/client/DUsersClient').then(res => {
|
this.$get('/v1/client/DUsersClient').then(res => {
|
||||||
this.PermissionsData = {
|
this.PermissionsData = {
|
||||||
id: res.data.id,
|
id: res.data.id,
|
||||||
@ -106,7 +101,7 @@ export default {
|
|||||||
this.$showConfirmDialog({
|
this.$showConfirmDialog({
|
||||||
title: "确认退出?",
|
title: "确认退出?",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$ls.remove('member_token');
|
this.$ls.remove('token');
|
||||||
location.replace('#/Login');
|
location.replace('#/Login');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
location.reload();
|
location.reload();
|
||||||
|
|||||||
19
src/main.js
@ -53,24 +53,9 @@ datadicStore.init()
|
|||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
// 全局前置守卫
|
|
||||||
router.beforeEach((to, from, next) => {
|
|
||||||
if (to.meta.title) {
|
|
||||||
document.title = to.meta.title;
|
|
||||||
}
|
|
||||||
if (to.meta.noLogin) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
const isLogin = userStore.isLogin;
|
|
||||||
if (!isLogin) {
|
|
||||||
return next({ name: 'Login', query: { redirect: to.fullPath } });
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.config.globalProperties.$datadic = {
|
app.config.globalProperties.$datadic = {
|
||||||
get: (code) => dictCache[code] || null,
|
get: (code) => dictCache[code] || null,
|
||||||
getContent: (code) => dictCache[code] ? dictCache[code].contents : '',
|
getContent: (code) => dictCache[code] ? dictCache[code].contents : '',
|
||||||
}
|
}
|
||||||
|
|
||||||
app.config.globalProperties.$userInfo = userStore.getUserInfo;
|
app.config.globalProperties.$userInfo = userStore.getUserInfo;
|
||||||
|
|||||||
@ -18,7 +18,7 @@ const routes = [
|
|||||||
path: '/Gift',
|
path: '/Gift',
|
||||||
name: 'Gift',
|
name: 'Gift',
|
||||||
component: () => import('./views/Tabbars/Gift.vue'),
|
component: () => import('./views/Tabbars/Gift.vue'),
|
||||||
meta: { title: '礼包区', cache: true }
|
meta: { title: '礼品区', cache: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/Mall',
|
path: '/Mall',
|
||||||
@ -26,12 +26,6 @@ const routes = [
|
|||||||
component: () => import('./views/Tabbars/Mall.vue'),
|
component: () => import('./views/Tabbars/Mall.vue'),
|
||||||
meta: { title: '商城', cache: true }
|
meta: { title: '商城', cache: true }
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/PointMall',
|
|
||||||
name: 'PointMall',
|
|
||||||
component: () => import('./views/Tabbars/PointMall.vue'),
|
|
||||||
meta: { title: '积分区', cache: true }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/My',
|
path: '/My',
|
||||||
name: 'My',
|
name: 'My',
|
||||||
@ -41,14 +35,6 @@ const routes = [
|
|||||||
],
|
],
|
||||||
meta: { noLogin: true }
|
meta: { noLogin: true }
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/WxCallback',
|
|
||||||
name: 'WxCallback',
|
|
||||||
component: () => import('./views/Account/WxCallback.vue'),
|
|
||||||
meta: {
|
|
||||||
noLogin: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/Login',
|
path: '/Login',
|
||||||
name: 'Login',
|
name: 'Login',
|
||||||
@ -81,7 +67,7 @@ const routes = [
|
|||||||
name: 'CV',
|
name: 'CV',
|
||||||
component: () => import('./views/User/Wallet/CV.vue'),
|
component: () => import('./views/User/Wallet/CV.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '会员卡',
|
title: '会员卡额度',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -148,7 +134,7 @@ const routes = [
|
|||||||
path: '/Invite',
|
path: '/Invite',
|
||||||
name: 'Invite',
|
name: 'Invite',
|
||||||
component: () => import('./views/User/Invite.vue'),
|
component: () => import('./views/User/Invite.vue'),
|
||||||
meta: { title: '邀请码', cache: true }
|
meta: { title: '邀请码' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/Team',
|
path: '/Team',
|
||||||
@ -190,43 +176,43 @@ const routes = [
|
|||||||
path: '/Business_School',
|
path: '/Business_School',
|
||||||
name: 'Business_School',
|
name: 'Business_School',
|
||||||
component: () => import('./views/Platform/Business_School.vue'),
|
component: () => import('./views/Platform/Business_School.vue'),
|
||||||
meta: { title: '商学院', noLogin: true }
|
meta: { title: '商学院' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/School_detail',
|
path: '/School_detail',
|
||||||
name: 'School_detail',
|
name: 'School_detail',
|
||||||
component: () => import('./views/Platform/School_Detail.vue'),
|
component: () => import('./views/Platform/School_Detail.vue'),
|
||||||
meta: { title: '商学院详情', noLogin: true, }
|
meta: { title: '商学院详情' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/School_Category',
|
path: '/School_Category',
|
||||||
name: 'School_Category',
|
name: 'School_Category',
|
||||||
component: () => import('./views/Platform/School_Category.vue'),
|
component: () => import('./views/Platform/School_Category.vue'),
|
||||||
meta: { title: '商学院分类', noLogin: true, }
|
meta: { title: '商学院分类' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/Column',
|
path: '/Column',
|
||||||
name: 'Column',
|
name: 'Column',
|
||||||
component: () => import('./views/Platform/Column.vue'),
|
component: () => import('./views/Platform/Column.vue'),
|
||||||
meta: { title: '栏目列表', noLogin: true }
|
meta: { title: '栏目列表' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/ColumnDetail',
|
path: '/ColumnDetail',
|
||||||
name: 'ColumnDetail',
|
name: 'ColumnDetail',
|
||||||
component: () => import('./views/Platform/ColumnDetail.vue'),
|
component: () => import('./views/Platform/ColumnDetail.vue'),
|
||||||
meta: { title: '栏目详情', noLogin: true }
|
meta: { title: '栏目详情' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/GoodsDetail',
|
path: '/GoodsDetail',
|
||||||
name: 'GoodsDetail',
|
name: 'GoodsDetail',
|
||||||
component: () => import('./views/Goods/GoodsDetail.vue'),
|
component: () => import('./views/Goods/GoodsDetail.vue'),
|
||||||
meta: { title: '商品详情', noLogin: true, }
|
meta: { title: '商品详情' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/Category',
|
path: '/Category',
|
||||||
name: 'Category',
|
name: 'Category',
|
||||||
component: () => import('./views/Goods/Category.vue'),
|
component: () => import('./views/Goods/Category.vue'),
|
||||||
meta: { title: '全部分类', noLogin: true, }
|
meta: { title: '全部分类' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/Operations',
|
path: '/Operations',
|
||||||
@ -282,12 +268,6 @@ const routes = [
|
|||||||
component: () => import('./views/Merchant/MerchantIntroduction.vue'),
|
component: () => import('./views/Merchant/MerchantIntroduction.vue'),
|
||||||
meta: { title: '商家资料' }
|
meta: { title: '商家资料' }
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/PayCode',
|
|
||||||
name: 'PayCode',
|
|
||||||
component: () => import('./views/Merchant/PayCode.vue'),
|
|
||||||
meta: { title: '收款码' }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/QrReader',
|
path: '/QrReader',
|
||||||
name: 'QrReader',
|
name: 'QrReader',
|
||||||
@ -324,9 +304,6 @@ const routes = [
|
|||||||
path: '/SyncAuth',
|
path: '/SyncAuth',
|
||||||
name: 'SyncAuth',
|
name: 'SyncAuth',
|
||||||
component: () => import('./views/SyncAuth.vue'),
|
component: () => import('./views/SyncAuth.vue'),
|
||||||
meta: {
|
|
||||||
noLogin: true,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/404',
|
path: '/404',
|
||||||
@ -357,3 +334,19 @@ const router = createRouter({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|
||||||
|
// 全局前置守卫
|
||||||
|
router.beforeEach((to, from, next) => {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
if (to.meta.title) {
|
||||||
|
document.title = to.meta.title;
|
||||||
|
}
|
||||||
|
if (to.meta.noLogin) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
const isLogin = userStore.isLogin;
|
||||||
|
if (!isLogin) {
|
||||||
|
return next({ name: 'Login', query: { redirect: to.fullPath } });
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { get } from '@/api/http'
|
import { get } from '@/api/http'
|
||||||
|
|
||||||
|
// Module level cache for quick access
|
||||||
export let dictCache = {}
|
export let dictCache = {}
|
||||||
|
|
||||||
const SESSION_KEY = 'dict_cache'
|
|
||||||
|
|
||||||
export const useDatadicStore = defineStore('datadic', {
|
export const useDatadicStore = defineStore('datadic', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
dicts: {},
|
dicts: {},
|
||||||
@ -21,18 +20,6 @@ export const useDatadicStore = defineStore('datadic', {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async init() {
|
async init() {
|
||||||
// 优先从 sessionStorage 读取缓存
|
|
||||||
const cached = sessionStorage.getItem(SESSION_KEY)
|
|
||||||
if (cached) {
|
|
||||||
try {
|
|
||||||
dictCache = JSON.parse(cached)
|
|
||||||
this.dicts = dictCache
|
|
||||||
this.loaded = true
|
|
||||||
return
|
|
||||||
} catch (e) {
|
|
||||||
sessionStorage.removeItem(SESSION_KEY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.loaded) return
|
if (this.loaded) return
|
||||||
try {
|
try {
|
||||||
const res = await get('/v1/client/CDatadicsClient')
|
const res = await get('/v1/client/CDatadicsClient')
|
||||||
@ -42,7 +29,6 @@ export const useDatadicStore = defineStore('datadic', {
|
|||||||
})
|
})
|
||||||
this.dicts = dictCache
|
this.dicts = dictCache
|
||||||
this.loaded = true
|
this.loaded = true
|
||||||
sessionStorage.setItem(SESSION_KEY, JSON.stringify(dictCache))
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('数据字典加载失败', e)
|
console.error('数据字典加载失败', e)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { get } from '@/api/http';
|
import { post } from '@/api/http';
|
||||||
|
|
||||||
export const useUserStore = defineStore('user', {
|
export const useUserStore = defineStore('user', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@ -64,7 +64,7 @@ export const useUserStore = defineStore('user', {
|
|||||||
*/
|
*/
|
||||||
async fetchUserInfo() {
|
async fetchUserInfo() {
|
||||||
try {
|
try {
|
||||||
const res = await get('/v1/client/DUsersClient');
|
const res = await post('/v1/client/UserClient/info');
|
||||||
if (res.status === 200 && res.data) {
|
if (res.status === 200 && res.data) {
|
||||||
this.setUser(res.data);
|
this.setUser(res.data);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
.b_l_w;
|
.b_l_w;
|
||||||
.box;
|
.box;
|
||||||
.box-wrap;
|
.box-wrap;
|
||||||
padding: 12vw 0 0;
|
padding: 24vw 0 0;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
@ -78,20 +78,17 @@
|
|||||||
width: 3.73vw;
|
width: 3.73vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
span {
|
||||||
border: none;
|
margin-left: 2.67vw;
|
||||||
flex: 1;
|
font-size: 4vw;
|
||||||
padding: 3.33vw 1.2vw;
|
line-height: 6.67vw;
|
||||||
font-size: 3.47vw;
|
color: #222222;
|
||||||
color: #333;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:-ms-input-placeholder,
|
.input_box {
|
||||||
::-webkit-input-placeholder,
|
.box;
|
||||||
input::placeholder {
|
.box-align-center;
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hqyzm {
|
.hqyzm {
|
||||||
.bs;
|
.bs;
|
||||||
@ -105,8 +102,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.input_box {
|
input {
|
||||||
display: none;
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
padding: 3.33vw 0;
|
||||||
|
font-size: 3.47vw;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
:-ms-input-placeholder,
|
||||||
|
::-webkit-input-placeholder,
|
||||||
|
input::placeholder {
|
||||||
|
color: #999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,10 +134,6 @@
|
|||||||
.box-center-center;
|
.box-center-center;
|
||||||
margin-top: 5.6vw;
|
margin-top: 5.6vw;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
a {
|
|
||||||
color: #f00;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.toLogin {
|
.toLogin {
|
||||||
@ -315,12 +318,12 @@
|
|||||||
.box-align-center;
|
.box-align-center;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 4vw;
|
width: 3.73vw;
|
||||||
height: 4vw;
|
height: 3.73vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-size: 3.67vw;
|
font-size: 3.47vw;
|
||||||
margin-left: 1.6vw;
|
margin-left: 1.6vw;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
@ -384,17 +387,10 @@
|
|||||||
|
|
||||||
.fast_to {
|
.fast_to {
|
||||||
.box;
|
.box;
|
||||||
.box-tb;
|
|
||||||
.box-pack-between;
|
.box-pack-between;
|
||||||
width: 100%;
|
flex-wrap: wrap;
|
||||||
gap: 2.4vw;
|
gap: 2.4vw;
|
||||||
|
|
||||||
>div {
|
|
||||||
.box;
|
|
||||||
gap: 2.4vw;
|
|
||||||
// margin-bottom: 2.4vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 44.8vw;
|
width: 44.8vw;
|
||||||
height: 17.33vw;
|
height: 17.33vw;
|
||||||
@ -581,7 +577,7 @@
|
|||||||
padding-top: 4.8vw;
|
padding-top: 4.8vw;
|
||||||
border-radius: 2vw;
|
border-radius: 2vw;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
border: solid 1px #ffffff;
|
border: solid 0.13vw #ffffff;
|
||||||
|
|
||||||
.top {
|
.top {
|
||||||
.box;
|
.box;
|
||||||
@ -1058,7 +1054,7 @@
|
|||||||
padding: 2.93vw 2.67vw;
|
padding: 2.93vw 2.67vw;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: 3.33vw;
|
border-radius: 3.33vw;
|
||||||
border: solid 1px #85cb58;
|
border: solid 0.13vw #85cb58;
|
||||||
}
|
}
|
||||||
|
|
||||||
.choose {
|
.choose {
|
||||||
@ -1069,7 +1065,7 @@
|
|||||||
border-radius: 2vw;
|
border-radius: 2vw;
|
||||||
background: url(/img/gift_bg1.png);
|
background: url(/img/gift_bg1.png);
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
// border: solid 1px #85cb58;
|
// border: solid 0.13vw #85cb58;
|
||||||
padding: 4vw 4vw;
|
padding: 4vw 4vw;
|
||||||
margin-top: 6.53vw;
|
margin-top: 6.53vw;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -1221,7 +1217,7 @@
|
|||||||
.box-align-center;
|
.box-align-center;
|
||||||
padding-bottom: 3.33vw;
|
padding-bottom: 3.33vw;
|
||||||
margin-top: 3.33vw;
|
margin-top: 3.33vw;
|
||||||
border-bottom: solid 1px #33333380;
|
border-bottom: solid 0.13vw #33333380;
|
||||||
|
|
||||||
.img {
|
.img {
|
||||||
.box;
|
.box;
|
||||||
@ -2080,7 +2076,6 @@
|
|||||||
.banner img {
|
.banner img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 3.07vw;
|
margin-top: 3.07vw;
|
||||||
border-radius: 2.2vw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.label_box {
|
.label_box {
|
||||||
@ -2154,7 +2149,6 @@
|
|||||||
img {
|
img {
|
||||||
margin: 3.33vw 0 1.87vw;
|
margin: 3.33vw 0 1.87vw;
|
||||||
height: 14.4vw;
|
height: 14.4vw;
|
||||||
border-radius: 50%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2231,7 +2225,7 @@
|
|||||||
width: 26.4vw;
|
width: 26.4vw;
|
||||||
height: 26.4vw;
|
height: 26.4vw;
|
||||||
border-radius: 2.67vw;
|
border-radius: 2.67vw;
|
||||||
border: solid 1px #f7f7f7;
|
border: solid 0.13vw #f7f7f7;
|
||||||
margin-bottom: 1.73vw;
|
margin-bottom: 1.73vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2437,7 +2431,7 @@
|
|||||||
// position: absolute;
|
// position: absolute;
|
||||||
// left: 0;
|
// left: 0;
|
||||||
// top: 0;
|
// top: 0;
|
||||||
// width: 21px;
|
// width: 20.13vw;
|
||||||
// height: 100%;
|
// height: 100%;
|
||||||
// z-index: 1;
|
// z-index: 1;
|
||||||
// background: url(/img/mall_i35.png) no-repeat;
|
// background: url(/img/mall_i35.png) no-repeat;
|
||||||
@ -2466,7 +2460,6 @@
|
|||||||
.box;
|
.box;
|
||||||
.box-pack-between;
|
.box-pack-between;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
flex-direction: row;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.good {
|
.good {
|
||||||
@ -2480,7 +2473,7 @@
|
|||||||
|
|
||||||
>div {
|
>div {
|
||||||
padding: 0 3vw 3.6vw;
|
padding: 0 3vw 3.6vw;
|
||||||
// height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@ -2637,7 +2630,7 @@
|
|||||||
height: 6.13vw;
|
height: 6.13vw;
|
||||||
padding: 0 1.47vw;
|
padding: 0 1.47vw;
|
||||||
border-radius: 1.07vw;
|
border-radius: 1.07vw;
|
||||||
border: solid 1px #222222;
|
border: solid 0.13vw #222222;
|
||||||
color: #1b1b1b;
|
color: #1b1b1b;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
@ -3047,7 +3040,7 @@
|
|||||||
z-index: 3;
|
z-index: 3;
|
||||||
font-size: 3.33vw;
|
font-size: 3.33vw;
|
||||||
margin-bottom: 4vw;
|
margin-bottom: 4vw;
|
||||||
padding: 0 1px;
|
padding: 0 0.13vw;
|
||||||
// color: #474747;
|
// color: #474747;
|
||||||
// padding: 2.8vw 4.93vw 2.53vw 4.93vw;
|
// padding: 2.8vw 4.93vw 2.53vw 4.93vw;
|
||||||
|
|
||||||
@ -3175,7 +3168,7 @@
|
|||||||
// .item {
|
// .item {
|
||||||
// margin-top: 6vw;
|
// margin-top: 6vw;
|
||||||
// padding-bottom: 5.2vw;
|
// padding-bottom: 5.2vw;
|
||||||
// border-bottom: 1px solid #f5f5f5;
|
// border-bottom: 0.13vw solid #f5f5f5;
|
||||||
|
|
||||||
// >div {
|
// >div {
|
||||||
// .box;
|
// .box;
|
||||||
@ -3287,7 +3280,7 @@
|
|||||||
width: 13.33vw;
|
width: 13.33vw;
|
||||||
height: 5.33vw;
|
height: 5.33vw;
|
||||||
border-radius: 0.67vw;
|
border-radius: 0.67vw;
|
||||||
border: solid 1px #ffffff;
|
border: solid 0.13vw #ffffff;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@ -3332,7 +3325,7 @@
|
|||||||
.box;
|
.box;
|
||||||
.box-align-center;
|
.box-align-center;
|
||||||
border-radius: 0.67vw;
|
border-radius: 0.67vw;
|
||||||
border: solid 1px #ffffff;
|
border: solid 0.13vw #ffffff;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: #999999;
|
color: #999999;
|
||||||
@ -3389,7 +3382,7 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
background-color: #fff5f5;
|
background-color: #fff5f5;
|
||||||
border-radius: 2vw;
|
border-radius: 2vw;
|
||||||
border: solid 1px #fc6a39;
|
border: solid 0.13vw #fc6a39;
|
||||||
margin: 2.933vw 0;
|
margin: 2.933vw 0;
|
||||||
padding: 3.867vw;
|
padding: 3.867vw;
|
||||||
|
|
||||||
@ -3503,7 +3496,7 @@
|
|||||||
height: 6.67vw;
|
height: 6.67vw;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 1.07vw;
|
border-radius: 1.07vw;
|
||||||
border: solid 1px #000000;
|
border: solid 0.13vw #000000;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4841,7 +4834,7 @@
|
|||||||
// .bs;
|
// .bs;
|
||||||
|
|
||||||
b {
|
b {
|
||||||
font-size: 4vw;
|
font-size: 3.73vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
@ -4917,13 +4910,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.list_title {
|
.list_title {
|
||||||
font-size: 4vw !important;
|
font-size: 4vw;
|
||||||
margin: 4vw 0;
|
margin: 4vw 0;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
.van-tab {
|
|
||||||
font-size: 4vw !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
@ -5069,18 +5058,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
.box;
|
|
||||||
.box-tb;
|
|
||||||
.box-align-center;
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 4vw;
|
margin-top: 4vw;
|
||||||
padding: 0 4vw;
|
padding: 0 4vw;
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
.box;
|
.box;
|
||||||
.box-align-center;
|
.box-align-center;
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 4vw;
|
margin-bottom: 4vw;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@ -5459,7 +5442,7 @@
|
|||||||
width: max-content;
|
width: max-content;
|
||||||
height: 4.67vw;
|
height: 4.67vw;
|
||||||
border-radius: 1.33vw;
|
border-radius: 1.33vw;
|
||||||
border: solid 1px #e2593a;
|
border: solid 0.13vw #e2593a;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 4.67vw;
|
height: 4.67vw;
|
||||||
@ -5582,8 +5565,4 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.paycode-page {
|
|
||||||
.f5;
|
|
||||||
}
|
}
|
||||||
@ -51,15 +51,6 @@ img {
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v-html容器中img样式
|
|
||||||
.html,
|
|
||||||
.vhtml {
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
margin-top: 1.2vw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[v-cloak] {
|
[v-cloak] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
@ -547,9 +538,8 @@ img {
|
|||||||
>img {
|
>img {
|
||||||
width: 16vw;
|
width: 16vw;
|
||||||
height: 16vw;
|
height: 16vw;
|
||||||
border-radius: 50%;
|
.y50;
|
||||||
margin-right: 2.933vw;
|
margin-right: 2.933vw;
|
||||||
object-fit: contain;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
@ -894,29 +884,6 @@ img {
|
|||||||
padding-bottom: 2.53vw;
|
padding-bottom: 2.53vw;
|
||||||
border-bottom: 1px solid #f5f5f580;
|
border-bottom: 1px solid #f5f5f580;
|
||||||
|
|
||||||
.state {
|
|
||||||
.box;
|
|
||||||
.box-center-center;
|
|
||||||
.bs;
|
|
||||||
height: 4.67vw;
|
|
||||||
padding: 0 1.2vw;
|
|
||||||
border-radius: 1.07vw;
|
|
||||||
margin-right: 1.2vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.state1 {
|
|
||||||
background-color: #2990f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.state3 {
|
|
||||||
background-color: #ea4747;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.state4 {
|
|
||||||
background-color: #229427;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 3.2vw;
|
width: 3.2vw;
|
||||||
height: 3.2vw;
|
height: 3.2vw;
|
||||||
@ -926,7 +893,6 @@ img {
|
|||||||
|
|
||||||
.goods_box {
|
.goods_box {
|
||||||
.box;
|
.box;
|
||||||
.box-align-center;
|
|
||||||
margin-top: 2.8vw;
|
margin-top: 2.8vw;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@ -938,9 +904,9 @@ img {
|
|||||||
.goods_info {
|
.goods_info {
|
||||||
.box;
|
.box;
|
||||||
.box-tb;
|
.box-tb;
|
||||||
.box-pack-between;
|
.box-pack-around;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 18.33vw;
|
height: 21.33vw;
|
||||||
|
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
@ -1767,15 +1733,6 @@ img {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
._remark {
|
|
||||||
.box;
|
|
||||||
.box-align-center;
|
|
||||||
border-radius: 2vw;
|
|
||||||
padding: 3.333vw;
|
|
||||||
background: #fff;
|
|
||||||
margin-bottom: 4vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
>button {
|
>button {
|
||||||
.b_l_w;
|
.b_l_w;
|
||||||
margin: 3.333vw 0;
|
margin: 3.333vw 0;
|
||||||
@ -2237,15 +2194,6 @@ img {
|
|||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: 1.6vw;
|
border-radius: 1.6vw;
|
||||||
|
|
||||||
.vhtml {
|
|
||||||
padding: 3.33vw 0;
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
margin-top: 1.2vw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tit {
|
.tit {
|
||||||
.box;
|
.box;
|
||||||
.box-align-center;
|
.box-align-center;
|
||||||
@ -2350,55 +2298,31 @@ img {
|
|||||||
.box;
|
.box;
|
||||||
.box-tb;
|
.box-tb;
|
||||||
.box-align-center;
|
.box-align-center;
|
||||||
|
padding: 6.8vw 9.2vw;
|
||||||
width: 80vw;
|
width: 80vw;
|
||||||
min-width: 80vw;
|
min-width: 80vw;
|
||||||
max-width: 80vw;
|
max-width: 80vw;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
background-color: #ffffff;
|
||||||
border-radius: 2.67vw;
|
border-radius: 2.67vw;
|
||||||
|
|
||||||
.share_box {
|
.share_box {
|
||||||
.box;
|
.box;
|
||||||
.box-tb;
|
.box-tb;
|
||||||
margin: 0 auto;
|
.box-align-center;
|
||||||
padding: 6.8vw 9.2vw;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background-image: linear-gradient(180deg,
|
|
||||||
#f5cfd8 0%,
|
|
||||||
#fff4f4 100%);
|
|
||||||
border-radius: 2.67vw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom_box {
|
.logo {
|
||||||
.box;
|
height: 10.53vw;
|
||||||
.box-align-center;
|
margin-bottom: 4vw;
|
||||||
.box-pack-around;
|
|
||||||
width: 100%;
|
|
||||||
padding: 3.33vw 0;
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
width: 18.93vw;
|
|
||||||
height: 22.27vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qrcode {
|
|
||||||
.box;
|
|
||||||
.box-tb;
|
|
||||||
.box-align-center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 17.07vw;
|
|
||||||
height: 17.07vw;
|
|
||||||
margin-bottom: 1.2vw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.share_userinfo {
|
.share_userinfo {
|
||||||
.box;
|
.box;
|
||||||
.box-align-center;
|
.box-align-center;
|
||||||
margin: 0 auto;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
@ -2411,22 +2335,22 @@ img {
|
|||||||
.name {
|
.name {
|
||||||
.box;
|
.box;
|
||||||
.box-center-center;
|
.box-center-center;
|
||||||
.bs;
|
color: #222222;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
background-color: #841e36;
|
background-color: #fde5eb;
|
||||||
border-radius: 3.33vw;
|
border-radius: 3.33vw;
|
||||||
// padding: .667vw 0;
|
// padding: .667vw 0;
|
||||||
// padding: 1.2vw 4vw 6vw;
|
// padding: 1.2vw 4vw 6vw;
|
||||||
padding-left: 6vw;
|
padding-left: 6vw;
|
||||||
padding-right: 4vw;
|
padding-right: 4vw;
|
||||||
margin-left: -4.33vw;
|
margin-left: -3.33vw;
|
||||||
height: 8vw;
|
height: 8vw;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
line-height: 8vw;
|
line-height: 8vw;
|
||||||
// margin-bottom: 2.4vw;
|
margin-bottom: 2.4vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2453,30 +2377,28 @@ img {
|
|||||||
height: 8vw;
|
height: 8vw;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.price {
|
|
||||||
.box;
|
|
||||||
.box-align-center;
|
|
||||||
.box-pack-between;
|
|
||||||
width: 100%;
|
|
||||||
padding-bottom: 3.33vw;
|
|
||||||
border-bottom: 1px #fff solid;
|
|
||||||
|
|
||||||
.goods_price {
|
.goods_price {
|
||||||
font-size: 4vw;
|
margin-top: 1.33vw;
|
||||||
font-weight: bold;
|
|
||||||
color: #ea3e23;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.o_price {
|
.qrcode {
|
||||||
color: #b1b1b1;
|
.box;
|
||||||
text-decoration: line-through;
|
.box-tb;
|
||||||
|
.box-align-center;
|
||||||
|
margin-top: 3.33vw;
|
||||||
|
padding-bottom: 3vw;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 17.07vw;
|
||||||
|
height: 17.07vw;
|
||||||
|
margin-bottom: 1.2vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.share_result {
|
.share_result {
|
||||||
// margin-top: 4vw;
|
margin-top: 4vw;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
|||||||
@ -161,7 +161,6 @@ a {
|
|||||||
.box {
|
.box {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
// flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*从左至右*/
|
/*从左至右*/
|
||||||
|
|||||||
@ -1,108 +1,159 @@
|
|||||||
/**
|
/**
|
||||||
* HTML转图片工具
|
* HTML转图片工具
|
||||||
* 基于 html-to-image 将DOM元素转换为图片
|
* 基于 html2canvas + canvas2image
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { toCanvas } from 'html-to-image'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将DOM元素转换为图片
|
* 将HTML元素转换为canvas
|
||||||
* @param {string|HTMLElement} selector - DOM选择器或元素
|
* @param {HTMLElement} element - DOM元素
|
||||||
* @param {Object} options - 配置选项
|
* @param {Object} options - 配置参数
|
||||||
* @param {number} [options.width] - 自定义宽度(会应用到元素上)
|
* @param {number} [options.scale=2] - 缩放比例
|
||||||
* @param {number} [options.height] - 自定义高度(会应用到元素上)
|
* @param {number} [options.width] - 指定宽度
|
||||||
* @param {number} [options.canvasWidth] - 输出画布宽度
|
* @param {number} [options.height] - 指定高度
|
||||||
* @param {number} [options.canvasHeight] - 输出画布高度
|
* @param {boolean} [options.useCORS=true] - 是否支持跨域
|
||||||
* @param {number} [options.pixelRatio] - 像素比例,默认2
|
* @param {number} [options.dpi=window.devicePixelRatio] - DPI
|
||||||
* @param {boolean} [options.useCORS] - 是否允许跨域,默认true
|
* @returns {Promise<HTMLCanvasElement>}
|
||||||
* @param {string} [options.format] - 图片格式,'png'或'jpeg',默认'png'
|
|
||||||
* @param {number} [options.quality] - 图片质量,0-1,仅jpeg有效,默认1.0
|
|
||||||
* @returns {Promise<string>} - 返回base64图片数据URL
|
|
||||||
*/
|
*/
|
||||||
export async function toDataURL(selector, options = {}) {
|
export async function html2canvas(element, options = {}) {
|
||||||
const {
|
const {
|
||||||
width,
|
scale = 2,
|
||||||
height,
|
width,
|
||||||
canvasWidth,
|
height,
|
||||||
canvasHeight,
|
useCORS = true,
|
||||||
pixelRatio = 2,
|
dpi = window.devicePixelRatio,
|
||||||
useCORS = true,
|
onclone,
|
||||||
format = 'png',
|
} = options;
|
||||||
quality = 1.0
|
|
||||||
} = options
|
|
||||||
|
|
||||||
const element = typeof selector === 'string' ? document.querySelector(selector) : selector
|
const opts = {
|
||||||
if (!element) {
|
scale,
|
||||||
throw new Error('Element not found')
|
useCORS,
|
||||||
}
|
dpi,
|
||||||
|
logging: false,
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
};
|
||||||
|
|
||||||
const canvasEl = await toCanvas(element, {
|
if (width) opts.width = width;
|
||||||
width,
|
if (height) opts.height = height;
|
||||||
height,
|
|
||||||
canvasWidth,
|
|
||||||
canvasHeight,
|
|
||||||
pixelRatio,
|
|
||||||
cors: useCORS,
|
|
||||||
backgroundColor: '#ffffff',
|
|
||||||
fetchLikeCORS: true
|
|
||||||
})
|
|
||||||
|
|
||||||
const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png'
|
// 添加 onclone 回调用于调试
|
||||||
return canvasEl.toDataURL(mimeType, quality)
|
if (onclone) {
|
||||||
|
opts.onclone = onclone;
|
||||||
|
}
|
||||||
|
|
||||||
|
const html2canvasFn = window.html2canvas;
|
||||||
|
if (!html2canvasFn) {
|
||||||
|
throw new Error('html2canvas not loaded, please include html2canvas.min.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
return html2canvasFn(element, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将DOM元素转换为图片并下载
|
* 将canvas转换为dataURL
|
||||||
* @param {string|HTMLElement} selector - DOM选择器或元素
|
* @param {HTMLCanvasElement} canvas
|
||||||
* @param {string} [filename] - 下载文件名,不含扩展名
|
* @param {string} [type='image/png']
|
||||||
* @param {Object} options - 配置选项,同toDataURL
|
* @param {number} [quality=1.0]
|
||||||
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export async function toImageDownload(selector, filename = 'download', options = {}) {
|
export function canvasToDataURL(canvas, type = 'image/png', quality = 1.0) {
|
||||||
const dataUrl = await toDataURL(selector, options)
|
return canvas.toDataURL(type, quality);
|
||||||
|
|
||||||
const link = document.createElement('a')
|
|
||||||
link.download = filename + '.png'
|
|
||||||
link.href = dataUrl
|
|
||||||
document.body.appendChild(link)
|
|
||||||
link.click()
|
|
||||||
document.body.removeChild(link)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将DOM元素转换为Blob
|
* 将canvas转换为Blob
|
||||||
* @param {string|HTMLElement} selector - DOM选择器或元素
|
* @param {HTMLCanvasElement} canvas
|
||||||
* @param {Object} options - 配置选项,同toDataURL
|
* @param {string} [type='image/png']
|
||||||
|
* @param {number} [quality=1.0]
|
||||||
* @returns {Promise<Blob>}
|
* @returns {Promise<Blob>}
|
||||||
*/
|
*/
|
||||||
export async function toBlob(selector, options = {}) {
|
export function canvasToBlob(canvas, type = 'image/png', quality = 1.0) {
|
||||||
const dataUrl = await toDataURL(selector, options)
|
return new Promise((resolve, reject) => {
|
||||||
|
canvas.toBlob(blob => {
|
||||||
const arr = dataUrl.split(',')
|
if (blob) {
|
||||||
const mime = arr[0].match(/:(.*?);/)[1]
|
resolve(blob);
|
||||||
const bstr = atob(arr[1])
|
} else {
|
||||||
let n = bstr.length
|
reject(new Error('Canvas to Blob failed'));
|
||||||
const u8arr = new Uint8Array(n)
|
}
|
||||||
while (n--) {
|
}, type, quality);
|
||||||
u8arr[n] = bstr.charCodeAt(n)
|
});
|
||||||
}
|
|
||||||
return new Blob([u8arr], { type: mime })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 dataURL 直接下载图片
|
* 将HTML元素直接转成dataURL图片
|
||||||
|
* @param {HTMLElement} element - DOM元素
|
||||||
|
* @param {Object} options - html2canvas配置
|
||||||
|
* @param {string} [type='image/png'] - 图片类型
|
||||||
|
* @param {number} [quality=1.0] - 图片质量
|
||||||
|
* @returns {Promise<string>} dataURL
|
||||||
*/
|
*/
|
||||||
export function downloadByDataURL(dataUrl, filename = 'download') {
|
export async function htmlToDataURL(element, options = {}, type = 'image/png', quality = 1.0) {
|
||||||
const link = document.createElement('a')
|
const canvas = await html2canvas(element, options);
|
||||||
link.download = filename + '.png'
|
return canvasToDataURL(canvas, type, quality);
|
||||||
link.href = dataUrl
|
|
||||||
document.body.appendChild(link)
|
|
||||||
link.click()
|
|
||||||
document.body.removeChild(link)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
/**
|
||||||
toDataURL,
|
* 将HTML元素直接转成Blob
|
||||||
toImageDownload,
|
* @param {HTMLElement} element - DOM元素
|
||||||
toBlob,
|
* @param {Object} options - html2canvas配置
|
||||||
downloadByDataURL
|
* @param {string} [type='image/png'] - 图片类型
|
||||||
}
|
* @param {number} [quality=1.0] - 图片质量
|
||||||
|
* @returns {Promise<Blob>}
|
||||||
|
*/
|
||||||
|
export async function htmlToBlob(element, options = {}, type = 'image/png', quality = 1.0) {
|
||||||
|
const canvas = await html2canvas(element, options);
|
||||||
|
return canvasToBlob(canvas, type, quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载canvas为图片
|
||||||
|
* @param {HTMLCanvasElement} canvas
|
||||||
|
* @param {string} filename - 文件名(不带扩展名)
|
||||||
|
* @param {string} [type='png'] - 图片格式 ('png' | 'jpeg' | 'webp')
|
||||||
|
*/
|
||||||
|
export function downloadCanvas(canvas, filename, type = 'png') {
|
||||||
|
const mimeType = `image/${type}`;
|
||||||
|
const dataURL = canvasToDataURL(canvas, mimeType, 1.0);
|
||||||
|
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.download = `${filename}.${type}`;
|
||||||
|
link.href = dataURL;
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将HTML元素转成图片并下载
|
||||||
|
* @param {HTMLElement} element - DOM元素
|
||||||
|
* @param {string} filename - 文件名(不带扩展名)
|
||||||
|
* @param {Object} options - html2canvas配置
|
||||||
|
* @param {string} [type='png'] - 图片格式
|
||||||
|
*/
|
||||||
|
export async function htmlToImage(element, filename, options = {}, type = 'png') {
|
||||||
|
const canvas = await html2canvas(element, options);
|
||||||
|
downloadCanvas(canvas, filename, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将dataURL保存为图片文件
|
||||||
|
* @param {string} dataURL - 图片dataURL
|
||||||
|
* @param {string} filename - 文件名(不带扩展名)
|
||||||
|
*/
|
||||||
|
export function downloadDataURL(dataURL, filename) {
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.download = filename;
|
||||||
|
link.href = dataURL;
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将Blob保存为图片文件
|
||||||
|
* @param {Blob} blob - 图片Blob
|
||||||
|
* @param {string} filename - 文件名(不带扩展名)
|
||||||
|
*/
|
||||||
|
export async function downloadBlob(blob, filename) {
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.download = filename;
|
||||||
|
link.href = url;
|
||||||
|
link.click();
|
||||||
|
setTimeout(() => URL.revokeObjectURL(url), 100);
|
||||||
|
}
|
||||||
|
|||||||
@ -25,6 +25,9 @@
|
|||||||
<div class="line">
|
<div class="line">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i1.png" alt="">
|
<img src="/img/login-i1.png" alt="">
|
||||||
|
<span>手机号</span>
|
||||||
|
</div>
|
||||||
|
<div class="input_box">
|
||||||
<input type="tel" maxlength="11" :placeholder="active === 1 && !isReg ? '请输入手机号码作为账号' : '请输入手机号'"
|
<input type="tel" maxlength="11" :placeholder="active === 1 && !isReg ? '请输入手机号码作为账号' : '请输入手机号'"
|
||||||
v-model="formData.Phone" />
|
v-model="formData.Phone" />
|
||||||
<van-icon v-if="formData.Phone" @click="formData.Phone = ''" name="cross" size="5vw"></van-icon>
|
<van-icon v-if="formData.Phone" @click="formData.Phone = ''" name="cross" size="5vw"></van-icon>
|
||||||
@ -35,6 +38,9 @@
|
|||||||
<div class="line" v-if="active === 1 || isReg">
|
<div class="line" v-if="active === 1 || isReg">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i2.png" alt="">
|
<img src="/img/login-i2.png" alt="">
|
||||||
|
<span>验证码</span>
|
||||||
|
</div>
|
||||||
|
<div class="input_box">
|
||||||
<input type="text" placeholder="请输入验证码" v-model="formData.SmsCode" maxlength="6" />
|
<input type="text" placeholder="请输入验证码" v-model="formData.SmsCode" maxlength="6" />
|
||||||
<van-button class="hqyzm" @click="getSmsCode" :disabled="countdown.isCounting">
|
<van-button class="hqyzm" @click="getSmsCode" :disabled="countdown.isCounting">
|
||||||
{{ countdown.isCounting ? `已发送(${countdown.seconds}s)` : '获取验证码' }}
|
{{ countdown.isCounting ? `已发送(${countdown.seconds}s)` : '获取验证码' }}
|
||||||
@ -46,6 +52,9 @@
|
|||||||
<div class="line" v-if="active === 0 || isReg">
|
<div class="line" v-if="active === 0 || isReg">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i3.png" alt="">
|
<img src="/img/login-i3.png" alt="">
|
||||||
|
<span>密码</span>
|
||||||
|
</div>
|
||||||
|
<div class="input_box">
|
||||||
<input :type="showPassword ? 'text' : 'password'" placeholder="请输入密码" v-model="formData.Password"
|
<input :type="showPassword ? 'text' : 'password'" placeholder="请输入密码" v-model="formData.Password"
|
||||||
@keydown.enter="handleSubmit" />
|
@keydown.enter="handleSubmit" />
|
||||||
<van-icon @click="showPassword = !showPassword" :name="showPassword ? 'closed-eye' : 'eye-o'"
|
<van-icon @click="showPassword = !showPassword" :name="showPassword ? 'closed-eye' : 'eye-o'"
|
||||||
@ -57,6 +66,9 @@
|
|||||||
<div class="line" v-if="isReg">
|
<div class="line" v-if="isReg">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i4.png" alt="">
|
<img src="/img/login-i4.png" alt="">
|
||||||
|
<span>确认密码</span>
|
||||||
|
</div>
|
||||||
|
<div class="input_box">
|
||||||
<input :type="showConfirmPassword ? 'text' : 'password'" placeholder="请确认密码" v-model="formData.RePassword"
|
<input :type="showConfirmPassword ? 'text' : 'password'" placeholder="请确认密码" v-model="formData.RePassword"
|
||||||
@keydown.enter="handleSubmit" />
|
@keydown.enter="handleSubmit" />
|
||||||
<van-icon @click="showConfirmPassword = !showConfirmPassword"
|
<van-icon @click="showConfirmPassword = !showConfirmPassword"
|
||||||
@ -68,7 +80,10 @@
|
|||||||
<div class="line" v-if="isReg">
|
<div class="line" v-if="isReg">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i5.png" alt="">
|
<img src="/img/login-i5.png" alt="">
|
||||||
<input type="text" maxlength="11" placeholder="请填写邀请人账号(选填)" v-model="formData.Recommend" />
|
<span>邀请人</span>
|
||||||
|
</div>
|
||||||
|
<div class="input_box">
|
||||||
|
<input type="text" placeholder="请填写邀请人账号(选填)" v-model="formData.Recommend" />
|
||||||
<van-icon v-if="formData.Recommend" @click="formData.Recommend = ''" name="cross" size="5vw"></van-icon>
|
<van-icon v-if="formData.Recommend" @click="formData.Recommend = ''" name="cross" size="5vw"></van-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -80,7 +95,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 用户协议 -->
|
<!-- 用户协议 -->
|
||||||
<van-checkbox icon-size="3.2vw" class="agreement" v-model="checked" checked-color="#841e36">
|
<van-checkbox icon-size="2.667vw" class="agreement" v-model="checked" checked-color="#841e36">
|
||||||
选中即代表同意<a @click.stop="showContract = true">《用户协议》</a>和<a @click.stop="showPolicy = true">《隐私政策》</a>
|
选中即代表同意<a @click.stop="showContract = true">《用户协议》</a>和<a @click.stop="showPolicy = true">《隐私政策》</a>
|
||||||
</van-checkbox>
|
</van-checkbox>
|
||||||
|
|
||||||
@ -145,35 +160,42 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
// 防止刷新重复处理微信 code
|
|
||||||
if (sessionStorage.getItem('wx_code_processed') === '1') {
|
|
||||||
sessionStorage.removeItem('wx_code_processed')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 已登录,直接跳转
|
|
||||||
if (this.$isLogin?.()) {
|
if (this.$isLogin?.()) {
|
||||||
location.replace('#/')
|
location.replace('#/')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 小程序环境
|
// this.checkWxLogin();
|
||||||
if (this.$isWechatMini()) {
|
const code = JSON.stringify(this.$route.query.code);
|
||||||
wx.miniProgram.reLaunch({ url: `/pages/user/login` })
|
if (code) {
|
||||||
return
|
alert(code)
|
||||||
}
|
|
||||||
// 微信公众号环境:有 code 则等待登录后绑定,无 code 则跳转授权
|
this.$post('/v1/client/AuthClient/loginwxweb', { code }).then(res => {
|
||||||
if (this.$isWechat()) {
|
this.$showSuccessToast('登录成功')
|
||||||
if (sessionStorage.getItem('wx_callback_code')) {
|
if (res.data?.openid) {
|
||||||
// 有 code,等登录后用 token + code 绑定
|
localStorage.setItem('openid', res.data.openid)
|
||||||
} else {
|
}
|
||||||
this.checkWxLogin()
|
}).catch(err => {
|
||||||
}
|
alert(JSON.stringify(err))
|
||||||
return
|
this.$showFailToast(err.message || '微信登录失败')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
this.$closeSkeleton?.()
|
||||||
},
|
},
|
||||||
checkWxLogin() {
|
checkWxLogin() {
|
||||||
if (!this.$isWechat()) return
|
if (!this.$isWechat()) return
|
||||||
const REDIRECT_URI = encodeURIComponent('https://m.taigurun.cn/#/WxCallback')
|
if (this.$route.query.code) return
|
||||||
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxdff8dd2032f1e054&redirect_uri=${REDIRECT_URI}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`
|
// console.log(window.location.href);
|
||||||
|
|
||||||
|
this.$get('/v1/client/AuthClient/loginwxweburl', {
|
||||||
|
returnUrl: `${encodeURIComponent(window.location.href)}`
|
||||||
|
}).then(res => {
|
||||||
|
alert(JSON.stringify(res))
|
||||||
|
if (res.data) {
|
||||||
|
window.location.href = res.data
|
||||||
|
}
|
||||||
|
}).catch(res => {
|
||||||
|
alert(res)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
validatePhone(phone) {
|
validatePhone(phone) {
|
||||||
if (!phone) {
|
if (!phone) {
|
||||||
@ -195,6 +217,8 @@ export default {
|
|||||||
},
|
},
|
||||||
getSmsCode() {
|
getSmsCode() {
|
||||||
if (!this.validatePhone(this.formData.Phone)) return
|
if (!this.validatePhone(this.formData.Phone)) return
|
||||||
|
|
||||||
|
// 开始倒计时
|
||||||
this.countdown.isCounting = true
|
this.countdown.isCounting = true
|
||||||
this.countdown.seconds = 60
|
this.countdown.seconds = 60
|
||||||
this.countdown.timer = setInterval(() => {
|
this.countdown.timer = setInterval(() => {
|
||||||
@ -205,13 +229,14 @@ export default {
|
|||||||
clearInterval(this.countdown.timer)
|
clearInterval(this.countdown.timer)
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
this.$post('/v1/client/AuthClient/sendcode', {
|
this.$post('/v1/client/AuthClient/sendcode', {
|
||||||
purpose: this.isReg ? 'register' : 'login',
|
"purpose": this.isReg ? "register" : "login",
|
||||||
cellphone: this.formData.Phone
|
"cellphone": this.formData.Phone
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
if (data.status === 200) {
|
if (data.status === 200) {
|
||||||
this.$showSuccessToast?.('发送成功')
|
this.$showSuccessToast?.('发送成功')
|
||||||
this.smsCode = data.data
|
this.smsCode = data.data // 保存接口返回的验证码
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.countdown.isCounting = false
|
this.countdown.isCounting = false
|
||||||
@ -221,6 +246,7 @@ export default {
|
|||||||
handleSubmit() {
|
handleSubmit() {
|
||||||
if (!this.validatePhone(this.formData.Phone)) return
|
if (!this.validatePhone(this.formData.Phone)) return
|
||||||
if (!this.validateAgreement()) return
|
if (!this.validateAgreement()) return
|
||||||
|
|
||||||
if (this.isReg) {
|
if (this.isReg) {
|
||||||
this.handleRegister()
|
this.handleRegister()
|
||||||
} else {
|
} else {
|
||||||
@ -228,8 +254,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleLogin() {
|
handleLogin() {
|
||||||
|
// 账号密码登录
|
||||||
if (this.active === 0) {
|
if (this.active === 0) {
|
||||||
// 账号密码登录
|
|
||||||
if (!this.formData.Password) {
|
if (!this.formData.Password) {
|
||||||
this.$showFailToast?.('请输入密码')
|
this.$showFailToast?.('请输入密码')
|
||||||
return
|
return
|
||||||
@ -244,13 +270,18 @@ export default {
|
|||||||
this.$showFailToast?.(data.message)
|
this.$showFailToast?.(data.message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.afterLogin(data.data.token)
|
const userStore = useUserStore()
|
||||||
|
userStore.setToken(data.data.token)
|
||||||
|
userStore.fetchUserInfo()
|
||||||
|
this.$showSuccessToast?.(data.message)
|
||||||
|
location.replace('#/My')
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.$showFailToast?.(err.message || '登录失败')
|
this.$showFailToast?.(err.message || '登录失败')
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
// 手机验证码登录
|
// 手机验证码登录
|
||||||
|
else {
|
||||||
if (!this.formData.SmsCode) {
|
if (!this.formData.SmsCode) {
|
||||||
this.$showFailToast?.('请输入验证码')
|
this.$showFailToast?.('请输入验证码')
|
||||||
return
|
return
|
||||||
@ -266,57 +297,27 @@ export default {
|
|||||||
this.$showFailToast?.(data.message)
|
this.$showFailToast?.(data.message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.afterLogin(data.data.token)
|
const userStore = useUserStore()
|
||||||
|
userStore.setToken(data.data.token)
|
||||||
|
userStore.fetchUserInfo()
|
||||||
|
this.$showSuccessToast?.(data.message)
|
||||||
|
location.replace('#/My')
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.$showFailToast?.(err.message || '登录失败')
|
this.$showFailToast?.(err.message || '登录失败')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 登录/注册成功后的统一处理:存 token、拉用户信息、绑定微信 openid
|
|
||||||
afterLogin(token) {
|
|
||||||
const userStore = useUserStore()
|
|
||||||
userStore.setToken(token)
|
|
||||||
userStore.fetchUserInfo()
|
|
||||||
this.bindWxOpenid(token)
|
|
||||||
},
|
|
||||||
// 用 token + code 换 openid 并绑定
|
|
||||||
bindWxOpenid(token) {
|
|
||||||
const code = sessionStorage.getItem('wx_callback_code')
|
|
||||||
if (!code) {
|
|
||||||
this.$showSuccessToast?.('登录成功')
|
|
||||||
location.replace('#/My')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fetch(`${import.meta.env.VITE_API_URL}/v1/client/AuthClient/loginwxweb`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
body: JSON.stringify(code),
|
|
||||||
}).then(res =>
|
|
||||||
res.json()
|
|
||||||
).then(res => {
|
|
||||||
// alert(JSON.stringify(res))
|
|
||||||
sessionStorage.removeItem('wx_callback_code')
|
|
||||||
if (res.message) {
|
|
||||||
localStorage.setItem('openid', res.message)
|
|
||||||
// alert('微信账号绑定成功,openid:' + res.message)
|
|
||||||
}
|
|
||||||
this.$showSuccessToast?.('登录成功')
|
|
||||||
location.replace('#/My')
|
|
||||||
}).catch(() => {
|
|
||||||
sessionStorage.removeItem('wx_callback_code')
|
|
||||||
this.$showSuccessToast?.('登录成功')
|
|
||||||
location.replace('#/My')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleRegister() {
|
handleRegister() {
|
||||||
if (!this.formData.SmsCode) {
|
if (!this.formData.SmsCode) {
|
||||||
this.$showFailToast?.('请输入验证码')
|
this.$showFailToast?.('请输入验证码')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 验证用户输入的验证码与接口返回的是否一致
|
||||||
|
if (this.formData.SmsCode !== this.smsCode) {
|
||||||
|
this.$showFailToast?.('验证码错误')
|
||||||
|
return
|
||||||
|
}
|
||||||
if (!this.formData.Password) {
|
if (!this.formData.Password) {
|
||||||
this.$showFailToast?.('请输入密码')
|
this.$showFailToast?.('请输入密码')
|
||||||
return
|
return
|
||||||
@ -329,19 +330,22 @@ export default {
|
|||||||
this.$showFailToast?.('密码至少6位')
|
this.$showFailToast?.('密码至少6位')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.$post('/v1/client/AuthClient/register', {
|
this.$post('/v1/client/AuthClient/register', {
|
||||||
cellphone: this.formData.Phone,
|
cellphone: this.formData.Phone,
|
||||||
userpwd: this.formData.Password,
|
userpwd: this.formData.Password,
|
||||||
pcellphone: this.formData.Recommend,
|
pcellphone: this.formData.Recommend
|
||||||
code: this.formData.SmsCode
|
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (data.status !== 200) {
|
if (data.status !== 200) {
|
||||||
this.$showFailToast?.(data.message)
|
this.$showFailToast?.(data.message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.afterLogin(data.data.token)
|
const userStore = useUserStore()
|
||||||
|
userStore.setToken(data.data.token)
|
||||||
|
this.$showSuccessToast?.('注册成功')
|
||||||
|
location.replace('#/My')
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.$showFailToast?.(err.message || '注册失败')
|
this.$showFailToast?.(err.message || '注册失败')
|
||||||
@ -357,7 +361,7 @@ export default {
|
|||||||
this.formData.Recommend = inviteCode;
|
this.formData.Recommend = inviteCode;
|
||||||
localStorage.setItem('recommend', inviteCode);
|
localStorage.setItem('recommend', inviteCode);
|
||||||
// 有邀请码时自动切换到注册模式
|
// 有邀请码时自动切换到注册模式
|
||||||
// this.isReg = true;
|
this.isReg = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
|
|||||||
@ -13,6 +13,10 @@
|
|||||||
<div class="line">
|
<div class="line">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i1.png" alt="">
|
<img src="/img/login-i1.png" alt="">
|
||||||
|
<span>账号</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input_box">
|
||||||
<input type="phone" maxlength="11" placeholder="请输入账号(手机号)" v-model="data.cellphone"
|
<input type="phone" maxlength="11" placeholder="请输入账号(手机号)" v-model="data.cellphone"
|
||||||
onblur="window.scrollTo(0, 0);" />
|
onblur="window.scrollTo(0, 0);" />
|
||||||
<van-icon @click="data.cellphone = ''" name="cross" size="5vw"></van-icon>
|
<van-icon @click="data.cellphone = ''" name="cross" size="5vw"></van-icon>
|
||||||
@ -22,6 +26,10 @@
|
|||||||
<div class="line">
|
<div class="line">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i2.png" alt="">
|
<img src="/img/login-i2.png" alt="">
|
||||||
|
<span>验证码</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input_box">
|
||||||
<input type="text" placeholder="请输入验证码" v-model="data.code" maxlength="6"
|
<input type="text" placeholder="请输入验证码" v-model="data.code" maxlength="6"
|
||||||
onblur="window.scrollTo(0, 0);" />
|
onblur="window.scrollTo(0, 0);" />
|
||||||
<van-button class="hqyzm" @click="sendCode" :disabled="isSend">
|
<van-button class="hqyzm" @click="sendCode" :disabled="isSend">
|
||||||
@ -33,6 +41,10 @@
|
|||||||
<div class="line">
|
<div class="line">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i3.png" alt="">
|
<img src="/img/login-i3.png" alt="">
|
||||||
|
<span>密码</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input_box">
|
||||||
<input :type="show1 ? 'text' : 'password'" placeholder="请输入新的登录密码" v-model="data.password"
|
<input :type="show1 ? 'text' : 'password'" placeholder="请输入新的登录密码" v-model="data.password"
|
||||||
@keydown.enter="login" onblur="window.scrollTo(0, 0);" />
|
@keydown.enter="login" onblur="window.scrollTo(0, 0);" />
|
||||||
<van-icon @click="show1 = true" name="eye-o" size="5vw" v-if="!show1"></van-icon>
|
<van-icon @click="show1 = true" name="eye-o" size="5vw" v-if="!show1"></van-icon>
|
||||||
@ -43,6 +55,9 @@
|
|||||||
<div class="line">
|
<div class="line">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img src="/img/login-i4.png" alt="">
|
<img src="/img/login-i4.png" alt="">
|
||||||
|
<span>确认密码</span>
|
||||||
|
</div>
|
||||||
|
<div class="input_box">
|
||||||
<input :type="show2 ? 'text' : 'password'" placeholder="请再次输入登录密码" v-model="data.RePassword"
|
<input :type="show2 ? 'text' : 'password'" placeholder="请再次输入登录密码" v-model="data.RePassword"
|
||||||
@keydown.enter="login" onblur="window.scrollTo(0, 0);" />
|
@keydown.enter="login" onblur="window.scrollTo(0, 0);" />
|
||||||
<van-icon @click="show2 = true" name="eye-o" size="5vw" v-if="!show2"></van-icon>
|
<van-icon @click="show2 = true" name="eye-o" size="5vw" v-if="!show2"></van-icon>
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
<template></template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'WxCallback',
|
|
||||||
mounted() {
|
|
||||||
const url = new URL(window.location.href)
|
|
||||||
const code = url.searchParams.get('code')
|
|
||||||
const inviteCode = url.searchParams.get('invite')
|
|
||||||
|
|
||||||
if (code) {
|
|
||||||
sessionStorage.setItem('wx_callback_code', code)
|
|
||||||
// 带上 invite 参数一起跳转,Login mounted 时读取
|
|
||||||
this.$router.replace('/Login' + (inviteCode ? `?invite=${inviteCode}` : ''))
|
|
||||||
} else {
|
|
||||||
this.$router.replace('/')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -11,8 +11,12 @@
|
|||||||
<img :src="i.bankspname === '支付宝' ? '/img/aliicon.png' : '/img/bankcardicon.png'" alt="">
|
<img :src="i.bankspname === '支付宝' ? '/img/aliicon.png' : '/img/bankcardicon.png'" alt="">
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span>
|
||||||
{{ i.realname }}({{ i.bankcardnumber }})
|
{{ i.bankspname === '支付宝' ? '支付宝账号' : i.bankspname }}({{ i.bankid === 91 ? i.bankcellphone
|
||||||
|
: i.bankcardnumber }})
|
||||||
</span>
|
</span>
|
||||||
|
<p>
|
||||||
|
2小时内到账
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -34,9 +38,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn_box">
|
<div class="btn_box">
|
||||||
<!-- <button class="alipay" @click="showAddAliPayPopup = true">
|
<button class="alipay" @click="showAddAliPayPopup = true">
|
||||||
添加支付宝
|
添加支付宝
|
||||||
</button> -->
|
</button>
|
||||||
<button class="bankcard" @click="showAddPopup = true">
|
<button class="bankcard" @click="showAddPopup = true">
|
||||||
添加银行卡
|
添加银行卡
|
||||||
</button>
|
</button>
|
||||||
@ -93,10 +97,8 @@
|
|||||||
:formatter="formatter" />
|
:formatter="formatter" />
|
||||||
<van-field v-model="tempData.bankcardnumber" label="银行卡号" placeholder="请输入银行卡号"
|
<van-field v-model="tempData.bankcardnumber" label="银行卡号" placeholder="请输入银行卡号"
|
||||||
:rules="[{ required: true, message: '请填写银行卡号' }]" clearable required :formatter="formatter" />
|
:rules="[{ required: true, message: '请填写银行卡号' }]" clearable required :formatter="formatter" />
|
||||||
<!--
|
<van-field v-model="tempData.bankname" label="银行名称" placeholder="请输入银行名称"
|
||||||
<van-field v-model="tempData.bankname" label="银行名称" placeholder="请选择银行名称"
|
:rules="[{ required: true, message: '请填写银行名称' }]" clearable required />
|
||||||
:rules="[{ required: true, message: '请选择银行名称' }]" readonly required is-link
|
|
||||||
@click="showBankPicker = true" /> -->
|
|
||||||
<van-field v-model="regionName" label="开户地区" placeholder="请选择开户地区"
|
<van-field v-model="regionName" label="开户地区" placeholder="请选择开户地区"
|
||||||
:rules="[{ required: true, message: '请选择开户地区' }]" clearable required is-link @click="showRegion = true;"
|
:rules="[{ required: true, message: '请选择开户地区' }]" clearable required is-link @click="showRegion = true;"
|
||||||
readonly />
|
readonly />
|
||||||
@ -120,10 +122,6 @@
|
|||||||
<van-cascader v-model="region" title="请选择地区" :options="areaList" :field-names="defaultProps" @change="onChange"
|
<van-cascader v-model="region" title="请选择地区" :options="areaList" :field-names="defaultProps" @change="onChange"
|
||||||
@finish="onFinish" @close="showRegion = false" />
|
@finish="onFinish" @close="showRegion = false" />
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
<!-- <van-popup v-model:show="showBankPicker" round position="bottom">
|
|
||||||
<van-picker title="选择银行" :columns="bankColumns" @confirm="onBankConfirm" @cancel="showBankPicker = false" />
|
|
||||||
</van-popup> -->
|
|
||||||
</div>
|
</div>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
|
|
||||||
@ -136,6 +134,17 @@ export default {
|
|||||||
name: 'CashoutAccount',
|
name: 'CashoutAccount',
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init();
|
this.init();
|
||||||
|
this.getBankId()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'tempData.bankname': function (newVal) {
|
||||||
|
if (newVal && this.bankidGroup.length) {
|
||||||
|
const bank = this.bankidGroup.find(item => item.name.includes(newVal) || newVal.includes(item.name))
|
||||||
|
if (bank) {
|
||||||
|
this.tempData.bankid = bank.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -152,6 +161,7 @@ export default {
|
|||||||
maxDate: new Date('2099/12/31'),
|
maxDate: new Date('2099/12/31'),
|
||||||
regionName: '',
|
regionName: '',
|
||||||
region: '',
|
region: '',
|
||||||
|
bankidGroup: {},
|
||||||
areaList: useCascaderAreaData(),
|
areaList: useCascaderAreaData(),
|
||||||
defaultProps: {
|
defaultProps: {
|
||||||
text: 'text',
|
text: 'text',
|
||||||
@ -160,8 +170,6 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
this.$get('/v1/client/DUserbankcardsClient').then(data => {
|
this.$get('/v1/client/DUserbankcardsClient').then(data => {
|
||||||
@ -173,6 +181,11 @@ export default {
|
|||||||
formatter(value) {
|
formatter(value) {
|
||||||
return value.replace(/\s/g, '');
|
return value.replace(/\s/g, '');
|
||||||
},
|
},
|
||||||
|
getBankId() {
|
||||||
|
this.$get('/v1/client/DBanksClient').then(res => {
|
||||||
|
this.bankidGroup = res.data;
|
||||||
|
})
|
||||||
|
},
|
||||||
onChange({ selectedOptions }) {
|
onChange({ selectedOptions }) {
|
||||||
this.tempData.provid = selectedOptions[0]?.value || '';
|
this.tempData.provid = selectedOptions[0]?.value || '';
|
||||||
},
|
},
|
||||||
@ -220,7 +233,7 @@ export default {
|
|||||||
"realname": this.tempData.realname,
|
"realname": this.tempData.realname,
|
||||||
"idnumber": this.tempData.idnumber,
|
"idnumber": this.tempData.idnumber,
|
||||||
"bankid": this.tempData.bankid || 0,
|
"bankid": this.tempData.bankid || 0,
|
||||||
// "bankname": this.tempData.bankname || '',
|
"bankname": this.tempData.bankname || '',
|
||||||
"bankcardnumber": this.tempData.bankcardnumber,
|
"bankcardnumber": this.tempData.bankcardnumber,
|
||||||
"bankcellphone": this.tempData.bankcellphone,
|
"bankcellphone": this.tempData.bankcellphone,
|
||||||
"sort": 0,
|
"sort": 0,
|
||||||
@ -239,9 +252,6 @@ export default {
|
|||||||
this.$post('/v1/client/DUserbankcardsClient', params).then(res => {
|
this.$post('/v1/client/DUserbankcardsClient', params).then(res => {
|
||||||
this.$showSuccessToast('添加成功');
|
this.$showSuccessToast('添加成功');
|
||||||
this.tempData = {};
|
this.tempData = {};
|
||||||
this.regionName = '';
|
|
||||||
this.region = '';
|
|
||||||
this.checked = 0;
|
|
||||||
this.init();
|
this.init();
|
||||||
this.showAddPopup = false;
|
this.showAddPopup = false;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasePage>
|
<BasePage :back="back">
|
||||||
<van-tabs class="b_l_w f5" v-model:active="activeTab" animated :sticky="true" @change="onTabChange">
|
<van-tabs class="b_l_w f5" v-model:active="activeTab" animated :sticky="true" @change="onTabChange">
|
||||||
<van-tab title="全部" name=""></van-tab>
|
<van-tab title="全部" name=""></van-tab>
|
||||||
<van-tab v-for="item in states" :title="item.label" :name="item.value"></van-tab>
|
<van-tab v-for="item in states" :title="item.label" :name="item.value"></van-tab>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasePage :title="data.name || '产品详情'">
|
<BasePage>
|
||||||
<div class="goodsdetails">
|
<div class="goodsdetails">
|
||||||
<div class="t">
|
<div class="t">
|
||||||
<img :src="$file(data.img)" alt="">
|
<img :src="$file(data.img)" alt="">
|
||||||
@ -125,6 +125,8 @@
|
|||||||
|
|
||||||
<van-popup v-model:show="show" class="shareimgbox" style="max-width: 80vw;">
|
<van-popup v-model:show="show" class="shareimgbox" style="max-width: 80vw;">
|
||||||
<div class="share_box" id="bsCard">
|
<div class="share_box" id="bsCard">
|
||||||
|
<img class="logo" src="/img/logo-lr.png" alt="">
|
||||||
|
|
||||||
<div class="share_userinfo">
|
<div class="share_userinfo">
|
||||||
<img :src="$file($userInfo.userimg)" alt="">
|
<img :src="$file($userInfo.userimg)" alt="">
|
||||||
<div class="name"><span>{{ $userInfo.nickname }}友情推荐</span></div>
|
<div class="name"><span>{{ $userInfo.nickname }}友情推荐</span></div>
|
||||||
@ -133,24 +135,18 @@
|
|||||||
<div class="goods_info">
|
<div class="goods_info">
|
||||||
<img class="goods_img" :src="$file(data.img)" alt="">
|
<img class="goods_img" :src="$file(data.img)" alt="">
|
||||||
<div class="goods_name">{{ data.name }}</div>
|
<div class="goods_name">{{ data.name }}</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="price">
|
|
||||||
<div class="goods_price">¥{{ data.saleprice?.toFixed(2) || '0.00' }}</div>
|
<div class="goods_price">¥{{ data.saleprice?.toFixed(2) || '0.00' }}</div>
|
||||||
<div class="o_price">¥{{ data.originalprice?.toFixed(2) || '0.00' }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bottom_box">
|
<div class="qrcode">
|
||||||
<div class="qrcode">
|
<vue-qr :margin="0" :text="shareLink" backgroundColor="rgb(255,255,255)"
|
||||||
<vue-qr :margin="0" :text="shareLink" backgroundColor="#ffffff00" colorLight="rgb(255,255,255)"></vue-qr>
|
colorLight="rgb(255,255,255)"></vue-qr>
|
||||||
长按扫码购买
|
长按扫码购买
|
||||||
|
|
||||||
</div>
|
|
||||||
<img class="logo" src="/img/logo.png" alt="">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="share_result" v-if="ShareImg">
|
<div class="share_result" v-if="ShareImg">
|
||||||
<img :src="ShareImg" alt="分享海报">
|
<img :src="ShareImg" alt="分享海报">
|
||||||
|
<!-- <div class="tips">长按保存图片</div> -->
|
||||||
</div>
|
</div>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
@ -162,8 +158,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { html2canvas, canvasToDataURL } from '@/utils/html2image';
|
||||||
import { toDataURL } from '@/utils/html2image.js'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GoodsDetail',
|
name: 'GoodsDetail',
|
||||||
@ -187,9 +182,7 @@ export default {
|
|||||||
],
|
],
|
||||||
shareLink: '',
|
shareLink: '',
|
||||||
ShareImg: '',
|
ShareImg: '',
|
||||||
loading: false,
|
loading: false
|
||||||
transparent: 'rgba(0,0,0,0)',
|
|
||||||
shareBoxHidden: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -228,7 +221,10 @@ export default {
|
|||||||
|
|
||||||
let matchedSku = this.specCombinations.find(combo => {
|
let matchedSku = this.specCombinations.find(combo => {
|
||||||
return specKeys.every(key => {
|
return specKeys.every(key => {
|
||||||
return combo.skuname.includes(this.selectedSpecs[key]);
|
const spec = this.specSelect.find(s => s.name === key);
|
||||||
|
if (!spec) return false;
|
||||||
|
const specValue = this.selectedSpecs[key];
|
||||||
|
return combo.skuname === specValue;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -241,22 +237,12 @@ export default {
|
|||||||
this.showShare = false;
|
this.showShare = false;
|
||||||
if (option.name === "分享海报") {
|
if (option.name === "分享海报") {
|
||||||
this.show = true;
|
this.show = true;
|
||||||
// 如果图片已生成且元素已隐藏,直接显示,不重复生成
|
|
||||||
if (this.ShareImg && this.shareBoxHidden) {
|
|
||||||
this.loading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 如果图片已生成但元素未隐藏,先隐藏元素再显示
|
|
||||||
if (this.ShareImg) {
|
|
||||||
this.hideShareBox();
|
|
||||||
this.loading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
this.ShareImg = '';
|
||||||
// 等待 DOM 渲染后再生成
|
// 等待 DOM 渲染后再生成
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.generateShareImg();
|
this.generateShareImg();
|
||||||
}, 500);
|
}, 200);
|
||||||
} else if (option.name == "复制链接") {
|
} else if (option.name == "复制链接") {
|
||||||
this.$copyText(location.href);
|
this.$copyText(location.href);
|
||||||
this.$showToast({ type: "success", message: "复制成功" });
|
this.$showToast({ type: "success", message: "复制成功" });
|
||||||
@ -277,40 +263,23 @@ export default {
|
|||||||
async generateShareImg() {
|
async generateShareImg() {
|
||||||
var shareContent = document.querySelector('#bsCard');
|
var shareContent = document.querySelector('#bsCard');
|
||||||
if (!shareContent) return;
|
if (!shareContent) return;
|
||||||
|
var width = shareContent.offsetWidth;
|
||||||
|
var height = shareContent.offsetHeight;
|
||||||
try {
|
try {
|
||||||
// Wait for all images inside shareContent to load
|
var canvas = await html2canvas(shareContent, {
|
||||||
const images = shareContent.querySelectorAll('img');
|
scale: 2,
|
||||||
for (const img of images) {
|
width: width,
|
||||||
if (!img.complete) {
|
height: height,
|
||||||
await new Promise((resolve) => {
|
|
||||||
img.onload = resolve;
|
|
||||||
img.onerror = resolve;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for vue-qr to render
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
|
||||||
|
|
||||||
this.ShareImg = await toDataURL(shareContent, {
|
|
||||||
pixelRatio: 2,
|
|
||||||
useCORS: true,
|
useCORS: true,
|
||||||
format: 'png'
|
allowTaint: true,
|
||||||
});
|
});
|
||||||
this.hideShareBox();
|
this.ShareImg = canvasToDataURL(canvas, "image/png", 1.0);
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
document.querySelector('.share_box').style.display = 'none';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
hideShareBox() {
|
|
||||||
const shareBox = document.querySelector('.share_box');
|
|
||||||
if (shareBox) {
|
|
||||||
shareBox.style.display = 'none';
|
|
||||||
this.shareBoxHidden = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-view />
|
<router-view v-slot="{ Component, route }">
|
||||||
|
<keep-alive>
|
||||||
|
<component :is="Component" :key="route.name" v-if="route.meta.cache" />
|
||||||
|
</keep-alive>
|
||||||
|
<component :is="Component" :key="route.name" v-if="!route.meta.cache" />
|
||||||
|
</router-view>
|
||||||
<van-tabbar v-model="DefaultActive" placeholder @change="changeActive" active-color="#841e36" inactive-color="#1b1b1b"
|
<van-tabbar v-model="DefaultActive" placeholder @change="changeActive" active-color="#841e36" inactive-color="#1b1b1b"
|
||||||
fixed>
|
fixed>
|
||||||
<van-tabbar-item v-for="item in Tabbars" :key="item.Name" :name="item.Name" :badge="getBadge(item)" :dot="item.Dot"
|
<van-tabbar-item v-for="item in Tabbars" :key="item.Name" :name="item.Name" :badge="getBadge(item)" :dot="item.Dot"
|
||||||
@ -27,7 +32,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: 'Gift',
|
Name: 'Gift',
|
||||||
Label: '礼包区',
|
Label: '商品区',
|
||||||
Icon_Active: '/img/Gift_Active.png',
|
Icon_Active: '/img/Gift_Active.png',
|
||||||
Icon_Inactive: '/img/Gift_Inactive.png',
|
Icon_Inactive: '/img/Gift_Inactive.png',
|
||||||
},
|
},
|
||||||
@ -37,12 +42,6 @@ export default {
|
|||||||
Icon_Active: '/img/Mall_Active.png',
|
Icon_Active: '/img/Mall_Active.png',
|
||||||
Icon_Inactive: '/img/Mall_Inactive.png',
|
Icon_Inactive: '/img/Mall_Inactive.png',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: 'PointMall',
|
|
||||||
Label: '积分区',
|
|
||||||
Icon_Active: '/img/PointMall_Active.png',
|
|
||||||
Icon_Inactive: '/img/PointMall_Inactive.png',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: 'My',
|
Name: 'My',
|
||||||
Label: '我的',
|
Label: '我的',
|
||||||
@ -50,7 +49,7 @@ export default {
|
|||||||
Icon_Inactive: '/img/My_Inactive.png',
|
Icon_Inactive: '/img/My_Inactive.png',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route.path': {
|
'$route.path': {
|
||||||
@ -66,34 +65,21 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
updateActive() {
|
updateActive() {
|
||||||
const routeName = this.$route.name
|
const routeName = this.$route.name
|
||||||
if (routeName === 'PointMall') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const tabbar = this.Tabbars.find(item => item.Name === routeName)
|
const tabbar = this.Tabbars.find(item => item.Name === routeName)
|
||||||
if (tabbar) {
|
if (tabbar) {
|
||||||
this.DefaultActive = tabbar.Name
|
this.DefaultActive = tabbar.Name
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeActive(name) {
|
changeActive(name) {
|
||||||
if (name === 'PointMall') {
|
|
||||||
this.$showToast('暂未开放');
|
|
||||||
this.DefaultActive = this.$route.name; // 恢复之前的选项
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$router.push({ name })
|
this.$router.push({ name })
|
||||||
|
|
||||||
},
|
},
|
||||||
getBadge(item) {
|
getBadge(item) {
|
||||||
return item.Badge || ''
|
return item.Badge || ''
|
||||||
},
|
},
|
||||||
onTabClick(name) {
|
onTabClick(name) {
|
||||||
if (name === 'PointMall') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.$route.name === name) {
|
if (this.$route.name === name) {
|
||||||
// 当前路由,双击刷新
|
// 当前路由,双击刷新
|
||||||
// this.$router.replace({ name })
|
this.$router.replace({ name })
|
||||||
location.reload()
|
|
||||||
} else {
|
} else {
|
||||||
this.$router.push({ name })
|
this.$router.push({ name })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,53 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- <BasePage> -->
|
<BasePage>
|
||||||
<ManagerPopup v-model="managerPopupVisible" />
|
<ManagerPopup v-model="managerPopupVisible" />
|
||||||
<div class="merchant">
|
<div class="merchant">
|
||||||
<div class="shopinfo">
|
<div class="shopinfo">
|
||||||
<img class="tx" :src="$file(data.shopimg)">
|
<img class="tx" :src="$file(data.shopimg)">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<b>{{ truncatedShopname }}</b>
|
<b>{{ truncatedShopname }}</b>
|
||||||
<p>账号:{{ data.shopphone }}</p>
|
<p>账号:{{ data.shopphone }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="service-box" @click="$showManagerPopup()">
|
||||||
|
管理中心
|
||||||
|
<van-icon name="arrow"></van-icon>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="service-box" @click="$showManagerPopup()">
|
<div class="wallet">
|
||||||
管理中心
|
<div class="tit">
|
||||||
<van-icon name="arrow"></van-icon>
|
<span @click="$navigate('MerchantIncome')"> 营业收入(元) <van-icon name="arrow"></van-icon>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
<div class="line">
|
||||||
|
<b @click="$navigate('MerchantIncome')">
|
||||||
<div class="wallet">
|
{{ data.shangjiashouru?.toFixed(2) }}
|
||||||
<div class="tit">
|
</b>
|
||||||
<span @click="$navigate('MerchantIncome')"> 营业收入(元) <van-icon name="arrow"></van-icon>
|
<!-- v-if="data.Income" -->
|
||||||
</span>
|
<div @click="$navigate('MerchantCashout')">
|
||||||
<div class="line">
|
<span>提现中金额
|
||||||
<b @click="$navigate('MerchantIncome')">
|
</span>
|
||||||
{{ data.shangjiashouru?.toFixed(2) }}
|
<p>¥{{ data.withdrawing?.toFixed(2) }}</p>
|
||||||
</b>
|
</div>
|
||||||
<!-- v-if="data.Income" -->
|
</div>
|
||||||
<div @click="$navigate('MerchantCashout')">
|
</div>
|
||||||
<span>提现中金额
|
<div class="cc">
|
||||||
|
<div class="ll" @click="$navigate('Balance')">
|
||||||
|
<span>
|
||||||
|
可用余额<van-icon name="arrow"></van-icon>
|
||||||
</span>
|
</span>
|
||||||
<p>¥{{ data.withdrawing?.toFixed(2) }}</p>
|
<b>{{ data.keyongyue?.toFixed(2) }}</b>
|
||||||
|
</div>
|
||||||
|
<div class="ll" @click="$navigate('CV')">
|
||||||
|
<span>
|
||||||
|
会员卡额度<van-icon name="arrow"></van-icon>
|
||||||
|
</span>
|
||||||
|
<b>{{ data.huiyuanka?.toFixed(2) }}</b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cc">
|
|
||||||
<div class="ll" @click="$navigate('Balance')">
|
|
||||||
<span>
|
|
||||||
余额<van-icon name="arrow"></van-icon>
|
|
||||||
</span>
|
|
||||||
<b>{{ data.keyongyue?.toFixed(2) }}</b>
|
|
||||||
</div>
|
|
||||||
<div class="ll" @click="$navigate('CV')">
|
|
||||||
<span>
|
|
||||||
会员卡<van-icon name="arrow"></van-icon>
|
|
||||||
</span>
|
|
||||||
<b>{{ data.huiyuanka?.toFixed(2) }}</b>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <div class="block">
|
<!-- <div class="block">
|
||||||
<div class="d1" @click="$navigate('MerchantTrade')">
|
<div class="d1" @click="$navigate('MerchantTrade')">
|
||||||
<b>订单记录</b>
|
<b>订单记录</b>
|
||||||
<p>查看订单记录</p>
|
<p>查看订单记录</p>
|
||||||
@ -73,97 +73,104 @@
|
|||||||
|
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
<div class="fastTo">
|
<div class="fastTo">
|
||||||
<div class="ft1" @click="$navigate('PayCode?id=' + id)">
|
<div class="ft1" @click="showBottom = true">
|
||||||
<span>收款码</span>
|
<span>收款码</span>
|
||||||
<img src="/img/ft_i1.png" alt="">
|
<img src="/img/ft_i1.png" alt="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ft2" @click="$navigate('MerchantTrade')">
|
||||||
|
<span>订单记录</span>
|
||||||
|
<img src="/img/ft_i2.png" alt="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ft3" @click="$navigate('MerchantIntroduction')">
|
||||||
|
<span>商家资料</span>
|
||||||
|
<img src="/img/ft_i3.png" alt="">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ft2" @click="$navigate('MerchantTrade')">
|
<div class="countbox">
|
||||||
<span>订单记录</span>
|
<div class="title">
|
||||||
<img src="/img/ft_i2.png" alt="">
|
<b>经营数据</b>
|
||||||
|
</div>
|
||||||
|
<div class="box line">
|
||||||
|
<span>截止{{ data.endTimes }}</span>
|
||||||
|
<p class="refresh" @click="getCount">刷新</p>
|
||||||
|
<p class="cou r" @click="$navigate('Statistics')">统计<van-icon name="arrow"></van-icon></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list">
|
||||||
|
<div class="item">
|
||||||
|
<span>
|
||||||
|
今日营业额(元)
|
||||||
|
</span>
|
||||||
|
<b>{{ countData.todayyingyee?.toFixed(2) }}</b>
|
||||||
|
<p>昨日<span>{{ countData.yesterdayyingyee?.toFixed(2) }}</span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item">
|
||||||
|
<span>
|
||||||
|
今日应收(元)
|
||||||
|
</span>
|
||||||
|
<b>{{ countData.todayyingshou?.toFixed(2) }}</b>
|
||||||
|
<p>昨日<span>{{ countData.yesterdayingshou?.toFixed(2) }}</span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item">
|
||||||
|
<span>
|
||||||
|
今日订单数
|
||||||
|
</span>
|
||||||
|
<b>{{ countData.todaydingdanshu }}</b>
|
||||||
|
<p>昨日<span>{{ countData.yesterdaydingdanshu }}</span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item">
|
||||||
|
<span>
|
||||||
|
今日惠利金额(元)
|
||||||
|
</span>
|
||||||
|
<b>{{ countData.todayyouhui?.toFixed(2) }}</b>
|
||||||
|
<p>昨日<span>{{ countData.yesterdayyouhui?.toFixed(2) }}</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ft3" @click="$navigate('MerchantIntroduction')">
|
|
||||||
<span>商家资料</span>
|
|
||||||
<img src="/img/ft_i3.png" alt="">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="countbox">
|
<van-action-sheet v-model:show="showBottom" title="收款码" @click-overlay="onCloseBottom" @opened="onOpenBottom">
|
||||||
<div class="title">
|
<div class="paycode-wrap">
|
||||||
<b>经营数据</b>
|
<div class="paycode-original" ref="paycodeOriginal" v-show="!paycodeImg">
|
||||||
</div>
|
<img src="/img/paycode.jpg" alt="" style="width: 100%; display: block;">
|
||||||
<div class="box line">
|
<div class="info">
|
||||||
<span>截止{{ data.endTimes }}</span>
|
<img :src="$file(data.shopimg)" alt="" style="border-radius: 50%;">
|
||||||
<p class="refresh" @click="getCount">刷新</p>
|
</div>
|
||||||
<p class="cou r" @click="$navigate('Statistics')">统计<van-icon name="arrow"></van-icon></p>
|
<div class="name">
|
||||||
</div>
|
<span>{{ data.shopname }}</span>
|
||||||
|
</div>
|
||||||
<div class="list">
|
<div class="code">
|
||||||
<div class="item">
|
<vue-qr v-if="!loading" :margin="0" :text="link" backgroundColor="rgb(255,255,255)"
|
||||||
<span>
|
colorLight="rgb(255,255,255)"></vue-qr>
|
||||||
今日营业额(元)
|
</div>
|
||||||
</span>
|
|
||||||
<b>{{ countData.todayyingyee?.toFixed(2) }}</b>
|
|
||||||
<p>昨日<span>{{ countData.yesterdayyingyee?.toFixed(2) }}</span></p>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="paycode-result" v-if="paycodeImg">
|
||||||
<div class="item">
|
<img :src="paycodeImg" style="width: 100%;" alt="收款码">
|
||||||
<span>
|
|
||||||
今日应收(元)
|
|
||||||
</span>
|
|
||||||
<b>{{ countData.todayyingshou?.toFixed(2) }}</b>
|
|
||||||
<p>昨日<span>{{ countData.yesterdayingshou?.toFixed(2) }}</span></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="item">
|
|
||||||
<span>
|
|
||||||
今日订单数
|
|
||||||
</span>
|
|
||||||
<b>{{ countData.todaydingdanshu }}</b>
|
|
||||||
<p>昨日<span>{{ countData.yesterdaydingdanshu }}</span></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="item">
|
|
||||||
<span>
|
|
||||||
今日惠利金额(元)
|
|
||||||
</span>
|
|
||||||
<b>{{ countData.todayyouhui?.toFixed(2) }}</b>
|
|
||||||
<p>昨日<span>{{ countData.yesterdayyouhui?.toFixed(2) }}</span></p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</van-action-sheet>
|
||||||
|
</BasePage>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- </BasePage> -->
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { html2canvas } from '@/utils/html2image'
|
||||||
import ManagerPopup from "@/components/ManagerPopup.vue"
|
import ManagerPopup from "@/components/ManagerPopup.vue"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Merchant',
|
name: 'Merchant',
|
||||||
components: { ManagerPopup },
|
components: { ManagerPopup },
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$get('/v1/client/DUsersClient').then(res => {
|
this.init()
|
||||||
this.id = res.data.id;
|
|
||||||
if (!res.data.isshop) {
|
|
||||||
this.$showFailToast('您不是商家账号!')
|
|
||||||
// localStorage.removeItem('member_token')
|
|
||||||
location.replace('#/My')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.init();
|
|
||||||
}).catch(() => {
|
|
||||||
this.$showFailToast('登录状态异常,请重新登录')
|
|
||||||
// localStorage.removeItem('member_token')
|
|
||||||
location.replace('#/Login')
|
|
||||||
})
|
|
||||||
|
|
||||||
window.addEventListener('showManagerPopup', this.onShowManagerPopup)
|
window.addEventListener('showManagerPopup', this.onShowManagerPopup)
|
||||||
window.addEventListener('closeManagerPopup', this.onCloseManagerPopup)
|
window.addEventListener('closeManagerPopup', this.onCloseManagerPopup)
|
||||||
},
|
},
|
||||||
@ -174,11 +181,33 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
managerPopupVisible: false,
|
managerPopupVisible: false,
|
||||||
id: this.$route.query.id || this.$ls.get('user_id'),
|
showInfo: false,
|
||||||
|
showBottom: false,
|
||||||
|
paycodeImg: '',
|
||||||
|
isCapturing: false,
|
||||||
|
link: '',
|
||||||
|
id: this.$route.query.id,
|
||||||
data: {
|
data: {
|
||||||
|
id: 'merchant_001',
|
||||||
|
MerchantAvatar: '',
|
||||||
|
MerchantName: '泰古润直营店',
|
||||||
|
MerchantPhone: '13800138000',
|
||||||
|
Income: 12868.50,
|
||||||
|
Point: 5680.00,
|
||||||
|
TodayAmount: 5680.00,
|
||||||
|
YesterdayAmount: 4200.00,
|
||||||
|
TodayDeduct: 1280.00,
|
||||||
|
YesterdayDeduct: 980.00,
|
||||||
|
TodayQty: 45,
|
||||||
|
YesterdayQty: 38,
|
||||||
|
MonthIncome: 45600.00,
|
||||||
|
PrevMonthIncome: 38500.00,
|
||||||
endTimes: new Date().toLocaleString('zh-CN', { hour12: false })
|
endTimes: new Date().toLocaleString('zh-CN', { hour12: false })
|
||||||
},
|
},
|
||||||
countData: {},
|
countData: {},
|
||||||
|
States: 0,
|
||||||
|
expiring: 3,
|
||||||
|
loading: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -197,14 +226,87 @@ export default {
|
|||||||
init() {
|
init() {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
this.$get(`/v1/client/DShopsClient/${this.id}`).then(res => {
|
this.$get(`/v1/client/DShopsClient/${this.id}`).then(res => {
|
||||||
|
// console.log(res);
|
||||||
this.data = res.data;
|
this.data = res.data;
|
||||||
this.data.endTimes = new Date().toLocaleString('zh-CN', { hour12: false });
|
this.data.endTimes = new Date().toLocaleString('zh-CN', { hour12: false });
|
||||||
this.$ls.set('merchant_shopname', res.data.shopname);
|
this.$ls.set('merchant_shopname', res.data.shopname);
|
||||||
this.$ls.set('merchant_shopimg', res.data.shopimg);
|
this.$ls.set('merchant_shopimg', res.data.shopimg);
|
||||||
this.$ls.set('merchant_cellphone', res.data.cellphone);
|
this.$ls.set('merchant_cellphone', res.data.cellphone);
|
||||||
|
|
||||||
|
this.link = `${location.origin}${location.pathname}#/Checkout?id=${res.data.userid}`
|
||||||
}),
|
}),
|
||||||
this.getCount()
|
this.getCount()
|
||||||
])
|
]
|
||||||
|
)
|
||||||
|
},
|
||||||
|
async onOpenBottom() {
|
||||||
|
this.paycodeImg = ''
|
||||||
|
this.$nextTick(async () => {
|
||||||
|
const el = this.$refs.paycodeOriginal
|
||||||
|
if (!el) return
|
||||||
|
|
||||||
|
const scale = 2
|
||||||
|
const elRect = el.getBoundingClientRect()
|
||||||
|
|
||||||
|
// 不画全图,改为各部分分别截图再合成
|
||||||
|
// 创建最终画布
|
||||||
|
const canvas = document.createElement('canvas')
|
||||||
|
const w = el.offsetWidth * scale
|
||||||
|
const h = el.offsetHeight * scale
|
||||||
|
canvas.width = w
|
||||||
|
canvas.height = h
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
|
||||||
|
// 画背景图(只截取背景img)
|
||||||
|
const bg = el.querySelector('img')
|
||||||
|
const bgCanvas = await html2canvas(bg, { scale, useCORS: true, width: el.offsetWidth, height: el.offsetHeight })
|
||||||
|
ctx.drawImage(bgCanvas, 0, 0, w, h)
|
||||||
|
|
||||||
|
// 截取头像并画成圆形
|
||||||
|
const infoEl = el.querySelector('.info')
|
||||||
|
const avatarEl = infoEl.querySelector('img')
|
||||||
|
const avatarCanvas = await html2canvas(avatarEl, { scale, useCORS: true, backgroundColor: 'transparent' })
|
||||||
|
|
||||||
|
const infoRect = infoEl.getBoundingClientRect()
|
||||||
|
const avatarSize = 30 * scale
|
||||||
|
const avatarX = (infoRect.left - elRect.left) * scale
|
||||||
|
const avatarY = (infoRect.top - elRect.top) * scale
|
||||||
|
|
||||||
|
ctx.save()
|
||||||
|
ctx.beginPath()
|
||||||
|
ctx.arc(avatarX + avatarSize / 2, avatarY + avatarSize / 2, avatarSize / 2, 0, Math.PI * 2)
|
||||||
|
ctx.clip()
|
||||||
|
ctx.drawImage(avatarCanvas, avatarX, avatarY, avatarSize, avatarSize)
|
||||||
|
ctx.restore()
|
||||||
|
|
||||||
|
// 截取二维码
|
||||||
|
const codeEl = el.querySelector('.code')
|
||||||
|
const codeCanvas = await html2canvas(codeEl, { scale, useCORS: true, backgroundColor: '#ffffff' })
|
||||||
|
const codeRect = codeEl.getBoundingClientRect()
|
||||||
|
ctx.drawImage(
|
||||||
|
codeCanvas,
|
||||||
|
(codeRect.left - elRect.left) * scale,
|
||||||
|
(codeRect.top - elRect.top) * scale,
|
||||||
|
codeRect.width * scale,
|
||||||
|
codeRect.height * scale
|
||||||
|
)
|
||||||
|
|
||||||
|
// 画商户名文字 (根据.name样式定位)
|
||||||
|
const nameEl = el.querySelector('.name')
|
||||||
|
const nameRect = nameEl.getBoundingClientRect()
|
||||||
|
const fontSize = 20 * scale
|
||||||
|
ctx.font = `${fontSize}px 'PingFang SC'`
|
||||||
|
ctx.fillStyle = '#333'
|
||||||
|
ctx.textBaseline = 'middle'
|
||||||
|
if (this.data.shopname)
|
||||||
|
ctx.fillText(this.truncatedShopname, (nameRect.left - elRect.left) * scale, (nameRect.top - elRect.top) * scale + fontSize / 2)
|
||||||
|
|
||||||
|
this.paycodeImg = canvas.toDataURL('image/png')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onCloseBottom() {
|
||||||
|
this.showBottom = false
|
||||||
|
// this.paycodeImg = ''
|
||||||
},
|
},
|
||||||
getCount() {
|
getCount() {
|
||||||
this.$get('/v1/client/DShopsClient/statistics').then(res => {
|
this.$get('/v1/client/DShopsClient/statistics').then(res => {
|
||||||
@ -217,4 +319,52 @@ export default {
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less"></style>
|
<style lang="less">
|
||||||
|
.paycode-original {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
font-family: 'PingFang SC';
|
||||||
|
|
||||||
|
>img {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
left: 30.67vw;
|
||||||
|
top: 32.27vw;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 6.4vw;
|
||||||
|
height: 6.4vw;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
position: absolute;
|
||||||
|
left: 39.33vw;
|
||||||
|
top: 33.47vw;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 4vw;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
position: absolute;
|
||||||
|
top: 42.4vw;
|
||||||
|
left: 23.33vw;
|
||||||
|
|
||||||
|
canvas,
|
||||||
|
img {
|
||||||
|
width: 53.33vw;
|
||||||
|
height: 53.33vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,187 +0,0 @@
|
|||||||
<template>
|
|
||||||
<BasePage>
|
|
||||||
<div class="paycode-page">
|
|
||||||
<div class="paycode-wrap">
|
|
||||||
<!-- 生成后的图片 -->
|
|
||||||
<div v-if="generatedImage" class="paycode-generated">
|
|
||||||
<img :src="generatedImage" alt="收款码">
|
|
||||||
</div>
|
|
||||||
<!-- 原始元素 -->
|
|
||||||
<div v-else class="paycode-original" ref="paycodeOriginalRef">
|
|
||||||
<img src="/img/paycode.jpg" alt="" style="width: 100%; display: block;" class="bg-img" @load="onBgLoad">
|
|
||||||
<div class="user-info">
|
|
||||||
<div class="info">
|
|
||||||
<img :src="$file(shopimg)" alt="">
|
|
||||||
</div>
|
|
||||||
<div class="name">
|
|
||||||
<span>{{ shopname?.length > 8 ? shopname.slice(0, 8) + '...' : shopname }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="code">
|
|
||||||
<vue-qr v-if="link" :margin="0" :text="link" backgroundColor="rgb(255,255,255)"
|
|
||||||
colorLight="rgb(255,255,255)"></vue-qr>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="save-btn">
|
|
||||||
<van-button type="primary" color="#ca2904" round block :loading="loading" @click="handleSave">{{ loading ?
|
|
||||||
'生成中...' : ('保存图片')
|
|
||||||
}}</van-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</BasePage>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { toDataURL, downloadByDataURL } from '@/utils/html2image'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PayCode',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
shopname: '',
|
|
||||||
shopimg: '',
|
|
||||||
link: '',
|
|
||||||
loading: false,
|
|
||||||
generatedImage: '',
|
|
||||||
bgLoaded: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.init()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
init() {
|
|
||||||
const id = this.$route.query.id
|
|
||||||
this.$get(`/v1/client/DShopsClient/${id}`).then(res => {
|
|
||||||
this.shopname = res.data.shopname
|
|
||||||
this.shopimg = res.data.shopimg
|
|
||||||
this.link = `${location.origin}${location.pathname}#/Checkout?id=${res.data.userid}`
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.generateImage()
|
|
||||||
})
|
|
||||||
}).catch(err => {
|
|
||||||
this.$showFailToast('加载失败')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
onBgLoad() {
|
|
||||||
this.bgLoaded = true
|
|
||||||
},
|
|
||||||
|
|
||||||
async generateImage() {
|
|
||||||
if (this.loading) return
|
|
||||||
this.loading = true
|
|
||||||
try {
|
|
||||||
await this.$nextTick()
|
|
||||||
// Wait for fonts with fallback for WeChat/Safari compatibility
|
|
||||||
if (document.fonts && document.fonts.ready) {
|
|
||||||
await document.fonts.ready
|
|
||||||
}
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 500))
|
|
||||||
const el = this.$refs.paycodeOriginalRef
|
|
||||||
if (!el) {
|
|
||||||
throw new Error('Element not found')
|
|
||||||
}
|
|
||||||
this.generatedImage = await toDataURL(el, { format: 'png', pixelRatio: 3, useCORS: true })
|
|
||||||
} catch (e) {
|
|
||||||
console.error('生成收款码失败:', e)
|
|
||||||
this.$showFailToast('生成失败')
|
|
||||||
} finally {
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async handleSave() {
|
|
||||||
if (this.loading) return
|
|
||||||
try {
|
|
||||||
this.loading = true
|
|
||||||
if (!this.generatedImage) {
|
|
||||||
await this.generateImage()
|
|
||||||
}
|
|
||||||
if (this.generatedImage) {
|
|
||||||
downloadByDataURL(this.generatedImage, `收款码_${this.shopname}`)
|
|
||||||
this.$showSuccessToast('保存成功')
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('保存失败:', e)
|
|
||||||
this.$showFailToast('保存失败')
|
|
||||||
} finally {
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.paycode-page {
|
|
||||||
// min-height: 100vh;
|
|
||||||
background: #f5f5f5;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.paycode-generated {
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.paycode-original {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
font-family: 'PingFang SC';
|
|
||||||
|
|
||||||
>img {
|
|
||||||
width: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-info {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
top: 32.27vw;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 6.4vw;
|
|
||||||
height: 6.4vw;
|
|
||||||
// border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
margin-left: 2.67vw;
|
|
||||||
// margin-bottom: 2.4vw;
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size: 4vw;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.code {
|
|
||||||
position: absolute;
|
|
||||||
top: 42.4vw;
|
|
||||||
left: 23.33vw;
|
|
||||||
|
|
||||||
canvas,
|
|
||||||
img {
|
|
||||||
width: 53.33vw;
|
|
||||||
height: 53.33vw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-btn {
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,90 +1,90 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- <BasePage> -->
|
<BasePage>
|
||||||
<ManagerPopup v-model="managerPopupVisible" />
|
<ManagerPopup v-model="managerPopupVisible" />
|
||||||
<div class="opera">
|
<div class="opera">
|
||||||
|
|
||||||
<div class="top">
|
<div class="top">
|
||||||
<div class="info_box">
|
<div class="info_box">
|
||||||
<img class="icon" :src="$file(userimg || '/img/default-avatar.png')" alt="">
|
<img class="icon" :src="$file(userimg || '/img/default-avatar.png')" alt="">
|
||||||
<div class="inf">
|
<div class="inf">
|
||||||
<b>{{ nickname || '未登录' }}</b>
|
<b>{{ nickname || '未登录' }}</b>
|
||||||
<div>
|
<div>
|
||||||
<img src="/img/phone.png" alt="">
|
<img src="/img/phone.png" alt="">
|
||||||
{{ cellphone || '暂无手机号' }}
|
{{ cellphone || '暂无手机号' }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="shopcenter" @click="$showManagerPopup()">
|
||||||
|
<span>
|
||||||
|
管理中心
|
||||||
|
<van-icon name="arrow" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shopcenter" @click="$showManagerPopup()">
|
<div class="containar">
|
||||||
<span>
|
<div class="wallet_box">
|
||||||
管理中心
|
<div class="item" @click="$navigate('Balance')">
|
||||||
<van-icon name="arrow" />
|
<div class="t">
|
||||||
</span>
|
<img src="/img/op-i1.png" alt="">
|
||||||
</div>
|
<span>余额</span>
|
||||||
</div>
|
<van-icon name="arrow"></van-icon>
|
||||||
|
</div>
|
||||||
<div class="containar">
|
|
||||||
<div class="wallet_box">
|
|
||||||
<div class="item" @click="$navigate('Balance')">
|
|
||||||
<div class="t">
|
|
||||||
<img src="/img/op-i1.png" alt="">
|
|
||||||
<span>余额</span>
|
|
||||||
<van-icon name="arrow"></van-icon>
|
|
||||||
</div>
|
|
||||||
<b>
|
|
||||||
{{ zijin?.toFixed(2) || '0.00' }}
|
|
||||||
</b>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="item" @click="$navigate('CV')">
|
|
||||||
<div class="t">
|
|
||||||
<img src="/img/op-i2.png" alt="">
|
|
||||||
<span>会员卡</span>
|
|
||||||
<van-icon name="arrow"></van-icon>
|
|
||||||
</div>
|
|
||||||
<b>
|
|
||||||
{{ xiaofeiquan?.toFixed(2) || '0.00' }}
|
|
||||||
</b>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="fun_box">
|
|
||||||
<div class="item" @click="$navigate('QrReader')">
|
|
||||||
<div class="left">
|
|
||||||
<b>
|
<b>
|
||||||
扫一扫
|
{{ zijin?.toFixed(2) || '0.00' }}
|
||||||
</b>
|
</b>
|
||||||
<p>核销礼品券</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img src="/img/op-i3.png" alt="">
|
<div class="item" @click="$navigate('CV')">
|
||||||
|
<div class="t">
|
||||||
|
<img src="/img/op-i2.png" alt="">
|
||||||
|
<span>会员卡</span>
|
||||||
|
<van-icon name="arrow"></van-icon>
|
||||||
|
</div>
|
||||||
|
<b>
|
||||||
|
{{ xiaofeiquan?.toFixed(2) || '0.00' }}
|
||||||
|
</b>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item" @click="$navigate('CertificateRecord?type=verif')">
|
<div class="fun_box">
|
||||||
<div class="left">
|
<div class="item" @click="$navigate('QrReader')">
|
||||||
<b>
|
<div class="left">
|
||||||
核销记录
|
<b>
|
||||||
</b>
|
扫一扫
|
||||||
<p>查看礼品券核销记录</p>
|
</b>
|
||||||
|
<p>核销礼品券</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img src="/img/op-i3.png" alt="">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img src="/img/op-i4.png" alt="">
|
<div class="item" @click="$navigate('CertificateRecord?type=verif')">
|
||||||
</div>
|
<div class="left">
|
||||||
|
<b>
|
||||||
|
核销记录
|
||||||
|
</b>
|
||||||
|
<p>查看礼品券核销记录</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="item" @click="$navigate('Allow')">
|
<img src="/img/op-i4.png" alt="">
|
||||||
<div class="left">
|
|
||||||
<b>
|
|
||||||
业绩统计
|
|
||||||
</b>
|
|
||||||
<p>查看业绩统计数据</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img src="/img/op-i5.png" alt="">
|
<div class="item" @click="$navigate('Allow')">
|
||||||
|
<div class="left">
|
||||||
|
<b>
|
||||||
|
业绩统计
|
||||||
|
</b>
|
||||||
|
<p>查看业绩统计数据</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img src="/img/op-i5.png" alt="">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</BasePage>
|
||||||
<!-- </BasePage> -->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@ -6,14 +6,14 @@
|
|||||||
<!-- <img style="width: 26.4vw;" src="/img/bs-icon.png" alt=""> -->
|
<!-- <img style="width: 26.4vw;" src="/img/bs-icon.png" alt=""> -->
|
||||||
<div style="margin-top: 3vw;" class="box box-align-center">
|
<div style="margin-top: 3vw;" class="box box-align-center">
|
||||||
<van-tabs v-model:active="activeTab" color="#ca2904" title-active-color="#ca2904" class="tabs"
|
<van-tabs v-model:active="activeTab" color="#ca2904" title-active-color="#ca2904" class="tabs"
|
||||||
line-height="0.67vw" line-width="8vw" :ellipsis="false">
|
line-height="0.67vw" line-width="8vw" :ellipsis="false" @click-tab="changeTab(category.id)">
|
||||||
<van-tab v-for="category in categories" :key="category.id" :name="category.id"
|
<van-tab v-for="category in categories" :key="category.id" :name="category.id"
|
||||||
:title="category.name"></van-tab>
|
:title="category.name"></van-tab>
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
<!-- <img class="r" @click="showLeft = true" style="height: 4vw;" src="/img/filter.png" alt="filter"> -->
|
<!-- <img class="r" @click="showLeft = true" style="height: 4vw;" src="/img/filter.png" alt="filter"> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<BaseList cache-key="Business_School" :url="`/v1/client/CBusinessschoolsClient`" :params="params" class="list_item">
|
<BaseList :url="`/v1/client/CBusinessschoolsClient`" :params="params" class="list_item">
|
||||||
<template #default="{ item }">
|
<template #default="{ item }">
|
||||||
<div class="school-list" :key="item.id" @click="$navigate(`/School_Detail?id=${item.id}`)">
|
<div class="school-list" :key="item.id" @click="$navigate(`/School_Detail?id=${item.id}`)">
|
||||||
<div class="img">
|
<div class="img">
|
||||||
@ -28,7 +28,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="times">
|
<div class="times">
|
||||||
<span>{{ $formatGMT(item.addtime, 'yyyy-MM-dd HH:mm:ss') }}</span>
|
<span>{{ $formatGMT(item.addtime, 'yyyy-MM-dd HH:mm:ss') }}</span>
|
||||||
<span>阅览量 {{ item.click }}</span>
|
<span>阅览量 {{ item.ReadCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -80,7 +80,9 @@ export default {
|
|||||||
activeTab: 1,
|
activeTab: 1,
|
||||||
showLeft: false,
|
showLeft: false,
|
||||||
categories: [],
|
categories: [],
|
||||||
_categoriesCache: null,
|
params: {
|
||||||
|
pid: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -95,20 +97,19 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getList() {
|
getList() {
|
||||||
if (this._categoriesCache) {
|
|
||||||
this.categories = this._categoriesCache
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$get('/v1/client/CBusinessschoolcatesClient',).then(res => {
|
this.$get('/v1/client/CBusinessschoolcatesClient',).then(res => {
|
||||||
this.categories = res.data;
|
this.categories = res.data;
|
||||||
this._categoriesCache = res.data;
|
// console.log(this.categories);
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
|
||||||
changeTab(id) {
|
|
||||||
this.activeTab = id;
|
|
||||||
this.showLeft = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onTabClick({ name }) {
|
||||||
|
this.$navigate(`/School_Category?id=${name}`)
|
||||||
|
},
|
||||||
|
changeTab(id) {
|
||||||
|
this.activeTab = id;
|
||||||
|
this.showLeft = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- -->
|
<!-- :title="currentColumn.name || '栏目列表'" -->
|
||||||
<BasePage :title="currentColumn.name || ''">
|
<BasePage title="新闻列表">
|
||||||
<!-- <div class="column-list" v-if="currentColumn"> -->
|
<!-- <div class="column-list" v-if="currentColumn"> -->
|
||||||
<!-- v-if="currentColumn.ColumnType === 'list'" -->
|
<!-- v-if="currentColumn.ColumnType === 'list'" -->
|
||||||
<div class="column-list b_l_w" v-if="articleList.length > 0">
|
<div class="column-list">
|
||||||
<div>
|
<div>
|
||||||
<div @click="$navigate(`/ColumnDetail?id=${item.id}`)" class="column" v-for="item in articleList"
|
<div v-if="articleList.length > 0" @click="$navigate(`/ColumnDetail?id=${item.id}`)" class="column"
|
||||||
:key="item.id">
|
v-for="item in articleList" :key="item.id">
|
||||||
<img v-if="item.img" :src="$file(item.img)" class="icon" />
|
<img :src="$file(item.img)" class="icon" />
|
||||||
<div class="overview">
|
<div class="overview">
|
||||||
<span class="title">{{ item.name }}</span>
|
<span class="title">{{ item.name }}</span>
|
||||||
<div class="desc">
|
<div class="desc">
|
||||||
@ -19,7 +19,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<van-empty v-else class="b_l_w" description="暂无数据" />
|
<!-- <van-empty v-else class="b_l_w" description="暂无数据" /> -->
|
||||||
<!-- </div> -->
|
<!-- </div> -->
|
||||||
<!-- <van-empty v-else class="b_l_w" description="栏目不存在" /> -->
|
<!-- <van-empty v-else class="b_l_w" description="栏目不存在" /> -->
|
||||||
</BasePage>
|
</BasePage>
|
||||||
@ -30,10 +30,9 @@ export default {
|
|||||||
name: 'Column',
|
name: 'Column',
|
||||||
emits: ['updateShare'],
|
emits: ['updateShare'],
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$get(`/v1/client/CNewsClient?pid=${this.pid}`).then(data => {
|
this.$get('/v1/client/CNewsClient?pid=3').then(data => {
|
||||||
// console.log(data);
|
// console.log(data);
|
||||||
this.articleList = data.data.items;
|
this.articleList = data.data.items;
|
||||||
this.currentColumn.name = data.data.items[0].pidname;
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -41,8 +40,6 @@ export default {
|
|||||||
columns: [],
|
columns: [],
|
||||||
articles: [],
|
articles: [],
|
||||||
articleList: [],
|
articleList: [],
|
||||||
currentColumn: {},
|
|
||||||
pid: this.$route.query.pid || 3,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -50,11 +47,8 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style>
|
||||||
.column-list {
|
.column-list {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.column {
|
.column {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 3.333vw;
|
padding: 3.333vw;
|
||||||
|
|||||||
@ -31,17 +31,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const cacheKey = `ColumnDetail_${this.id}`
|
|
||||||
const cached = sessionStorage.getItem(cacheKey)
|
|
||||||
if (cached) {
|
|
||||||
try {
|
|
||||||
this.article = JSON.parse(cached)
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.setupImagePreview();
|
|
||||||
});
|
|
||||||
return
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
this.getDetail(this.id);
|
this.getDetail(this.id);
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.setupImagePreview();
|
this.setupImagePreview();
|
||||||
@ -51,7 +40,6 @@ export default {
|
|||||||
getDetail(id) {
|
getDetail(id) {
|
||||||
this.$get(`/v1/client/CNewsClient/${id}`).then(data => {
|
this.$get(`/v1/client/CNewsClient/${id}`).then(data => {
|
||||||
this.article = data.data;
|
this.article = data.data;
|
||||||
sessionStorage.setItem(`ColumnDetail_${id}`, JSON.stringify(data.data))
|
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
this.$showFailToast(err.message);
|
this.$showFailToast(err.message);
|
||||||
});
|
});
|
||||||
@ -103,13 +91,6 @@ export default {
|
|||||||
.content {
|
.content {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
padding: 3.333vw;
|
padding: 3.333vw;
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
display: block;
|
|
||||||
margin: 10px auto;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasePage :title="article.name">
|
<BasePage :title="article.Title">
|
||||||
<div class="b_l_w" style="padding: 3.333vw; border-bottom: 1px solid #ebedf0">
|
<div class="b_l_w" style="padding: 3.333vw; border-bottom: 1px solid #ebedf0">
|
||||||
<span style="font-size: 24px">{{ article.name }}</span>
|
<span style="font-size: 24px">{{ article.name }}</span>
|
||||||
<div style="display: flex; justify-content: space-between; margin-top: 12px">
|
<div style="display: flex; justify-content: space-between; margin-top: 12px">
|
||||||
@ -24,10 +24,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
const id = this.$route.query.id
|
this.$get(`/v1/client/CBusinessschoolsClient/${this.$route.query.id}`).then(res => {
|
||||||
this.$get(`/v1/client/CBusinessschoolsClient/${id}`).then(res => {
|
|
||||||
this.article = res.data;
|
this.article = res.data;
|
||||||
// sessionStorage.setItem(cacheKey, JSON.stringify(res.data))
|
// console.log(this.article);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -37,26 +36,26 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// setupImagePreview() {
|
setupImagePreview() {
|
||||||
// const contentEl = this.$refs.contentRef;
|
const contentEl = this.$refs.contentRef;
|
||||||
// if (!contentEl) return;
|
if (!contentEl) return;
|
||||||
|
|
||||||
// const images = contentEl.querySelectorAll('img');
|
const images = contentEl.querySelectorAll('img');
|
||||||
// this.imageUrls = Array.from(images).map(img => img.src);
|
this.imageUrls = Array.from(images).map(img => img.src);
|
||||||
|
|
||||||
// images.forEach((img, index) => {
|
images.forEach((img, index) => {
|
||||||
// img.addEventListener('click', () => {
|
img.addEventListener('click', () => {
|
||||||
// this.previewImages(index);
|
this.previewImages(index);
|
||||||
// });
|
});
|
||||||
// });
|
});
|
||||||
// },
|
},
|
||||||
// previewImages(startPosition) {
|
previewImages(startPosition) {
|
||||||
// this.$showImagePreview({
|
this.$showImagePreview({
|
||||||
// images: this.imageUrls,
|
images: this.imageUrls,
|
||||||
// startPosition,
|
startPosition,
|
||||||
// closeable: true,
|
closeable: true,
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -3,27 +3,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { useUserStore } from '@/stores/user'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.token) {
|
if (this.token)
|
||||||
localStorage.setItem('member_token', this.token)
|
localStorage.setItem('member_token', this.token);
|
||||||
const userStore = useUserStore()
|
// if (this.miniopenid)
|
||||||
userStore.setToken(this.token)
|
// localStorage.setItem('miniopenid', this.miniopenid);
|
||||||
setTimeout(() => {
|
if (this.target)
|
||||||
const target = this.target ? `/${this.target}` : '/Home'
|
location.replace(`#/${this.target}`);
|
||||||
// console.log(target);
|
else
|
||||||
|
location.replace('#/');
|
||||||
this.$router.replace(target)
|
|
||||||
}, 200)
|
|
||||||
} else {
|
|
||||||
this.$router.replace('/Home')
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
token: decodeURIComponent(this.$route.query.token || ''),
|
token: decodeURIComponent(this.$route.query.token || ''),
|
||||||
|
// miniopenid: decodeURIComponent(this.$route.query.miniopenid || ''),
|
||||||
target: decodeURIComponent(this.$route.query.target || ''),
|
target: decodeURIComponent(this.$route.query.target || ''),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
123
src/views/Tabbars/Agriculture.vue
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<div class="agriculture">
|
||||||
|
<div class="top">
|
||||||
|
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
|
||||||
|
<van-swipe-item>
|
||||||
|
<img style="width: 100%;" src="/img/agri_bg.png" alt="">
|
||||||
|
</van-swipe-item>
|
||||||
|
</van-swipe>
|
||||||
|
<div class="search">
|
||||||
|
<img src="/img/search-w.png" alt="">
|
||||||
|
<input type="text" placeholder="搜索您想要的产品">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tabs">
|
||||||
|
<van-tabs style="max-width: 90%;" line-height="0" v-model:active="active" :ellipsis="false"
|
||||||
|
title-active-color="#13774d" title-inactive-color="#4e4e4e">
|
||||||
|
<van-tab title="新品" name=""></van-tab>
|
||||||
|
<van-tab v-for="i in tabs" :name="i.id" :title="i.name"></van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
<img @click="showLeft = true" class="r" style="width: 5.4vw;" src="/img/filter.png" alt="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<BaseList url="/v1/client/EProsClient" class="goods_list" :params="{ mallstate: 2, pid: active }">
|
||||||
|
<template #default="{ item }">
|
||||||
|
<div class="goods_item" :key="item.id" @click="toDetail(item.id)">
|
||||||
|
<img :src="$file(item.img)" alt="">
|
||||||
|
<div>
|
||||||
|
<span class="title">{{ item.name }}</span>
|
||||||
|
<p>¥{{ item.originalprice }}</p>
|
||||||
|
<div class="money">
|
||||||
|
<div>
|
||||||
|
<span>¥
|
||||||
|
<b>{{ item.saleprice }}</b>.00
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img class="r" style="width: 5.6vw;" src="/img/cart.png" alt="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BaseList>
|
||||||
|
|
||||||
|
<!-- <div class="goods_list">
|
||||||
|
<div class="goods_item" v-for="item in goods" :key="item.id" @click="toDetail(item.id)">
|
||||||
|
<img :src="item.Icon" alt="">
|
||||||
|
<div>
|
||||||
|
<span class="title">{{ item.SubTitle }}</span>
|
||||||
|
<p>¥{{ item.OPrice }}</p>
|
||||||
|
<div class="money">
|
||||||
|
<div>
|
||||||
|
<span>¥
|
||||||
|
<b>{{ item.Price }}</b>.00
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img class="r" style="width: 5.6vw;" src="/img/cart.png" alt="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<van-popup v-model:show="showLeft" position="left" :style="{ width: '30%', height: '100%' }">
|
||||||
|
<div v-for="i in tabs">
|
||||||
|
<div @click="changeTab(i.id)" style="height: 10vw;width: 100%;border-bottom: solid 1px #f5f5f5;"
|
||||||
|
class="box box-center-center">
|
||||||
|
{{ i.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</van-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Agriculture',
|
||||||
|
activated() {
|
||||||
|
this.getTab()
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
active: '',
|
||||||
|
showLeft: false,
|
||||||
|
tabs: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTab()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTab() {
|
||||||
|
this.$get('/v1/client/EProcatesClient/2').then(res => {
|
||||||
|
this.tabs = res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
changeTab(id) {
|
||||||
|
this.active = id;
|
||||||
|
this.showLeft = false;
|
||||||
|
},
|
||||||
|
toDetail(e) {
|
||||||
|
this.$navigate(`/GoodsDetail?id=${e}`)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
filteredGoods() {
|
||||||
|
// if (this.active === 0) {
|
||||||
|
// return this.goods
|
||||||
|
// }
|
||||||
|
// const categoryId = this.active
|
||||||
|
// return this.goods.filter(item => item.CategoryId === categoryId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.finished-text {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -38,21 +38,33 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- v-if="selected.id" -->
|
<!-- v-if="selected.id" -->
|
||||||
<div class="detail" v-if="selected.id">
|
<div class="detail">
|
||||||
<div v-if="selected.jifen">
|
<!-- <div>
|
||||||
<span class="title">
|
<span class="title">
|
||||||
赠送积分数额
|
购买产品数量
|
||||||
</span>
|
</span>
|
||||||
<b class="r">
|
<span class="r">
|
||||||
{{ selected.jifen?.toFixed(2) }}
|
<van-stepper v-model="value" />
|
||||||
|
</span>
|
||||||
|
</div> -->
|
||||||
|
<div>
|
||||||
|
<span class="title">
|
||||||
|
赠送积分
|
||||||
|
</span>
|
||||||
|
<b class="r"> 1980.00
|
||||||
|
<!-- {{
|
||||||
|
// (selected.saleprice * value || 0)?.toFixed(2)
|
||||||
|
|
||||||
|
}} -->
|
||||||
</b>
|
</b>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="selected.huiyuanka">
|
<div>
|
||||||
<span class="title">
|
<span class="title">
|
||||||
赠送会员卡额
|
赠送会员卡额度
|
||||||
</span>
|
</span>
|
||||||
<b class="r">
|
<b class="r">
|
||||||
<span>¥</span> {{ selected.huiyuanka?.toFixed(2) }}
|
<!-- {{ (Number(selected.gongxianzhi) || 0)?.toFixed(2) }} -->
|
||||||
|
<span>¥</span> 6000.00
|
||||||
</b>
|
</b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -113,7 +125,7 @@
|
|||||||
|
|
||||||
<!-- <van-checkbox icon-size="2.667vw" class="agreement" v-model="checked" checked-color="#85cb58">
|
<!-- <van-checkbox icon-size="2.667vw" class="agreement" v-model="checked" checked-color="#85cb58">
|
||||||
已阅读并同意<a @click.stop="showContract = true">《保供臻选商务权益礼包电子协议》</a>
|
已阅读并同意<a @click.stop="showContract = true">《保供臻选商务权益礼包电子协议》</a>
|
||||||
</van-checkbox> -->
|
</van-checkbox> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- </div> -->
|
<!-- </div> -->
|
||||||
@ -128,7 +140,7 @@
|
|||||||
请选择礼包产品
|
请选择礼包产品
|
||||||
</div>
|
</div>
|
||||||
<b style="color: #f00;font-size: 3.2vw;">
|
<b style="color: #f00;font-size: 3.2vw;">
|
||||||
礼包产品为活动产品,不支持退货退款!
|
礼包产品一经售出概不退还
|
||||||
</b>
|
</b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -148,7 +160,7 @@
|
|||||||
<div class="name">
|
<div class="name">
|
||||||
<b>{{ item.name }}</b>
|
<b>{{ item.name }}</b>
|
||||||
<div class="text">
|
<div class="text">
|
||||||
{{ item.description }}
|
{{ item.skuname }}
|
||||||
<b style="line-height: 5.6vw;">
|
<b style="line-height: 5.6vw;">
|
||||||
<span><span>¥</span>{{ item.saleprice }}</span>
|
<span><span>¥</span>{{ item.saleprice }}</span>
|
||||||
<!-- <span> /{{ item.skuname }}</span> -->
|
<!-- <span> /{{ item.skuname }}</span> -->
|
||||||
@ -189,7 +201,7 @@
|
|||||||
<!-- <BasePwd v-model:show="showPayPwd" :title="`交易密码`" @val="submitOrder" /> -->
|
<!-- <BasePwd v-model:show="showPayPwd" :title="`交易密码`" @val="submitOrder" /> -->
|
||||||
|
|
||||||
<van-action-sheet v-model:show="showDetail" title="权益详情" style="min-height: 60vh;padding: 3.333vw;">
|
<van-action-sheet v-model:show="showDetail" title="权益详情" style="min-height: 60vh;padding: 3.333vw;">
|
||||||
<div class="w100 html" v-html="data.SpuDetail"></div>
|
<div class="w100" v-html="data.SpuDetail"></div>
|
||||||
</van-action-sheet>
|
</van-action-sheet>
|
||||||
|
|
||||||
<van-action-sheet v-model:show="showContract" safe-area-inset-bottom title="保供臻选商务权益礼包电子协议" closeable
|
<van-action-sheet v-model:show="showContract" safe-area-inset-bottom title="保供臻选商务权益礼包电子协议" closeable
|
||||||
@ -242,8 +254,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
Promise.all([
|
Promise.all([])
|
||||||
])
|
|
||||||
},
|
},
|
||||||
onAddressConfirm(address) {
|
onAddressConfirm(address) {
|
||||||
this.address.ReceiveName = address.ReceiveName;
|
this.address.ReceiveName = address.ReceiveName;
|
||||||
@ -272,17 +283,8 @@ export default {
|
|||||||
this.submitOrder();
|
this.submitOrder();
|
||||||
},
|
},
|
||||||
onShowDetail(e) {
|
onShowDetail(e) {
|
||||||
this.$get(`/v1/client/EProsClient/${e.id}`)
|
this.data.SpuDetail = e.SpuDetail;
|
||||||
.then(res => {
|
this.showDetail = true;
|
||||||
this.data.SpuDetail = res.data.contents;
|
|
||||||
this.showDetail = true;
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.$showFailToast('数据加载失败');
|
|
||||||
});
|
|
||||||
// this.data.SpuDetail = e.SpuDetail;
|
|
||||||
// this.spuid = e.id;
|
|
||||||
// this.showDetail = true;
|
|
||||||
},
|
},
|
||||||
onRefresh() {
|
onRefresh() {
|
||||||
this.$refs.BaseList.refresh()
|
this.$refs.BaseList.refresh()
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="index-page">
|
<div class="index-page">
|
||||||
<van-swipe v-if="data && data.Carousel" :autoplay="3000" indicator-color="white">
|
<van-swipe v-if="data && data.Carousel" @change="onSwipe" :autoplay="3000" indicator-color="white">
|
||||||
<van-swipe-item v-for="item in data.Carousel">
|
<van-swipe-item v-for="item in data.Carousel">
|
||||||
<a @click="item.link ? $openUrl(item.Url) : ''"><img :src="$file(item.img) || '/img/avatar.png'"
|
<a @click="item.link ? $openUrl(item.Url) : ''"><img :src="$file(item.img) || '/img/avatar.png'"
|
||||||
width="100%"></a>
|
width="100%"></a>
|
||||||
@ -16,13 +16,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<van-swipe vertical v-bind:touchable="false" class="notice-swipe" style="height: 12vw" :autoplay="3000"
|
<van-swipe vertical v-bind:touchable="false" class="notice-swipe" style="height: 12vw" :autoplay="3000"
|
||||||
v-bind:show-indicators="false">
|
v-bind:show-indicators="false">
|
||||||
<van-swipe-item class="v" style="height: 12vw; line-height: 6vw" v-for="(group, index) in trendsGrouped"
|
<van-swipe-item class="v" style="height: 12vw; line-height: 6vw" v-for="item in data.Trends" :key="index">
|
||||||
:key="index">
|
<a :key="item.id" @click="$navigate(`/ColumnDetail?id=${item.id}`)">
|
||||||
<template v-for="item in group">
|
<span></span>{{ item.name }}
|
||||||
<a @click="$navigate(`/Column?pid=2`)">
|
</a>
|
||||||
<span></span>{{ item.name }}
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
</van-swipe-item>
|
</van-swipe-item>
|
||||||
</van-swipe>
|
</van-swipe>
|
||||||
</div>
|
</div>
|
||||||
@ -30,7 +27,7 @@
|
|||||||
<div class="column3_part">
|
<div class="column3_part">
|
||||||
<div class="p1" @click="$navigate('/ColumnDetail?id=1')">
|
<div class="p1" @click="$navigate('/ColumnDetail?id=1')">
|
||||||
<img src="/img/index-column-i1.png">
|
<img src="/img/index-column-i1.png">
|
||||||
<span>平台介绍</span>
|
<span>公司介绍</span>
|
||||||
<p>了解泰古润</p>
|
<p>了解泰古润</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="p2" @click="$navigate('/Business_School')">
|
<div class="p2" @click="$navigate('/Business_School')">
|
||||||
@ -44,7 +41,7 @@
|
|||||||
</div> -->
|
</div> -->
|
||||||
<div class="p3" @click="$navigate('/Column?pid=3')">
|
<div class="p3" @click="$navigate('/Column?pid=3')">
|
||||||
<img src="/img/index-column-i4.png">
|
<img src="/img/index-column-i4.png">
|
||||||
<span>平台动态</span>
|
<span>公司动态</span>
|
||||||
<p>最新动态资讯</p>
|
<p>最新动态资讯</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -120,27 +117,33 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// import date from "../utils/date.js";
|
||||||
import date from "../../utils/date.js"
|
import date from "../../utils/date.js"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Home',
|
name: 'Home',
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init();
|
this.init();
|
||||||
|
this.data = { Carousel: [], News: [], Trends: [], Video: null };
|
||||||
|
this.options = [];
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
data: {},
|
data: {},
|
||||||
month: date.getMonth_C(),
|
month: date.getMonth_C(),
|
||||||
}
|
showcreate: false,
|
||||||
},
|
showcreateing: false,
|
||||||
computed: {
|
checked: 0,
|
||||||
trendsGrouped() {
|
tempData: {},
|
||||||
if (!this.data.Trends) return [];
|
|
||||||
const result = [];
|
showRegion: false,
|
||||||
for (let i = 0; i < this.data.Trends.length; i += 2) {
|
options: [],
|
||||||
result.push(this.data.Trends.slice(i, i + 2));
|
defaultProps: {
|
||||||
}
|
value: "id",
|
||||||
return result;
|
text: "name",
|
||||||
|
},
|
||||||
|
region: '',
|
||||||
|
loading: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -162,6 +165,94 @@ export default {
|
|||||||
this.$showFailToast(err.message || '数据加载失败');
|
this.$showFailToast(err.message || '数据加载失败');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
create() {
|
||||||
|
// this.showcreate = true;
|
||||||
|
this.$post('Member/GetApplyAgent').then(res => {
|
||||||
|
const data = res.data || res;
|
||||||
|
if (!data.AgentCode)
|
||||||
|
this.showcreate = true;
|
||||||
|
else {
|
||||||
|
this.showcreateing = true;
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
this.$showFailToast(err.message);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
changebox(e) {
|
||||||
|
this.checked = e;
|
||||||
|
this.tempData.AgentRegion = '';
|
||||||
|
this.tempData.AgentRegionName = '';
|
||||||
|
this.region = '';
|
||||||
|
},
|
||||||
|
onChange(e) {
|
||||||
|
if (e.selectedOptions.length > 0 && e.selectedOptions[0].level == 'province' && this.checked == 4) {
|
||||||
|
e.selectedOptions[e.tabIndex].children = null;
|
||||||
|
this.showRegion = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (e.selectedOptions.length > 1 && e.selectedOptions[1].level == 'city' && this.checked == 3) {
|
||||||
|
e.selectedOptions[e.tabIndex].children = null;
|
||||||
|
this.showRegion = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (e.selectedOptions.length > 2 && e.selectedOptions[2].level == 'district' && this.checked == 2) {
|
||||||
|
e.selectedOptions[e.tabIndex].children = null;
|
||||||
|
this.showRegion = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.selectedOptions[e.tabIndex].leaf) {
|
||||||
|
e.selectedOptions[e.tabIndex].children = null;
|
||||||
|
this.showRegion = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!e.selectedOptions[e.tabIndex].children || e.selectedOptions[e.tabIndex].children.length == 0) {
|
||||||
|
this.$post('Common/GetRegions', { value: e.value }).then(res => {
|
||||||
|
const data = res.data || res;
|
||||||
|
if (data.length > 0) {
|
||||||
|
data.forEach(x => { x.children = [] });
|
||||||
|
e.selectedOptions[e.tabIndex].children = data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
e.selectedOptions[e.tabIndex].children = null;
|
||||||
|
this.showRegion = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFinish(e) {
|
||||||
|
this.showRegion = false;
|
||||||
|
this.tempData.AgentRegion = e.selectedOptions.map(x => x.id).join(';');
|
||||||
|
this.tempData.AgentRegionName = e.selectedOptions.map(x => x.name).join('');
|
||||||
|
},
|
||||||
|
submit() {
|
||||||
|
if (!this.tempData.AgentName) {
|
||||||
|
this.$showFailToast('请输入姓名');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.tempData.AgentPhone) {
|
||||||
|
this.$showFailToast('请输入手机号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.$validPhone(this.tempData.AgentPhone)) {
|
||||||
|
this.$showFailToast('手机号格式错误');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.tempData.AgentRegion) {
|
||||||
|
this.$showFailToast('请选择共创区域');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.loading = true;
|
||||||
|
this.$post('Member/ApplyAgent', this.tempData).then(res => {
|
||||||
|
this.tempData = {};
|
||||||
|
this.$showSuccessToast('提交成功');
|
||||||
|
this.showcreate = false;
|
||||||
|
}).catch(err => {
|
||||||
|
this.$showFailToast(err.message);
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -5,7 +5,7 @@
|
|||||||
<img src="/img/search.png" alt="">
|
<img src="/img/search.png" alt="">
|
||||||
<input v-model="searchParams.Key" placeholder="请输入关键词搜索"
|
<input v-model="searchParams.Key" placeholder="请输入关键词搜索"
|
||||||
@search="$navigate('Category?Key=' + searchParams.Key)">
|
@search="$navigate('Category?Key=' + searchParams.Key)">
|
||||||
<button @click="$navigate('Category?Key=' + searchParams.Key)" :style="btnStyle">搜索</button>
|
<button @click="$navigate('Category?Key=' + searchParams.Key)">搜索</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="banner">
|
<div class="banner">
|
||||||
<van-swipe :autoplay="3000" indicator-color="white" @change="onSwipeChange">
|
<van-swipe :autoplay="3000" indicator-color="white" @change="onSwipeChange">
|
||||||
@ -15,7 +15,26 @@
|
|||||||
</van-swipe-item>
|
</van-swipe-item>
|
||||||
</van-swipe>
|
</van-swipe>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- <div class="label_box">
|
||||||
|
<div class="">
|
||||||
|
<img src="/img/mall_i1.png" alt="">
|
||||||
|
<span>
|
||||||
|
官方商城
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<img src="/img/mall_i2.png" alt="">
|
||||||
|
<span>
|
||||||
|
正品保障
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<img src="/img/mall_i3.png" alt="">
|
||||||
|
<span>
|
||||||
|
售后无忧
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cg_bigbox">
|
<div class="cg_bigbox">
|
||||||
@ -199,15 +218,21 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'Mall',
|
name: 'Mall',
|
||||||
|
// emits: ['changeTabbar'],
|
||||||
|
activated() {
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeType: '',
|
activeType: '',
|
||||||
searchParams: {
|
searchParams: {
|
||||||
mallstate: 3,
|
mallstate: 3,
|
||||||
pid: '',
|
pid: '',
|
||||||
Key: '',
|
|
||||||
},
|
},
|
||||||
|
show: true,
|
||||||
data: {
|
data: {
|
||||||
Carousel: [],
|
Carousel: [],
|
||||||
SpuType: [],
|
SpuType: [],
|
||||||
@ -217,66 +242,53 @@ export default {
|
|||||||
bgcolor: '',
|
bgcolor: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
activated() {
|
|
||||||
this.$refs.BaseList?.refresh()
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.init()
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
this.$get('/v1/client/EProcatesClient').then(res => {
|
this.$get(`/v1/client/EProcatesClient`).then(res => {
|
||||||
this.data.SpuType = res.data.filter(i => i.homeshowed)
|
this.data.SpuType = res.data
|
||||||
}),
|
}),
|
||||||
this.$get('/v1/client/CSlidesClient?pid=2').then(res => {
|
this.$get(`/v1/client/CSlidesClient?pid=2`).then(res => {
|
||||||
this.data.Carousel = res.data
|
this.data.Carousel = res.data
|
||||||
this.bgcolor = res.data?.[0]?.bgcolor || ''
|
if (res.data?.[0]?.bgcolor) {
|
||||||
}),
|
this.bgcolor = res.data[0].bgcolor
|
||||||
this.$get('/v1/client/EProsClient?recommend=true').then(res => {
|
|
||||||
this.hotData = res.data.items || []
|
|
||||||
}),
|
|
||||||
this.$get('/v1/client/EProcatesClient/1').then(res => {
|
|
||||||
const filtered = res.data.filter(i => i.homeshowed)
|
|
||||||
this.typeData = filtered
|
|
||||||
if (filtered.length > 0) {
|
|
||||||
this.activeType = filtered[0].id
|
|
||||||
this.searchParams.pid = filtered[0].id
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
this.$get('/v1/client/EProsClient?recommend=true').then(res => {
|
||||||
|
this.hotData = res.data.items;
|
||||||
|
}),
|
||||||
|
this.$get('/v1/client/EProcatesClient/1').then(res => {
|
||||||
|
this.typeData = res.data
|
||||||
|
this.searchParams.pid = res.data?.[0]?.id || ''
|
||||||
|
}),
|
||||||
]).catch(err => {
|
]).catch(err => {
|
||||||
this.$showFailToast(err.message || '加载失败')
|
});
|
||||||
})
|
},
|
||||||
|
groupItems(items, num) {
|
||||||
|
const grouped = [];
|
||||||
|
for (let i = 0; i < items.length; i += num) {
|
||||||
|
grouped.push(items.slice(i, i + num));
|
||||||
|
}
|
||||||
|
return grouped;
|
||||||
},
|
},
|
||||||
|
|
||||||
changeTab(type) {
|
changeTab(type) {
|
||||||
this.searchParams.pid = type
|
this.searchParams.pid = type;
|
||||||
|
this.$refs.BaseList.refresh()
|
||||||
},
|
},
|
||||||
|
|
||||||
onSwipeChange(index) {
|
onSwipeChange(index) {
|
||||||
this.bgcolor = this.data.Carousel[index]?.bgcolor || ''
|
const item = this.data.Carousel[index]
|
||||||
},
|
this.bgcolor = item?.bgcolor || ''
|
||||||
|
}
|
||||||
onSearch() {
|
|
||||||
this.$refs.BaseList?.refresh()
|
|
||||||
},
|
|
||||||
|
|
||||||
onClear() {
|
|
||||||
this.searchParams.Key = ''
|
|
||||||
this.$refs.BaseList?.refresh()
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
bgStyle() {
|
bgStyle() {
|
||||||
return this.bgcolor ? { background: `linear-gradient(${this.bgcolor}, #f5f5f5)` } : {}
|
if (this.bgcolor) {
|
||||||
},
|
return {
|
||||||
btnStyle() {
|
background: `linear-gradient(${this.bgcolor}, #f5f5f5)`
|
||||||
return this.bgcolor ? { background: this.bgcolor } : {}
|
}
|
||||||
},
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,290 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="pointmall">
|
|
||||||
<div class="top">
|
|
||||||
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
|
|
||||||
<van-swipe-item>
|
|
||||||
<img style="width: 100%;" src="/img/pointmall_bg.jpg" alt="">
|
|
||||||
</van-swipe-item>
|
|
||||||
</van-swipe>
|
|
||||||
<!-- <div class="search">
|
|
||||||
<img src="/img/search-w.png" alt="">
|
|
||||||
<input type="text" placeholder="搜索您想要的产品">
|
|
||||||
</div> -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="contaiar">
|
|
||||||
<div class="tabs">
|
|
||||||
<van-tabs style="max-width: 90%;" background="transparent" line-height="0.8vw" line-width="9.33vw;"
|
|
||||||
v-model:active="active" :ellipsis="false" color="#ca2904" title-active-color="#ca2904"
|
|
||||||
title-inactive-color="#4e4e4e">
|
|
||||||
<van-tab title="新品" name=""></van-tab>
|
|
||||||
<van-tab v-for="i in tabs" :name="i.id" :title="i.name"></van-tab>
|
|
||||||
</van-tabs>
|
|
||||||
<img @click="showLeft = true" class="filter_img" style="width: 5.4vw;" src="/img/filter.png" alt="">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <BaseList url="/v1/client/EProsClient" class="goods_list" :params="{ mallstate: 2, pid: active }">
|
|
||||||
<template #default="{ item }">
|
|
||||||
<div class="goods_item" :key="item.id" @click="toDetail(item.id)">
|
|
||||||
<img :src="$file(item.img)" alt="">
|
|
||||||
<div>
|
|
||||||
<span class="title">{{ item.name }}</span>
|
|
||||||
<p>¥{{ item.originalprice }}</p>
|
|
||||||
<div class="money">
|
|
||||||
<div>
|
|
||||||
<span>¥
|
|
||||||
<b>{{ item.saleprice }}</b>.00
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<img class="r" style="width: 5.6vw;" src="/img/cart.png" alt="">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</BaseList> -->
|
|
||||||
|
|
||||||
|
|
||||||
<div class="goods_list">
|
|
||||||
<div class="goods_item" v-for="item in goods" :key="item.id" @click="toDetail(item.id)">
|
|
||||||
<img :src="item.Icon" alt="">
|
|
||||||
<div>
|
|
||||||
<span class="title">{{ item.SubTitle }}</span>
|
|
||||||
<div class="point_box">
|
|
||||||
<img style="width: 3.33vw;height: 3.2vw;" src="/img/point.png" alt="">
|
|
||||||
<span style="font-size: 3.2vw; color: #d9a452;">积分可抵¥500.00</span>
|
|
||||||
</div>
|
|
||||||
<!-- <p>¥{{ item.OPrice }}</p> -->
|
|
||||||
<div class="money">
|
|
||||||
<div>
|
|
||||||
<span>¥</span>
|
|
||||||
<b>{{ item.Price }}</b>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span class="oprice">
|
|
||||||
¥{{ item.OPrice }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<van-popup v-model:show="showLeft" position="left" :style="{ width: '30%', height: '100%' }">
|
|
||||||
<div v-for="i in tabs">
|
|
||||||
<div @click="changeTab(i.id)" style="height: 10vw;width: 100%;border-bottom: solid 1px #f5f5f5;"
|
|
||||||
class="box box-center-center">
|
|
||||||
{{ i.name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</van-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'PointMall',
|
|
||||||
activated() {
|
|
||||||
this.getTab()
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
active: '',
|
|
||||||
showLeft: false,
|
|
||||||
tabs: [],
|
|
||||||
goods: [
|
|
||||||
{
|
|
||||||
id: 1, Icon:
|
|
||||||
'/img/avatar.png', SubTitle:
|
|
||||||
'积分礼品测试商品1', OPrice: '99.00',
|
|
||||||
Price: '9.90'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2, Icon:
|
|
||||||
'/img/avatar.png', SubTitle:
|
|
||||||
'积分礼品测试商品2', OPrice:
|
|
||||||
'199.00', Price: '19.90'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3, Icon:
|
|
||||||
'/img/avatar.png', SubTitle:
|
|
||||||
'积分礼品测试商品3', OPrice:
|
|
||||||
'299.00', Price: '29.90'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.getTab()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getTab() {
|
|
||||||
this.$get('/v1/client/EProcatesClient/2').then(res => {
|
|
||||||
this.tabs = res.data
|
|
||||||
})
|
|
||||||
},
|
|
||||||
changeTab(id) {
|
|
||||||
this.active = id;
|
|
||||||
this.showLeft = false;
|
|
||||||
},
|
|
||||||
toDetail(e) {
|
|
||||||
this.$navigate(`/GoodsDetail?id=${e}`)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
filteredGoods() {
|
|
||||||
// if (this.active === 0) {
|
|
||||||
// return this.goods
|
|
||||||
// }
|
|
||||||
// const categoryId = this.active
|
|
||||||
// return this.goods.filter(item => item.CategoryId === categoryId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.pointmall {
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
background: #f5f5f5;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.finished-text {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top {
|
|
||||||
position: relative;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contaiar {
|
|
||||||
position: relative;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-radius: 8vw 8vw 0vw 0vw;
|
|
||||||
margin-top: -12vw;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
.tabs {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0 5vw;
|
|
||||||
margin-top: 4vw;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.filter_img {
|
|
||||||
width: 5.4vw;
|
|
||||||
height: 5.4vw;
|
|
||||||
position: absolute;
|
|
||||||
right: 5vw;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.goods_list {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 0 4vw;
|
|
||||||
margin-top: 4vw;
|
|
||||||
|
|
||||||
.goods_item {
|
|
||||||
background-color: #fefefe;
|
|
||||||
border-radius: 2vw;
|
|
||||||
margin-bottom: 4vw;
|
|
||||||
width: 44.8vw;
|
|
||||||
max-width: 44.8vw;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 44.8vw;
|
|
||||||
height: 44.8vw;
|
|
||||||
background-color: #fefefe;
|
|
||||||
border-radius: 2vw 2vw 0vw 0vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
>div {
|
|
||||||
padding: 3.2vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
width: 38.4vw;
|
|
||||||
max-width: 38.4vw;
|
|
||||||
font-size: 3.47vw;
|
|
||||||
overflow: hidden !important;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: -webkit-box !important;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
line-clamp: 2;
|
|
||||||
line-height: 4vw;
|
|
||||||
height: 8vw;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 3.2vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.point_box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 3.2vw;
|
|
||||||
height: 5.33vw;
|
|
||||||
background-color: #fff6dd;
|
|
||||||
border-radius: 0.8vw;
|
|
||||||
border: solid 0.27vw #f1c98c;
|
|
||||||
padding: 0 2vw;
|
|
||||||
width: fit-content;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 3.33vw;
|
|
||||||
height: 3.2vw;
|
|
||||||
margin-right: 1.6vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size: 3.2vw;
|
|
||||||
color: #d9a452;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.money {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
color: #ea3e23;
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: #ca2904;
|
|
||||||
text-decoration: line-through;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
b {
|
|
||||||
font-size: 4vw;
|
|
||||||
color: #ea3e23;
|
|
||||||
text-decoration: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.oprice {
|
|
||||||
font-size: 3.2vw;
|
|
||||||
color: #b1b1b1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -106,7 +106,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
back() {
|
back() {
|
||||||
this.$router.push('/TradeList');
|
this.$router.push('/Tradelist');
|
||||||
},
|
},
|
||||||
async loadData() {
|
async loadData() {
|
||||||
try {
|
try {
|
||||||
@ -135,67 +135,27 @@ export default {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await this.$post(`/v1/client/FOrdersClient/${this.ordernum}/pay`, {
|
const res = await this.$post(`/v1/client/FOrdersClient/${this.ordernum}/pay`, {
|
||||||
paychannel: paychannel,
|
Paychannel: paychannel,
|
||||||
openid: method === 'wechat' ? openid : ''
|
Openid: method === 'wechat' ? openid : ''
|
||||||
});
|
});
|
||||||
|
if (res.data && res.data.startsWith('http')) {
|
||||||
if (method === 'wechat') {
|
// 返回链接则跳转
|
||||||
// 微信支付使用 WeixinJSBridge 调起
|
location.href = res.data;
|
||||||
this.callWechatPay(res.data);
|
} else if (res.status === 200) {
|
||||||
} else if (method === 'balance') {
|
// 余额支付成功
|
||||||
// 余额支付成功,不显示弹窗
|
|
||||||
this.$showSuccessToast(res.message || '支付成功');
|
this.$showSuccessToast(res.message || '支付成功');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.onPayCompleted();
|
this.onPayCompleted();
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} else if (res.data && res.data.startsWith('http')) {
|
|
||||||
// 其他支付方式跳转链接
|
|
||||||
location.href = res.data;
|
|
||||||
this.showPayResult = true;
|
|
||||||
}
|
}
|
||||||
|
this.showPayResult = true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (method !== 'balance' && method !== 'wechat') {
|
this.showPayResult = false;
|
||||||
this.showPayResult = false;
|
|
||||||
}
|
|
||||||
this.$showFailToast(err.message || '支付失败');
|
this.$showFailToast(err.message || '支付失败');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
callWechatPay(payData) {
|
|
||||||
// 微信支付调起方法
|
|
||||||
const onBridgeReady = () => {
|
|
||||||
WeixinJSBridge.invoke(
|
|
||||||
'getBrandWCPayRequest', {
|
|
||||||
appId: payData.appId,
|
|
||||||
timeStamp: payData.timeStamp,
|
|
||||||
nonceStr: payData.nonceStr,
|
|
||||||
package: payData.package,
|
|
||||||
signType: payData.signType,
|
|
||||||
paySign: payData.paySign
|
|
||||||
},
|
|
||||||
(res) => {
|
|
||||||
if (res.err_msg === 'get_brand_wcpay_request:ok') {
|
|
||||||
this.$showSuccessToast('支付成功');
|
|
||||||
this.onPayCompleted();
|
|
||||||
} else {
|
|
||||||
// this.showPayResult = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof WeixinJSBridge === 'undefined') {
|
|
||||||
if (document.addEventListener) {
|
|
||||||
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
|
|
||||||
} else if (document.attachEvent) {
|
|
||||||
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
|
|
||||||
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onBridgeReady();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onPayCompleted() {
|
onPayCompleted() {
|
||||||
this.$router.replace('/TradeList');
|
this.$router.replace('/Tradelist');
|
||||||
},
|
},
|
||||||
onRePay() {
|
onRePay() {
|
||||||
this.showPayResult = false;
|
this.showPayResult = false;
|
||||||
|
|||||||
@ -7,21 +7,6 @@
|
|||||||
<b style="#d2220d">{{ data.statename }}</b>
|
<b style="#d2220d">{{ data.statename }}</b>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="_address">
|
|
||||||
<div class="icon">
|
|
||||||
<img src="/img/address.png">
|
|
||||||
</div>
|
|
||||||
<div class="c">
|
|
||||||
<div class="name">
|
|
||||||
{{ data.receiptrealname }} {{ data.receiptcellphone }}
|
|
||||||
</div>
|
|
||||||
<div class="s">
|
|
||||||
<p>{{ data.receiptprovince }}{{ data.receiptcity }}{{ data.receiptcounty }}{{
|
|
||||||
data.receiptaddress }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="_goods">
|
<div class="_goods">
|
||||||
<img :src="$file(data.proimg)">
|
<img :src="$file(data.proimg)">
|
||||||
<div class="c">
|
<div class="c">
|
||||||
@ -40,12 +25,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="_remark" v-if="data.remark">
|
|
||||||
<p>买家留言: </p>
|
|
||||||
<span class="r">
|
|
||||||
{{ data.remark || '无' }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="_detail">
|
<div class="_detail">
|
||||||
<div class="p">
|
<div class="p">
|
||||||
<p>
|
<p>
|
||||||
@ -64,13 +43,9 @@
|
|||||||
实付金额
|
实付金额
|
||||||
<b style="color: #f00;">¥{{ data.realmoney?.toFixed(2) }}</b>
|
<b style="color: #f00;">¥{{ data.realmoney?.toFixed(2) }}</b>
|
||||||
</p>
|
</p>
|
||||||
<p v-if="data.paychannelname">
|
|
||||||
支付方式
|
|
||||||
<span>{{ data.paychannelname }}</span>
|
|
||||||
</p>
|
|
||||||
<p v-if="data.zongsongjifen">
|
<p v-if="data.zongsongjifen">
|
||||||
赠送积分
|
赠送积分
|
||||||
<span>{{ data.zongsongjifen?.toFixed(2) }}</span>
|
<span>{{ data.zongsongjifen }}</span>
|
||||||
</p>
|
</p>
|
||||||
<hr style="margin:1.67vw 0;height: 1px;border: none;background: #f5f5f580;">
|
<hr style="margin:1.67vw 0;height: 1px;border: none;background: #f5f5f580;">
|
||||||
<p>
|
<p>
|
||||||
@ -132,7 +107,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
back() {
|
back() {
|
||||||
this.$navigate('/TradeList');
|
this.$router.back();
|
||||||
},
|
},
|
||||||
async loadData() {
|
async loadData() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasePage :back="back">
|
<BasePage>
|
||||||
<div class="tradelist">
|
<div class="tradelist">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<van-tabs class="area" v-model:active="TradeArea" color="#f00" title-active-color="#222"
|
<van-tabs class="area" v-model:active="TradeArea" color="#f00" title-active-color="#222"
|
||||||
@ -13,27 +13,30 @@
|
|||||||
<van-tab v-for="i in tradeStates" :title="i.label" :name="String(i.value)"></van-tab>
|
<van-tab v-for="i in tradeStates" :title="i.label" :name="String(i.value)"></van-tab>
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
</div>
|
</div>
|
||||||
<van-search v-model="_searchParams.ordernum" left-icon=" " shape="round" placeholder="输入订单号搜索" @search="onSearch"
|
<van-search v-model="searchParams.ordernum" left-icon=" " shape="round" placeholder="输入订单号搜索" @search="onSearch"
|
||||||
@clear="onClear">
|
@clear="onClear">
|
||||||
<template #right-icon>
|
<template #right-icon>
|
||||||
<van-icon name="/img/sort-search.png" @click="onSearch"></van-icon>
|
<van-icon name="/img/sort-search.png" @click="onSearch"></van-icon>
|
||||||
</template>
|
</template>
|
||||||
</van-search>
|
</van-search>
|
||||||
|
|
||||||
<BaseList ref="baseList" url="/v1/client/FOrdersClient" :params="searchParams" :parseData="parseData"
|
<BaseList v-if="TradeArea !== 2" ref="baseList" url="/v1/client/FOrdersClient" :params="searchParams"
|
||||||
style="padding: 3.33vw;" @refresh="onRefresh">
|
:parseData="res => res.data.items" style="padding: 3.33vw;" @refresh="onRefresh">
|
||||||
<template #default="{ item }">
|
<template #default="{ item }">
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<div class="order_box">
|
<div class="order_box">
|
||||||
<span :class="'state' + item.mallstate" class="state">{{ item.mallstatename.slice(0, 2) }}</span>
|
<span>
|
||||||
<span>订单编号:{{ item.ordernum }}</span>
|
订单编号:{{ item.ordernum }}
|
||||||
|
</span>
|
||||||
<img src="/img/copy_b.png" @click="$copyText(item.ordernum); $showSuccessToast('复制成功')" alt="">
|
<img src="/img/copy_b.png" @click="$copyText(item.ordernum); $showSuccessToast('复制成功')" alt="">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="goods_box">
|
<div class="goods_box">
|
||||||
<img :src="$file(item.shopimg || item.proimg)" alt="">
|
<img :src="$file(item.proimg)" alt="">
|
||||||
|
|
||||||
<div class="goods_info">
|
<div class="goods_info">
|
||||||
<div class="tit">{{ item.shopname || item.proname }}</div>
|
<div class="tit">{{ item.proname }}</div>
|
||||||
<div class="spec" v-if="!item.shopname">
|
<div class="spec">
|
||||||
<span>{{ item.proskuname }}</span>
|
<span>{{ item.proskuname }}</span>
|
||||||
<p>x{{ item.buynums }}</p>
|
<p>x{{ item.buynums }}</p>
|
||||||
</div>
|
</div>
|
||||||
@ -43,17 +46,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="price">
|
<div class="price">
|
||||||
实付:<span>¥<b>{{ item.realmoney?.toFixed(2) }}</b></span>
|
实付:<span>¥<b>{{ item.realmoney?.toFixed(2) }}</b></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="state_box">
|
<div class="state_box">
|
||||||
<b :class="'b' + item.state">{{ item.statename }}</b>
|
<b :class="'b' + item.state">
|
||||||
|
{{ item.statename }}
|
||||||
|
</b>
|
||||||
|
|
||||||
<div class="btn_box">
|
<div class="btn_box">
|
||||||
<button v-if="item.state === 0" @click="cancelTrade(item)">取消订单</button>
|
<button v-if="item.state === 0" @click="cancelTrade(item)">取消订单</button>
|
||||||
<button v-if="!item.shopname" @click="$navigate(`TradeDetail?ordernum=${item.ordernum}`)">查看详情</button>
|
<!-- <button v-if="item.state === 3">查看物流</button> -->
|
||||||
<button v-else @click="$navigate(`MerchantTradeDetail?id=${item.ordernum}`)">查看详情</button>
|
<button @click="$navigate(`TradeDetail?ordernum=${item.ordernum}`)">查看详情</button>
|
||||||
<button v-if="item.state === 3 || item.state === 4" @click="showLogistics(item)">物流信息</button>
|
|
||||||
|
|
||||||
<button v-if="item.state === 3" @click="confirmReceipt(item)">确认收货</button>
|
<button v-if="item.state === 3" @click="confirmReceipt(item)">确认收货</button>
|
||||||
<button v-if="item.state === 0" @click="$navigate(`Pay?ordernum=${item.ordernum}`)">立即支付</button>
|
<button v-if="item.state === 0" @click="$navigate(`Pay?ordernum=${item.ordernum}`)">立即支付</button>
|
||||||
</div>
|
</div>
|
||||||
@ -62,26 +68,58 @@
|
|||||||
</template>
|
</template>
|
||||||
</BaseList>
|
</BaseList>
|
||||||
|
|
||||||
|
<BaseList v-else ref="baseList" url="/v1/client/FOrdersshopClient" :params="searchParams"
|
||||||
|
:parseData="res => res.data.items" style="padding: 3.33vw;" @refresh="onRefresh">
|
||||||
|
<template #default="{ item }">
|
||||||
|
<div class="list">
|
||||||
|
<div class="merchant_info">
|
||||||
|
<img class="icon" :src="$file(item.shopimg)" alt="">
|
||||||
|
<div class="inf">
|
||||||
|
<span>{{ item.shopname }}</span>
|
||||||
|
<div>
|
||||||
|
<p>¥{{ item.ordermoney?.toFixed(2) }}</p>
|
||||||
|
<span class="dr" v-if="item.discountratio">
|
||||||
|
{{ item.discountratio }}%让利
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<van-popup v-model:show="logisticsVisible" round position="bottom" teleport="body">
|
<div class="price">
|
||||||
<div class="logistics-popup">
|
实付:<span>¥<b>{{ item.realmoney?.toFixed(2) }}</b></span>
|
||||||
<div class="logistics-tit">物流信息</div>
|
|
||||||
<div class="logistics-content">
|
|
||||||
<div class="logistics-item">
|
|
||||||
<span class="label">物流公司</span>
|
|
||||||
<span class="value">{{ currentLogistics?.exportname }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="logistics-item">
|
|
||||||
<span class="label">物流单号</span>
|
<div class="detail_box">
|
||||||
<span class="value">{{ currentLogistics?.exportnum }}</span>
|
<div>
|
||||||
<img src="/img/copy_b.png" @click="$copyText(currentLogistics?.exportnum); $showSuccessToast('复制成功')" alt="">
|
<span>订单编号:</span>
|
||||||
|
<span class="r">
|
||||||
|
{{ item.ordernum }}
|
||||||
|
<img src="/img/copy_b.png" @click="$copyText(item.ordernum); $showSuccessToast('复制成功')" alt="">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<span>下单时间:</span>
|
||||||
|
<span class="r">
|
||||||
|
{{ $formatGMT(item.addtime, 'yyyy-MM-dd HH:mm:ss') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="state_box">
|
||||||
|
<b :class="'b' + item.state">
|
||||||
|
{{ item.statename }}
|
||||||
|
</b>
|
||||||
|
|
||||||
|
<div class="btn_box">
|
||||||
|
<button @click="$navigate(`MerchantTradeDetail?id=${item.ordernum}&type=user`)">查看详情</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="logistics-close">
|
</template>
|
||||||
<van-button type="primary" block round color="#ca2904" @click="logisticsVisible = false">关闭</van-button>
|
</BaseList>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</van-popup>
|
|
||||||
</div>
|
</div>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
</template>
|
</template>
|
||||||
@ -89,213 +127,102 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'TradeList',
|
name: 'TradeList',
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
TradeArea: this.$route.query.TradeArea || 0,
|
activeTab: '',
|
||||||
activeTab: this.$route.query.state || '',
|
TradeArea: Number(this.$route.query.TradeArea) || 3,
|
||||||
_searchParams: {
|
searchParams: {
|
||||||
ordernum: '',
|
ordernum: '',
|
||||||
state: '',
|
state: '',
|
||||||
|
mallstate: Number(this.$route.query.TradeArea) || 3,
|
||||||
},
|
},
|
||||||
tradeStates: [
|
tradeStates: [
|
||||||
{
|
|
||||||
"value": 0,
|
|
||||||
"label": "待付款"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 1,
|
|
||||||
"label": "待发货"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 3,
|
|
||||||
"label": "待收货"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 4,
|
|
||||||
"label": "已完成"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
mallList: [
|
mallList: [
|
||||||
{ value: 0, label: '全部订单' },
|
{ value: 3, label: '商城订单' },
|
||||||
{
|
{ value: 1, label: '礼包订单' },
|
||||||
"value": 1,
|
{ value: 2, label: '买单订单' },
|
||||||
"label": "礼包订单"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 3,
|
|
||||||
"label": "商城订单"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": 4,
|
|
||||||
"label": "买单订单"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
_initializing: true,
|
|
||||||
logisticsVisible: false,
|
|
||||||
currentLogistics: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
computed: {
|
this.getTradeStates();
|
||||||
parseData() {
|
|
||||||
return res => res.data.items
|
|
||||||
},
|
|
||||||
searchParams() {
|
|
||||||
const params = {
|
|
||||||
ordernum: this._searchParams.ordernum,
|
|
||||||
state: this._searchParams.state === '' ? '' : Number(this._searchParams.state),
|
|
||||||
}
|
|
||||||
if (this.TradeArea !== 0) {
|
|
||||||
params.mallstate = this.TradeArea
|
|
||||||
}
|
|
||||||
return params
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
'$route.query.TradeArea': {
|
TradeArea(val) {
|
||||||
handler(val) {
|
this.searchParams.mallstate = val;
|
||||||
this.TradeArea = val !== undefined ? Number(val) : 0
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
},
|
},
|
||||||
'$route.query.state': {
|
'$route.query.state': {
|
||||||
handler(val) {
|
handler(newVal) {
|
||||||
this.activeTab = val || ''
|
if (newVal !== undefined && newVal !== '') {
|
||||||
this._searchParams.state = val || ''
|
this.activeTab = String(newVal);
|
||||||
},
|
// this.getTradeStates();
|
||||||
immediate: true
|
} else {
|
||||||
|
this.activeTab = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
// 加载订单状态和类型列表
|
back() {
|
||||||
// async loadFilterOptions() {
|
this.$router.push('/My')
|
||||||
// try {
|
},
|
||||||
// const [stateRes, areaRes] = await Promise.all([
|
|
||||||
// this.$get('/v1/client/FOrdersClient/orderstate'),
|
|
||||||
// this.$get('/v1/client/EProsClient/mallstate'),
|
|
||||||
// ])
|
|
||||||
// this.tradeStates = stateRes.data || []
|
|
||||||
// this.mallList = [{ value: 0, label: '全部订单' }, ...(areaRes.data || [])]
|
|
||||||
// this._initializing = false
|
|
||||||
// } catch (err) {
|
|
||||||
// this.$showFailToast(err.message || '加载失败')
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
|
|
||||||
// Tab 切换 - 订单状态
|
|
||||||
onTabChange(name) {
|
onTabChange(name) {
|
||||||
this._searchParams.state = name
|
this.searchParams.state = name;
|
||||||
// this.$refs.baseList?.refresh()
|
this.$refs.baseList?.refresh();
|
||||||
},
|
},
|
||||||
|
changeMall(name) {
|
||||||
// Tab 切换 - 订单类型
|
this.searchParams.mallstate = Number(name) || 3;
|
||||||
changeMall(val) {
|
this.searchParams.state = '';
|
||||||
this.TradeArea = val
|
this.$refs.baseList?.refresh();
|
||||||
this._searchParams.state = ''
|
|
||||||
this.activeTab = ''
|
|
||||||
// 不需要手动 refresh,BaseList 的 watch params 会自动触发
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 搜索 & 清除
|
|
||||||
onSearch() {
|
onSearch() {
|
||||||
this.$refs.baseList?.refresh()
|
this.$refs.baseList?.refresh();
|
||||||
},
|
},
|
||||||
onClear() {
|
onClear() {
|
||||||
this._searchParams.ordernum = ''
|
this.searchParams.ordernum = '';
|
||||||
this.$refs.baseList?.refresh()
|
this.$refs.baseList?.refresh();
|
||||||
|
},
|
||||||
|
getTradeStates() {
|
||||||
|
this.$get('/v1/client/FOrdersClient/orderstate').then(res => {
|
||||||
|
this.tradeStates = res.data;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const stateFromRoute = this.$route.query.state;
|
||||||
|
if (stateFromRoute !== undefined && stateFromRoute !== '') {
|
||||||
|
this.activeTab = String(stateFromRoute);
|
||||||
|
this.searchParams.state = stateFromRoute;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).catch((err) => {
|
||||||
|
this.$showFailToast(err.message || '获取订单状态失败');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onRefresh() {
|
||||||
},
|
},
|
||||||
|
|
||||||
// 确认收货
|
|
||||||
confirmReceipt(item) {
|
confirmReceipt(item) {
|
||||||
this.$showConfirmDialog({ title: '是否确认收货' })
|
this.$showConfirmDialog({
|
||||||
.then(() => this.$put(`/v1/client/FOrdersClient/${item.ordernum}/receipt`))
|
title: "是否确认收货",
|
||||||
.then(() => {
|
}).then(() => {
|
||||||
this.$showSuccessToast('确认收货成功')
|
this.$put(`/v1/client/FOrdersClient/${item.ordernum}/receipt`).then(() => {
|
||||||
this.$refs.baseList?.refresh()
|
this.$showSuccessToast('确认收货成功');
|
||||||
})
|
this.$refs.baseList?.refresh();
|
||||||
.catch(err => this.$showFailToast(err.message || '操作失败'))
|
}).catch(err => {
|
||||||
|
this.$showFailToast(err.message || '操作失败');
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
},
|
},
|
||||||
|
|
||||||
// 取消订单
|
|
||||||
cancelTrade(item) {
|
cancelTrade(item) {
|
||||||
this.$showConfirmDialog({ title: '是否确认取消订单' })
|
this.$showConfirmDialog({
|
||||||
.then(() => this.$put(`/v1/client/FOrdersClient/${item.ordernum}/cancel`))
|
title: "是否确认取消订单",
|
||||||
.then(() => {
|
}).then(() => {
|
||||||
this.$showSuccessToast('取消订单成功')
|
this.$put(`/v1/client/FOrdersClient/${item.ordernum}/cancel`).then(() => {
|
||||||
this.$refs.baseList?.refresh()
|
this.$showSuccessToast('取消订单成功');
|
||||||
})
|
this.$refs.baseList?.refresh();
|
||||||
.catch(err => this.$showFailToast(err.message || '取消失败'))
|
}).catch(err => {
|
||||||
|
this.$showFailToast(err.message || '取消失败');
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
},
|
},
|
||||||
|
}
|
||||||
// 显示物流信息
|
|
||||||
showLogistics(item) {
|
|
||||||
this.currentLogistics = item
|
|
||||||
this.logisticsVisible = true
|
|
||||||
},
|
|
||||||
|
|
||||||
back() {
|
|
||||||
this.$navigate('/My');
|
|
||||||
},
|
|
||||||
|
|
||||||
onRefresh() { },
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.logistics-popup {
|
|
||||||
padding: 20px;
|
|
||||||
|
|
||||||
.logistics-tit {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logistics-content {
|
|
||||||
background: #f5f5f5;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 15px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logistics-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
width: 70px;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
flex: 1;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.logistics-close {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@ -1,27 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasePage>
|
<BasePage>
|
||||||
|
<!-- v-if="data.Icon" -->
|
||||||
<div class="ewm_bg" style="font-family: 'PingFang SC'">
|
<div class="ewm_bg" style="font-family: 'PingFang SC'">
|
||||||
<div class="d1">
|
<div class="d1">
|
||||||
<div class="w100">
|
<div class="w100">
|
||||||
<img id="invite_bg" src="/img/invite_bg.jpg" crossorigin="anonymous">
|
<img id="invite_bg" :src="$file($datadic.getContent('code_yqmbj'))" crossorigin="anonymous" />
|
||||||
|
<!-- <img id="invite_bg" src="/img/invite_bg.jpg" crossorigin="anonymous"> -->
|
||||||
</div>
|
</div>
|
||||||
<img class="icon" :src="$file(data.Avatar)" crossorigin="anonymous">
|
<img class="icon" :src="$file(data.Avatar) + '?t=1'" crossorigin="anonymous">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<b>{{ $substring(data.NickName, 0, 8) }}</b>
|
<b>{{ $substring(data.NickName, 0, 8) }}</b>
|
||||||
|
<p>邀请你使用泰古润平台<br>
|
||||||
|
共赴葡园品鉴醇香</p>
|
||||||
</div>
|
</div>
|
||||||
<p class="tips">邀请你使用泰古润平台<br>积分带卡消费,享受更多实惠</p>
|
|
||||||
<div class="ewm_test box box-tb box-align-center">
|
<div class="ewm_test box box-tb box-align-center">
|
||||||
<vue-qr v-if="!loading" :text="link" backgroundColor="rgb(255,255,255)"
|
<vue-qr v-if="!loading" :text="link" backgroundColor="rgb(255,255,255)"
|
||||||
colorLight="rgb(255,255,255)"></vue-qr>
|
colorLight="rgb(255,255,255)"></vue-qr>
|
||||||
|
<!-- <span>扫码立即注册</span> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="sc_ewm" class="b_l_w bx" style="font-family: 'PingFang SC'"></div>
|
<div id="sc_ewm" class="b_l_w bx" style="font-family: 'PingFang SC'"></div>
|
||||||
|
|
||||||
</BasePage>
|
</BasePage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import html2canvas from 'html2canvas'
|
import { html2canvas, canvasToDataURL } from '@/utils/html2image';
|
||||||
|
import { useUserStore } from '@/stores/user';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Invite',
|
name: 'Invite',
|
||||||
@ -29,96 +36,80 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loading: true,
|
loading: true,
|
||||||
data: {
|
data: {
|
||||||
|
Icon: '',
|
||||||
Avatar: '',
|
Avatar: '',
|
||||||
NickName: '',
|
NickName: '',
|
||||||
},
|
},
|
||||||
link: '',
|
link: '',
|
||||||
}
|
userStore: useUserStore(),
|
||||||
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init()
|
this.loading = false;
|
||||||
|
this.init().then(() => {
|
||||||
|
// 等数据和二维码都准备好后再生成海报
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const img = document.getElementById("invite_bg");
|
||||||
|
if (img.complete) {
|
||||||
|
this.CreatePoster(".ewm_bg > div", "#sc_ewm");
|
||||||
|
} else {
|
||||||
|
img.onload = () => this.CreatePoster(".ewm_bg > div", "#sc_ewm");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async init() {
|
async init() {
|
||||||
try {
|
try {
|
||||||
const userInfo = await this.$get('/v1/client/DUsersClient')
|
// 获取用户信息
|
||||||
|
const userInfo = await this.$get('/v1/client/DUsersClient');
|
||||||
if (userInfo?.data) {
|
if (userInfo?.data) {
|
||||||
this.data.Avatar = userInfo.data.userimg || ''
|
this.data.Avatar = userInfo.data.userimg || '';
|
||||||
this.data.NickName = userInfo.data.nickname || ''
|
this.data.NickName = userInfo.data.nickname || '';
|
||||||
|
this.data.Icon = userInfo.data.Icon || '';
|
||||||
}
|
}
|
||||||
const inviteCode = userInfo?.data?.cellphone || ''
|
// 生成包含邀请码的链接
|
||||||
this.link = `${location.origin}${location.pathname}#/Login?invite=${inviteCode}`
|
const inviteCode = userInfo?.data?.cellphone || '';
|
||||||
|
this.link = `${location.origin}${location.pathname}#/Login?invite=${inviteCode}`;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('获取用户信息失败:', err)
|
console.error('获取用户信息失败:', err);
|
||||||
} finally {
|
|
||||||
this.loading = false
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.generatePoster()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async CreatePoster(divID, targetID) {
|
||||||
async generatePoster() {
|
var shareContent = document.querySelector(divID);
|
||||||
const el = document.querySelector('.ewm_bg > .d1')
|
var width = shareContent.offsetWidth;
|
||||||
const bgImg = document.querySelector('#invite_bg')
|
var height = shareContent.offsetHeight;
|
||||||
if (!el || !bgImg) return
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Convert local image to base64 for Safari compatibility
|
// 等待头像图片加载完成
|
||||||
if (bgImg.src.startsWith('/')) {
|
const avatarImg = shareContent.querySelector('.icon');
|
||||||
await this.loadImageToBase64(bgImg)
|
if (avatarImg && !avatarImg.complete) {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
avatarImg.onload = resolve;
|
||||||
|
avatarImg.onerror = resolve; // 加载失败也继续
|
||||||
|
setTimeout(resolve, 5000); // 超时也继续
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.fonts?.ready) {
|
var canvas = await html2canvas(shareContent, {
|
||||||
await document.fonts.ready
|
|
||||||
}
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 500))
|
|
||||||
|
|
||||||
const canvas = await html2canvas(el, {
|
|
||||||
scale: 2,
|
scale: 2,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
useCORS: true,
|
useCORS: true,
|
||||||
backgroundColor: '#ffffff',
|
allowTaint: false,
|
||||||
logging: false
|
});
|
||||||
})
|
var dataUrl = canvasToDataURL(canvas, "image/png", 1.0);
|
||||||
const dataUrl = canvas.toDataURL('image/png')
|
var newImg = document.createElement("img");
|
||||||
|
newImg.src = dataUrl;
|
||||||
const target = document.querySelector('#sc_ewm')
|
newImg.width = width;
|
||||||
if (target) {
|
newImg.height = height;
|
||||||
target.innerHTML = ''
|
document.querySelector(targetID).appendChild(newImg);
|
||||||
const img = document.createElement('img')
|
|
||||||
img.src = dataUrl
|
|
||||||
img.style.width = '100%'
|
|
||||||
img.style.display = 'block'
|
|
||||||
target.appendChild(img)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('生成海报失败', err)
|
console.error('生成海报失败', err);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
loadImageToBase64(imgEl) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const img = new Image()
|
|
||||||
img.crossOrigin = 'anonymous'
|
|
||||||
img.onload = () => {
|
|
||||||
try {
|
|
||||||
const canvas = document.createElement('canvas')
|
|
||||||
canvas.width = img.width
|
|
||||||
canvas.height = img.height
|
|
||||||
const ctx = canvas.getContext('2d')
|
|
||||||
ctx.drawImage(img, 0, 0)
|
|
||||||
imgEl.src = canvas.toDataURL('image/png')
|
|
||||||
resolve()
|
|
||||||
} catch (e) {
|
|
||||||
reject(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
img.onerror = reject
|
|
||||||
img.src = imgEl.src
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@ -136,22 +127,19 @@ export default {
|
|||||||
|
|
||||||
.name {
|
.name {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 34vw;
|
left: 20.27vw;
|
||||||
bottom: 46vw;
|
bottom: 25.6vw;
|
||||||
|
line-height: 6vw;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
b {
|
b {
|
||||||
font-size: 3.47vw;
|
font-size: 3.47vw;
|
||||||
|
color: #3a0a05;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
p {
|
||||||
|
font-size: 3.2vw;
|
||||||
.tips {
|
}
|
||||||
font-size: 3.2vw;
|
|
||||||
color: #3a0a05;
|
|
||||||
position: absolute;
|
|
||||||
left: 20.27vw;
|
|
||||||
bottom: 32.4vw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
@ -159,7 +147,7 @@ export default {
|
|||||||
width: 10.67vw;
|
width: 10.67vw;
|
||||||
height: 10.67vw;
|
height: 10.67vw;
|
||||||
left: 20.27vw;
|
left: 20.27vw;
|
||||||
bottom: 43vw;
|
bottom: 42vw;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@
|
|||||||
<div @click="$navigate('CV')">
|
<div @click="$navigate('CV')">
|
||||||
<div class="t">
|
<div class="t">
|
||||||
<img src="/img/my_w2.png" alt="">
|
<img src="/img/my_w2.png" alt="">
|
||||||
<span>会员卡</span>
|
<span>会员卡额度</span>
|
||||||
</div>
|
</div>
|
||||||
<b>{{ data.xiaofeiquan?.toFixed(2) }}</b>
|
<b>{{ data.xiaofeiquan?.toFixed(2) }}</b>
|
||||||
</div>
|
</div>
|
||||||
@ -68,24 +68,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="c">
|
<div class="c">
|
||||||
<van-badge :dot="data.ordercountdaifukuan > 0" :offset="[3, -3]">
|
<van-badge :dot="data.ordercountdaifukuan > 0" :offset="[3, -3]">
|
||||||
<div class="st_box" @click="$navigate(`/TradeList?state=0`)">
|
<div class="st_box" @click="$navigate(`TradeList?TradeArea=3&state=0`)">
|
||||||
<img src="/img/my_o1.png">
|
<img src="/img/my_o1.png">
|
||||||
<p>待付款</p>
|
<p>待付款</p>
|
||||||
</div>
|
</div>
|
||||||
</van-badge>
|
</van-badge>
|
||||||
<van-badge :dot="data.ordercountdaifahuo > 0" :offset="[3, -3]">
|
<van-badge :dot="data.ordercountdaifahuo > 0" :offset="[3, -3]">
|
||||||
<div class="st_box" @click="$navigate(`/TradeList?state=1`)">
|
<div class="st_box" @click="$navigate(`TradeList?TradeArea=3&state=1`)">
|
||||||
<img src="/img/my_o2.png">
|
<img src="/img/my_o2.png">
|
||||||
<p>待发货</p>
|
<p>待发货</p>
|
||||||
</div>
|
</div>
|
||||||
</van-badge>
|
</van-badge>
|
||||||
<van-badge :dot="data.ordercountdaishouhuo > 0" :offset="[3, -3]">
|
<van-badge :dot="data.ordercountdaishouhuo > 0" :offset="[3, -3]">
|
||||||
<div class="st_box" @click="$navigate(`/TradeList?state=3`)">
|
<div class="st_box" @click="$navigate(`TradeList?TradeArea=3&state=3`)">
|
||||||
<img src="/img/my_o3.png">
|
<img src="/img/my_o3.png">
|
||||||
<p>待收货</p>
|
<p>待收货</p>
|
||||||
</div>
|
</div>
|
||||||
</van-badge>
|
</van-badge>
|
||||||
<div class="st_box" @click="$navigate(`/TradeList?state=4`)">
|
<div class="st_box" @click="$navigate(`TradeList?TradeArea=3&state=4`)">
|
||||||
<img src="/img/my_o4.png">
|
<img src="/img/my_o4.png">
|
||||||
<p>已完成</p>
|
<p>已完成</p>
|
||||||
</div>
|
</div>
|
||||||
@ -93,14 +93,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fast_to">
|
<div class="fast_to">
|
||||||
<div>
|
<img src="/img/my_f1.jpg" @click="toInvite()" alt="">
|
||||||
<img src="/img/my_f1.jpg" @click="toInvite()" alt="">
|
<img src="/img/my_f2.jpg" @click="$navigate('Team')" alt="">
|
||||||
<img src="/img/my_f2.jpg" @click="$navigate('Team')" alt="">
|
<img src="/img/my_f3.jpg" @click="$navigate('Allow')" alt="">
|
||||||
</div>
|
<img src="/img/my_f4.jpg" @click="$navigate('Certificate')" alt="">
|
||||||
<div>
|
|
||||||
<img src="/img/my_f3.jpg" @click="$navigate('Allow')" alt="">
|
|
||||||
<img src="/img/my_f4.jpg" @click="$navigate('Certificate')" alt="">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="service_center">
|
<div class="service_center">
|
||||||
@ -203,7 +199,7 @@
|
|||||||
|
|
||||||
<van-dialog v-model:show="showFollow" :closeOnClickOverlay="false" :showConfirmButton="false"
|
<van-dialog v-model:show="showFollow" :closeOnClickOverlay="false" :showConfirmButton="false"
|
||||||
style="background: transparent; display: flex; align-items: center; flex-direction: column;">
|
style="background: transparent; display: flex; align-items: center; flex-direction: column;">
|
||||||
<img :src="$file(FollowQRCode)" style="width: 60vw" />
|
<img :src="$file(data.FollowQRCode)" style="width: 60vw" />
|
||||||
<div style="margin: 3.333vw 0">
|
<div style="margin: 3.333vw 0">
|
||||||
<span style="color: #fff">为了更好为您提供服务<br />请长按识别二维码关注公众号</span>
|
<span style="color: #fff">为了更好为您提供服务<br />请长按识别二维码关注公众号</span>
|
||||||
</div>
|
</div>
|
||||||
@ -222,28 +218,8 @@ export default {
|
|||||||
components: { ManagerPopup },
|
components: { ManagerPopup },
|
||||||
computed: {
|
computed: {
|
||||||
},
|
},
|
||||||
beforeRouteEnter(to, from, next) {
|
|
||||||
if (!localStorage.getItem('member_token')) {
|
|
||||||
next({ name: 'Login', query: { redirect: to.fullPath } });
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init();
|
this.init();
|
||||||
this.$get('/v1/client/HWxinfoClient/qrcode').then(res => {
|
|
||||||
this.FollowQRCode = res.data;
|
|
||||||
});
|
|
||||||
if (this.$isWechat()) {
|
|
||||||
// alert(localStorage.getItem('openid'))
|
|
||||||
this.$get(`/v1/client/DUsersClient/subscribe?openid=${localStorage.getItem('openid')}`).then(res => {
|
|
||||||
// alert(JSON.stringify(res))
|
|
||||||
if (res.data === false) {
|
|
||||||
this.showFollow = true;
|
|
||||||
}
|
|
||||||
}).catch(() => { });
|
|
||||||
// this.showFollow = true;
|
|
||||||
}
|
|
||||||
window.addEventListener('showManagerPopup', this.onShowManagerPopup)
|
window.addEventListener('showManagerPopup', this.onShowManagerPopup)
|
||||||
window.addEventListener('closeManagerPopup', this.onCloseManagerPopup)
|
window.addEventListener('closeManagerPopup', this.onCloseManagerPopup)
|
||||||
},
|
},
|
||||||
@ -270,33 +246,27 @@ export default {
|
|||||||
hfLoading: true,
|
hfLoading: true,
|
||||||
isSendCode: false,
|
isSendCode: false,
|
||||||
sendCodeTime: 0,
|
sendCodeTime: 0,
|
||||||
FollowQRCode: '',
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
if (!this.$isLogin()) {
|
Promise.all(
|
||||||
this.$showFailToast('登录状态异常,请重新登录')
|
[
|
||||||
location.replace('#/Login')
|
this.$get('/v1/client/DUsersClient').then(data => {
|
||||||
return
|
// console.log(data);
|
||||||
}
|
this.data = data.data;
|
||||||
window.addEventListener('showManagerPopup', this.onShowManagerPopup)
|
this.$ls.set('cellphone', data.data.cellphone);
|
||||||
window.addEventListener('closeManagerPopup', this.onCloseManagerPopup)
|
this.$ls.set('userimg', data.data.userimg);
|
||||||
Promise.all([
|
this.$ls.set('nickname', data.data.nickname);
|
||||||
this.$get('/v1/client/DUsersClient').then(data => {
|
this.$ls.set('isshop', data.data.isshop);
|
||||||
// console.log(data);
|
this.$ls.set('iscenter', data.data.col2);
|
||||||
this.data = data.data;
|
this.$ls.set('user_id', data.data.id);
|
||||||
this.$ls.set('cellphone', data.data.cellphone);
|
this.$ls.set('huiyuankaid', data.data.huiyuankaid);
|
||||||
this.$ls.set('userimg', data.data.userimg);
|
this.$ls.set('user_cv', data.data.xiaofeiquan);
|
||||||
this.$ls.set('nickname', data.data.nickname);
|
this.$ls.set('user_point', data.data.xiaofeijifen);
|
||||||
this.$ls.set('isshop', data.data.isshop);
|
|
||||||
this.$ls.set('iscenter', data.data.col2);
|
}),
|
||||||
this.$ls.set('user_id', data.data.id);
|
]
|
||||||
this.$ls.set('huiyuankaid', data.data.huiyuankaid);
|
|
||||||
this.$ls.set('user_cv', data.data.xiaofeiquan);
|
|
||||||
this.$ls.set('user_point', data.data.xiaofeijifen);
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
},
|
},
|
||||||
@ -311,7 +281,7 @@ export default {
|
|||||||
this.$showConfirmDialog({
|
this.$showConfirmDialog({
|
||||||
title: "确认退出?",
|
title: "确认退出?",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$ls.remove('member_token');
|
this.$ls.remove('token');
|
||||||
location.replace('#/Login');
|
location.replace('#/Login');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
location.reload();
|
location.reload();
|
||||||
@ -395,7 +365,7 @@ export default {
|
|||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.saving = false;
|
this.saving = false;
|
||||||
this.$ls.remove('member_token');
|
this.$ls.remove('token');
|
||||||
location.replace('#/Login');
|
location.replace('#/Login');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -75,8 +75,7 @@
|
|||||||
|
|
||||||
<div class="list_title">
|
<div class="list_title">
|
||||||
<!-- 直推好友列表({{ total.TotalCount }}) -->
|
<!-- 直推好友列表({{ total.TotalCount }}) -->
|
||||||
<van-tabs v-model:active="active" background="transparent" color="#ad9573" style="font-size: 4vw;"
|
<van-tabs v-model:active="active" background="transparent" color="#ad9573">
|
||||||
font-size="4vw">
|
|
||||||
<van-tab :title="'分享的好友(' + total.friendcount + ')'"></van-tab>
|
<van-tab :title="'分享的好友(' + total.friendcount + ')'"></van-tab>
|
||||||
<van-tab :title="'拓展的商家'"></van-tab>
|
<van-tab :title="'拓展的商家'"></van-tab>
|
||||||
<van-tab :title="'我的推荐人'"></van-tab>
|
<van-tab :title="'我的推荐人'"></van-tab>
|
||||||
@ -224,7 +223,7 @@ export default {
|
|||||||
.merchantinfo img {
|
.merchantinfo img {
|
||||||
width: 12vw;
|
width: 12vw;
|
||||||
height: 12vw;
|
height: 12vw;
|
||||||
/* border-radius: 50%; */
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.merchantinfo .inf {
|
.merchantinfo .inf {
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<div class="db">
|
<div class="db">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<span>金额(元)</span>
|
<span>余额(元)</span>
|
||||||
<b>{{ data.totalsum?.toFixed(2) }}</b>
|
<b>{{ data.totalsum?.toFixed(2) }}</b>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -52,7 +52,7 @@
|
|||||||
<template #default="{ item }">
|
<template #default="{ item }">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="t">
|
<div class="t">
|
||||||
<span class="tit">当前金额:{{ item.balance?.toFixed(2) }}</span>
|
<span class="tit">当前额度:{{ item.balance?.toFixed(2) }}</span>
|
||||||
<span :class="item.nums > 0 ? 'in' : 'out'" class="r">
|
<span :class="item.nums > 0 ? 'in' : 'out'" class="r">
|
||||||
<span v-if="item.nums > 0">增加:+</span>
|
<span v-if="item.nums > 0">增加:+</span>
|
||||||
<span v-else>减少:</span>
|
<span v-else>减少:</span>
|
||||||
|
|||||||
@ -3,8 +3,7 @@
|
|||||||
<div class="verif">
|
<div class="verif">
|
||||||
<div class="search_box">
|
<div class="search_box">
|
||||||
<img src="/img/search.png" alt="">
|
<img src="/img/search.png" alt="">
|
||||||
<input type="text" placeholder="输入用户账号/礼品券码搜索" v-model="keyword1" v-if="type === 'verif'">
|
<input type="text" placeholder="输入用户账号/礼品券码搜索" v-model="keyword1">
|
||||||
<input type="text" placeholder="输入用户账号/会员卡号搜索" v-model="keyword1" v-else>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BaseList ref="listRef"
|
<BaseList ref="listRef"
|
||||||
@ -18,12 +17,9 @@
|
|||||||
<span>{{ item.nickname || item.username || '未知用户' }}</span>
|
<span>{{ item.nickname || item.username || '未知用户' }}</span>
|
||||||
<p>账号:{{ item.cellphone || item.username }}</p>
|
<p>账号:{{ item.cellphone || item.username }}</p>
|
||||||
</div>
|
</div>
|
||||||
<span class="r tt" v-if="type === 'verif'">
|
<span class="r tt">
|
||||||
已核销
|
已核销
|
||||||
</span>
|
</span>
|
||||||
<span class="r pre" v-else>
|
|
||||||
赠送金额 :<b style="color: f00;">500.00</b>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="info_box">
|
<div class="info_box">
|
||||||
<div>
|
<div>
|
||||||
@ -32,27 +28,17 @@
|
|||||||
src="/img/copy_b.png" alt=""></span>
|
src="/img/copy_b.png" alt=""></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="type === 'verif'">
|
<div>
|
||||||
<span class="left">礼品券码:</span>
|
<span class="left">礼品券码:</span>
|
||||||
<span class="r rg">{{ item.sysid }}<img @click="$copyText(item.sysid); $showSuccessToast('复制成功')"
|
<span class="r rg">{{ item.sysid }}<img @click="$copyText(item.sysid); $showSuccessToast('复制成功')"
|
||||||
src="/img/copy_b.png" alt=""></span>
|
src="/img/copy_b.png" alt=""></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else>
|
<div>
|
||||||
<span class="left">会员卡号:</span>
|
|
||||||
<span class="r rg">{{ item.huiyuankaid }}<img
|
|
||||||
@click="$copyText(item.huiyuankaid); $showSuccessToast('复制成功')" src="/img/copy_b.png" alt=""></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="type === 'verif'">
|
|
||||||
<span class="left">核销时间:</span>
|
<span class="left">核销时间:</span>
|
||||||
<span class="r rg">{{ formatTime(item.writeofftime) }}</span>
|
<span class="r rg">{{ formatTime(item.writeofftime) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else>
|
|
||||||
<span class="left">赠送时间:</span>
|
|
||||||
<span class="r rg">{{ formatTime(item.addtime) }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<div class="tit">
|
<div class="tit">
|
||||||
被赠送人账号
|
被赠送人账号
|
||||||
</div>
|
</div>
|
||||||
<input v-model="cellphone" type="text" maxlength="11" @blur="checkExists" placeholder="请输入被赠送人手机号">
|
<input v-model="cellphone" type="text" maxlength="11" @blur="checkExists" placeholder="请输入被赠送人ID">
|
||||||
<hr>
|
<hr>
|
||||||
<span class="errorinfo">{{ errorInfo }}</span>
|
<span class="errorinfo">{{ errorInfo }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -36,8 +36,8 @@
|
|||||||
|
|
||||||
<div class="quota_box">
|
<div class="quota_box">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<b>赠送金额</b>
|
<b>赠送额度</b>
|
||||||
<span class="r" @click="showTerm = true">
|
<span class="r">
|
||||||
<van-icon name="info-o" />
|
<van-icon name="info-o" />
|
||||||
赠送说明
|
赠送说明
|
||||||
</span>
|
</span>
|
||||||
@ -52,11 +52,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
|
|
||||||
<van-action-sheet v-model:show="showTerm" safe-area-inset-bottom :title="`${this.$route.meta.title}说明`" closeable
|
|
||||||
style="min-height: 50%; padding: 0px 10px 10px 10px">
|
|
||||||
<div class="w100 html" v-html="$datadic.getContent('code_hykzssm')" />
|
|
||||||
</van-action-sheet>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -108,7 +103,6 @@ export default {
|
|||||||
amount: 500.00,
|
amount: 500.00,
|
||||||
checked: 'balance',
|
checked: 'balance',
|
||||||
checkedCH: "余额",
|
checkedCH: "余额",
|
||||||
showTerm: false,
|
|
||||||
left: 0,
|
left: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
toUser: { NickName: null },
|
toUser: { NickName: null },
|
||||||
@ -182,7 +176,6 @@ export default {
|
|||||||
}).then(data => {
|
}).then(data => {
|
||||||
if (data.status === 200) {
|
if (data.status === 200) {
|
||||||
this.$showSuccessToast('赠卡成功!')
|
this.$showSuccessToast('赠卡成功!')
|
||||||
this.$navigate('CertificateRecord')
|
|
||||||
}
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
this.$showFailToast(err.message);
|
this.$showFailToast(err.message);
|
||||||
|
|||||||