This commit is contained in:
liushiwei
2023-10-07 15:30:41 +08:00
parent a2f2737741
commit b3804e9b13
11 changed files with 965 additions and 50 deletions

View File

@@ -13,7 +13,9 @@
"core-js": "^3.8.3",
"dayjs": "^1.11.9",
"element-ui": "^2.15.13",
"v-viewer": "^1.6.4",
"vue": "^2.6.14",
"vue-cropper": "^0.6.4",
"vue-json-excel": "^0.3.0",
"vue-qr": "^4.0.9",
"vue-router": "^3.2.0",

244
public/js/FileSaver.js Normal file
View File

@@ -0,0 +1,244 @@
/* FileSaver.js
* A saveAs() FileSaver implementation.
* 2014-11-29
*
* By Eli Grey, http://eligrey.com
* License: X11/MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
*/
/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs = saveAs
// IE 10+ (native saveAs)
|| (typeof navigator !== "undefined" &&
navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
// Everyone else
|| (function(view) {
"use strict";
// IE <10 is explicitly unsupported
if (typeof navigator !== "undefined" &&
/MSIE [1-9]\./.test(navigator.userAgent)) {
return;
}
var
doc = view.document
// only get URL when necessary in case Blob.js hasn't overridden it yet
, get_URL = function() {
return view.URL || view.webkitURL || view;
}
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
, can_use_save_link = "download" in save_link
, click = function(node) {
var event = doc.createEvent("MouseEvents");
event.initMouseEvent(
"click", true, false, view, 0, 0, 0, 0, 0
, false, false, false, false, 0, null
);
node.dispatchEvent(event);
}
, webkit_req_fs = view.webkitRequestFileSystem
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
, throw_outside = function(ex) {
(view.setImmediate || view.setTimeout)(function() {
throw ex;
}, 0);
}
, force_saveable_type = "application/octet-stream"
, fs_min_size = 0
// See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and
// https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047
// for the reasoning behind the timeout and revocation flow
, arbitrary_revoke_timeout = 500 // in ms
, revoke = function(file) {
var revoker = function() {
if (typeof file === "string") { // file is an object URL
get_URL().revokeObjectURL(file);
} else { // file is a File
file.remove();
}
};
if (view.chrome) {
revoker();
} else {
setTimeout(revoker, arbitrary_revoke_timeout);
}
}
, dispatch = function(filesaver, event_types, event) {
event_types = [].concat(event_types);
var i = event_types.length;
while (i--) {
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") {
try {
listener.call(filesaver, event || filesaver);
} catch (ex) {
throw_outside(ex);
}
}
}
}
, FileSaver = function(blob, name) {
// First try a.download, then web filesystem, then object URLs
var
filesaver = this
, type = blob.type
, blob_changed = false
, object_url
, target_view
, dispatch_all = function() {
dispatch(filesaver, "writestart progress write writeend".split(" "));
}
// on any filesys errors revert to saving with object URLs
, fs_error = function() {
// don't create more object URLs than needed
if (blob_changed || !object_url) {
object_url = get_URL().createObjectURL(blob);
}
if (target_view) {
target_view.location.href = object_url;
} else {
var new_tab = view.open(object_url, "_blank");
if (new_tab == undefined && typeof safari !== "undefined") {
//Apple do not allow window.open, see http://bit.ly/1kZffRI
view.location.href = object_url
}
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
revoke(object_url);
}
, abortable = function(func) {
return function() {
if (filesaver.readyState !== filesaver.DONE) {
return func.apply(this, arguments);
}
};
}
, create_if_not_found = {create: true, exclusive: false}
, slice
;
filesaver.readyState = filesaver.INIT;
if (!name) {
name = "download";
}
if (can_use_save_link) {
object_url = get_URL().createObjectURL(blob);
save_link.href = object_url;
save_link.download = name;
click(save_link);
filesaver.readyState = filesaver.DONE;
dispatch_all();
revoke(object_url);
return;
}
// Object and web filesystem URLs have a problem saving in Google Chrome when
// viewed in a tab, so I force save with application/octet-stream
// http://code.google.com/p/chromium/issues/detail?id=91158
// Update: Google errantly closed 91158, I submitted it again:
// https://code.google.com/p/chromium/issues/detail?id=389642
if (view.chrome && type && type !== force_saveable_type) {
slice = blob.slice || blob.webkitSlice;
blob = slice.call(blob, 0, blob.size, force_saveable_type);
blob_changed = true;
}
// Since I can't be sure that the guessed media type will trigger a download
// in WebKit, I append .download to the filename.
// https://bugs.webkit.org/show_bug.cgi?id=65440
if (webkit_req_fs && name !== "download") {
name += ".download";
}
if (type === force_saveable_type || webkit_req_fs) {
target_view = view;
}
if (!req_fs) {
fs_error();
return;
}
fs_min_size += blob.size;
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
var save = function() {
dir.getFile(name, create_if_not_found, abortable(function(file) {
file.createWriter(abortable(function(writer) {
writer.onwriteend = function(event) {
target_view.location.href = file.toURL();
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "writeend", event);
revoke(file);
};
writer.onerror = function() {
var error = writer.error;
if (error.code !== error.ABORT_ERR) {
fs_error();
}
};
"writestart progress write abort".split(" ").forEach(function(event) {
writer["on" + event] = filesaver["on" + event];
});
writer.write(blob);
filesaver.abort = function() {
writer.abort();
filesaver.readyState = filesaver.DONE;
};
filesaver.readyState = filesaver.WRITING;
}), fs_error);
}), fs_error);
};
dir.getFile(name, {create: false}, abortable(function(file) {
// delete file if it already exists
file.remove();
save();
}), abortable(function(ex) {
if (ex.code === ex.NOT_FOUND_ERR) {
save();
} else {
fs_error();
}
}));
}), fs_error);
}), fs_error);
}
, FS_proto = FileSaver.prototype
, saveAs = function(blob, name) {
return new FileSaver(blob, name);
}
;
FS_proto.abort = function() {
var filesaver = this;
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "abort");
};
FS_proto.readyState = FS_proto.INIT = 0;
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error =
FS_proto.onwritestart =
FS_proto.onprogress =
FS_proto.onwrite =
FS_proto.onabort =
FS_proto.onerror =
FS_proto.onwriteend =
null;
return saveAs;
}(
typeof self !== "undefined" && self
|| typeof window !== "undefined" && window
|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
if (typeof module !== "undefined" && module !== null) {
module.exports = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) {
define([], function() {
return saveAs;
});
}

75
public/js/download.js Normal file
View File

@@ -0,0 +1,75 @@
function init() {
if (window.location.href.startsWith('https://www.aliexpress.us/item/')) {
const popup = document.createElement("div")
popup.innerText = "下载图片"
const styles = {
position: "fixed",
right: '10px',
top: '60px',
zIndex: 9999,
padding: "8px",
background: "#409EFF",
color: "#fff",
borderRadius: "8px",
cursor: "pointer"
}
for (const e in styles) {
popup.style[e] = styles[e]
}
popup.addEventListener('click', async () => {
let obj = window.runParams.data;
let id = obj.productInfoComponent.idStr
var baseList = [];
var downloadList = []
var imgObjList = document.querySelectorAll('#product-description img')
for (var i = 0; i < imgObjList.length; i++) {
baseList.push({type: 0, index: i+1, src: imgObjList[i].src})
}
for (var j = 0; j < obj.imageComponent.imagePathList.length; j++) {
baseList.push({type: 1, index: j+1, src: obj.imageComponent.imagePathList[j]})
}
var zip = new JSZip();
var imgsBanner = zip.folder("轮插图");
var imgsDetail = zip.folder("详情图");
for (var k = 0; k < baseList.length; k++) {
let type = baseList[k].type
let index = baseList[k].index
let image = new Image();
// 解决跨域 Canvas 污染问题
image.setAttribute("crossOrigin", "anonymous");
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
let url = canvas.toDataURL(); // 得到图片的base64编码数据
canvas.toDataURL("image/png");
downloadList.push({type: type, index: index, data: url.substring(22)}); // 去掉base64编码前的 data:image/png;base64,
if (downloadList.length === baseList.length && downloadList.length > 0) {
for (let l = 0; l < downloadList.length; l++) {
if (downloadList[l].type == '0') {
imgsDetail.file(`详情图${downloadList[l].index}.png`, downloadList[l].data, { base64: true });
} else if (downloadList[l].type == '1') {
imgsBanner.file(`轮播图${downloadList[l].index}.png`, downloadList[l].data, { base64: true });
}
}
zip.generateAsync({ type: "blob" }).then(function (content) {
// see FileSaver.js
saveAs(content, "aliexpress_" + id + ".zip");
});
}
};
image.src = baseList[k].src;
}
})
document.body.appendChild(popup)
}
}
init();

13
public/js/jszip.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,17 +1,30 @@
<template>
<section class="AiPayment">
<el-tabs type="card" stretch v-model="search.module" @tab-click="getPayments">
<el-tab-pane label="激活码兑换" name="2"/>
<el-tab-pane label="基础会员" name="0"/>
<el-tab-pane label="金币充值" name="1"/>
</el-tabs>
<div class="content">
<div v-if="search.module == '0' " style="grid-template-columns: 1fr 1fr" class="payments mb-16">
<div v-if="search.module == '0'" class="mb-16">
<div style="grid-template-columns: 1fr 1fr" class="payments ">
<div class="card" v-for="pay in payments" :key="pay.id" :class="{active:pay.id==selected.id}"
@click="getQrcode(pay)">
<div v-text="pay.title"/>
<div class="c-f00 mt-16" v-text="`¥${pay.price}`"/>
</div>
</div>
<div>
<el-form :model="vipForm" label-position="top" ref="vipForm" label-width="100px" class="form">
<el-form-item
prop="mallName"
label="当前绑定店铺"
:rules="[{ required: true, message: '请先登录拼多多跨境卖家中心', trigger: 'blur' }]">
<el-input readonly placeholder="请先登录拼多多跨境卖家中心" v-model="vipForm.mallName"></el-input>
</el-form-item>
</el-form>
</div>
</div>
<div v-else-if="search.module == '1' " class="payments mb-16">
<div class="card" v-for="pay in payments" :key="pay.id" :class="{active:pay.id==selected.id}"
@click="getQrcode(pay)">
@@ -22,6 +35,28 @@
<div class="c-999 mt-16" v-text="`${pay.coin}金币`"/>
</div>
</div>
<div v-else-if="search.module == '2'" style="grid-template-columns: 1fr" class="payments mb-16">
<el-form :model="form" label-position="top" ref="form" label-width="100px" class="form">
<el-form-item
prop="mallName"
label="当前绑定店铺"
:rules="[{ required: true, message: '请先登录拼多多跨境卖家中心', trigger: 'blur' }]">
<el-input readonly placeholder="请先登录拼多多跨境卖家中心" v-model="form.mallName"></el-input>
</el-form-item>
<el-form-item
prop="mallId"
v-show="false"
:rules="[{ message: '请输入商城ID', trigger: 'blur' }]">
<el-input placeholder="请输入商城ID" v-model="form.mallId"></el-input>
</el-form-item>
<el-form-item
prop="code"
label="激活码"
:rules="[{ required: true, message: '请输入激活码', trigger: 'blur' }]">
<el-input placeholder="请输入激活码" v-model="form.code"></el-input>
</el-form-item>
</el-form>
</div>
<el-row type="flex" align="middle">
<ul class="fill" v-if="search.module == '0'">
<li v-for="(desc,i) in descriptionsModule0" :key="i" v-text="desc"/>
@@ -29,7 +64,7 @@
<ul class="fill" v-if="search.module == '1'">
<li v-for="(desc,i) in descriptionsModule1" :key="i" v-text="desc"/>
</ul>
<div class="fill flex-center">
<div class="fill flex-center" v-if="search.module != '2'">
<vue-qr v-if="qrcode" :text="qrcode" :size="120" :margin="8" :logoSrc="wechatLogo"/>
<div v-else class="qrcode c-666">请选择<br>项目</div>
<div class="c-999 ml-16">
@@ -43,14 +78,19 @@
</div>
</div>
</el-row>
<div class="bottom flex-center">
<el-button size="small" @click="$emit('cancel')">取消支付</el-button>
<el-button size="small" @click="$emit('ok')">已扫码支付</el-button>
<div class="bottom flex-center" v-if="search.module != '2'">
<el-button size="small" @click="$store.commit('setActiveDlgShow', false)">取消支付</el-button>
<el-button size="small" @click="paied">已扫码支付</el-button>
</div>
<div class="bottom flex-center" v-else>
<el-button size="small" @click="$store.commit('setActiveDlgShow', false)">取消</el-button>
<el-button size="small" @click="active">确定</el-button>
</div>
</div>
</section>
</template>
<script>
import { Message } from "element-ui"
import VueQr from "vue-qr"
export default {
@@ -59,6 +99,17 @@ export default {
props: {},
data() {
return {
form: {
mallId: this.$store.state.mallId,
mallName: this.$store.state.mallName,
code: ''
},
vipForm: {
mallId: this.$store.state.mallId,
mallName: this.$store.state.mallName
},
vipType: ["体验会员","年会员","年会员多店通用"],
search: {module: "0"},
show: true,
descriptionsModule0: ["抢仓发货", "数据下载", "复制商品", "会员服务"],
@@ -74,6 +125,7 @@ export default {
},
methods: {
getPayments() {
if (this.search.module == '2') return
this.$http.post("/api/priceConfig/page", null, {
params: {...this.search}
}).then(res => {
@@ -83,7 +135,10 @@ export default {
})
},
getQrcode(item) {
if (item.module == '0' && !this.vipForm.mallId) {
Message.error("请先登录拼多多垮境卖家中心")
return
}
this.selected = item
this.$http.post("/api/order/createOrder", null, {
params: {priceConfigId: item.id}
@@ -98,6 +153,43 @@ export default {
this.qrcode = res.data.codeUrl
}
})
},
paied() {
this.$store.dispatch('getUserInfo')
this.$store.commit('setActiveDlgShow', false)
},
active() {
this.$refs.form.validate((valid) => {
if (valid) {
this.$http.post(`/api/coupon/getDetail`, null, {
params: {
code: this.form.code
}
}).then(res => {
if (res.code == 0) {
let msg = this.getMessage(res.data.type);
this.$confirm(msg, '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'info'
}).then(() => {
this.$http.post(`/api/order/upgradeByCode`, null, {
params: {
...this.form
}
}).then(res => {
if (res.code == 0) {
this.$message.success('激活成功')
this.$store.dispatch('getUserInfo')
this.$store.commit('setActiveDlgShow', false)
}
})
})
}
});
}
})
}
},
created() {

View File

@@ -0,0 +1,497 @@
<template>
<section class="uploader">
<el-upload
action
multiple
ref="upload"
:class="{validError:!validateState}"
:http-request="submitUpload"
:on-remove="handleRemove"
:on-change="handleChange"
:before-upload="onBeforeUpload"
:file-list="fileList"
:limit="limit"
:disabled="disabled"
:list-type="isImg ? 'picture-card' : 'text'"
:accept="accept"
:show-file-list="!isSingle"
:on-preview="handlePictureCardPreview"
:auto-upload="isAutoUpload"
:on-exceed="handleExceed">
<template v-if="!disabled">
<template v-if="hasUploaded&&isSingle">
<div class="fileItem">
<div class="uploadFile" @click.stop>
<div class="info">
<span v-text="uploadFile.name"/>
<span class="size" v-text="uploadFile.size"/>
</div>
</div>
<el-button>重新选择</el-button>
<el-button v-if="clearable" plain type="danger" @click.stop="handleClear">删除</el-button>
</div>
</template>
<template v-else-if="limit > fileList.length">
<slot v-if="hasTriggerSlot" name="trigger"/>
<div v-else class="uploaderBox">
<span class="iconfont" :class="isImg ? 'iconPhoto' : 'iconAdd'"/>
<p>上传{{ isImg ? '图片' : '附件' }}</p>
</div>
</template>
<div slot="tip" class="el-upload__tip" v-if="showTips">
<p v-if="fileType === 'img' && !acceptType && !hasTipsSlot">最多上传{{
limit
}}张图片,单个文件最大10MB支持jpgjpegpng格式</p>
<p v-if="fileType === 'file' && !acceptType && !hasTipsSlot">最多上传{{ limit }}个附件,单个文件最大10MB</p>
<p v-if="fileType === 'file' && !acceptType && !hasTipsSlot">
支持.zip.rar.doc.docx.xls.xlsx.ppt.pptx.pdf.txt.jpg.png格式</p>
<p>
<slot name="tips" v-if="hasTipsSlot"></slot>
</p>
</div>
</template>
</el-upload>
<el-dialog :visible.sync="dialog" title="图片预览编辑器" :modal="false" :show-close="false" z-index="202204131734"
append-to-body>
<vue-cropper
ref="cropper"
style="height: 400px;"
:img="fileList.length ? fileList[0].url : ''" v-bind="crop"/>
<div style="text-align: center;margin-top: 10px;">
<el-radio-group v-if="crop.fixed" size="small" v-model="currFixedIndex" @change="onFixedChange"
style="margin-right: 8px;">
<el-radio-button
:label="0"
size="small">
1.6:1
</el-radio-button>
<el-radio-button
:label="1"
size="small">
4:3
</el-radio-button>
</el-radio-group>
<el-button size="small" circle icon="el-icon-refresh-right" @click="$refs.cropper.rotateRight()"></el-button>
<el-button size="small" circle icon="el-icon-refresh-left" @click="$refs.cropper.rotateLeft()"></el-button>
</div>
<div slot="footer">
<el-button type="primary" @click="previewCrop">保存</el-button>
<el-button @click="onClose">关闭</el-button>
</div>
</el-dialog>
<div class="images" v-viewer="{movable: true}" v-show="false">
<img v-for="(item, index) in imgList" :src="item" :key="index" alt="">
</div>
</section>
</template>
<script>
import {VueCropper} from 'vue-cropper'
import 'viewerjs/dist/viewer.css'
import Viewer from 'v-viewer'
import Vue from "vue";
Viewer.setDefaults({
zIndex: 20170
})
Vue.use(Viewer)
export default {
name: 'AiUploader',
components: {VueCropper},
inject: {
elFormItem: {default: ""},
elForm: {default: ''},
},
model: {
prop: 'value',
event: 'change'
},
props: {
value: {default: () => []},
url: {
type: String,
default: '/api/upload/uploadFile?folder=admin'
},
isShowTip: {
type: Boolean,
default: false
},
isWechat: {
type: Boolean,
default: false
},
maxSize: {
type: Number,
default: 10
},
instance: Function,
acceptType: {type: String},
fileType: {type: String, default: 'img'},
limit: {type: Number, default: 9},
disabled: {type: Boolean, default: false},
isCrop: {type: Boolean, default: false},
cropOps: Object,
isImport: {
type: Boolean,
default: false
},
clearable: {default: true},
valueIsUrl: Boolean
},
data() {
return {
fileList: [],
dialog: false,
currFixedIndex: 0,
}
},
watch: {
value: {
handler(v) {
this.dispatch('ElFormItem', 'el.form.change', [v]);
if (v?.length > 0) {
this.fileList = this.valueIsUrl ? v?.split(",")?.map(url => ({url})) : [...v]
}
},
immediate: true,
deep: true
}
},
computed: {
isImg() {
return this.fileType === 'img'
},
validateState() {
return ['', 'success'].includes(this.elFormItem?.validateState)
},
isAutoUpload() {
return !(this.isCrop || this.isImport);
},
hasTipsSlot() {
return this.$slots.tips
},
hasTriggerSlot() {
return this.$slots.trigger
},
accept() {
if (this.acceptType) {
return this.acceptType
}
return this.isImg ? '.jpg,.png,.jpeg' : '.zip,.rar,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.txt,.jpg,.png'
},
crop() {
return {
autoCrop: true,
outputType: 'png',
fixedBox: false,
fixed: true,
fixedNumber: [1.6, 1],
width: 0,
height: 0,
...this.cropOps
}
},
imgList() {
return this.fileList.map(v => v.url)
},
isSingle() {
return this.limit == 1 && this.isImport
},
showTips() {
return this.isShowTip || this.$slots.tips
},
hasUploaded() {
return this.fileList?.length > 0
},
uploadFile() {
let file = this.fileList?.[0],
size = Number(file.size),
icon = "iconTxt"
//显示大小
if (size > Math.pow(1024, 2)) {
size = (size / Math.pow(1024, 2)).toFixed(1) + 'MB'
} else {
size = (size / 1024).toFixed(1) + 'KB'
}
//显示图标
if (/\.(xls|xlsx)$/.test(file.name)) {
icon = "iconExcel"
} else if (/\.(zip)$/.test(file.name)) {
icon = "iconZip"
} else if (/\.(rar)$/.test(file.name)) {
icon = "iconRar"
} else if (/\.(png)$/.test(file.name)) {
icon = "iconPng"
} else if (/\.(pptx|ppt)$/.test(file.name)) {
icon = "iconPPT"
} else if (/\.(doc|docx)$/.test(file.name)) {
icon = "iconWord"
}
return {...file, size, icon}
}
},
methods: {
onFixedChange(e) {
this.fixedNumber = e === 0 ? [1.6, 1] : [4, 3]
this.$nextTick(() => {
this.$refs.cropper.goAutoCrop()
})
},
handleChange(file, fileList) {
if (this.isImport) {
if (!this.onOverSize(file)) {
this.fileList = []
return false
}
this.fileList = fileList
this.emitChange(fileList)
return false
}
if (this.isCrop) {
if (file.raw.type === 'image/gif') {
this.$message.error(`不支持gif格式的图片`)
this.fileList = []
return false
}
if (!this.onOverSize(file)) {
this.fileList = []
return false
}
this.dialog = true
this.fileList = fileList
} else {
this.fileList = fileList
}
},
handleExceed(files) {
if (this.isSingle && files[0]) {
this.$refs.upload?.clearFiles()
this.$refs.upload?.handleStart(files[0])
} else this.$message.warning(`最多上传${this.limit}${this.isImg ? '图片' : '文件'}`)
},
handlePictureCardPreview(file) {
if (this.fileType !== 'img') return
const index = this.imgList.indexOf(file.url)
const viewer = this.$el.querySelector('.images').$viewer
viewer.view(index)
},
handleRemove(file, fileList) {
this.fileList = fileList
this.emitChange(fileList)
},
emitChange(files) {
this.$emit('change', this.valueIsUrl ? files?.map(e => e.url)?.toString() : files)
},
handleClear() {
this.fileList = []
},
getExtension(name) {
return name.substring(name.lastIndexOf('.'))
},
onOverSize(e) {
const isLt10M = e.size / 1024 / 1024 < this.maxSize
const suffixName = this.getExtension(e.name)
const suffixNameList = this.accept.split(',')
if (suffixNameList.indexOf(`${suffixName.toLowerCase()}`) === -1) {
this.$message.error(`不支持该格式`)
return false
}
if (!isLt10M) {
this.$message.error(`${this.isImg ? '图片' : '文件'}大小不超过${this.maxSize}MB!`)
return false
}
return true
},
onBeforeUpload(event) {
return this.onOverSize(event)
},
onClose() {
this.fileList = []
this.dialog = false
},
submitUpload(file) {
let formData = new FormData()
formData.append('file', file.file)
this.instance.post(this.url, formData, {
withCredentials: false
}).then(res => {
if (res?.code == 0) {
let data = res.data
this.fileList.forEach(item => {
if (item.uid === file.file.uid) {
item.path = data
item.url = data
}
})
this.emitChange(this.fileList)
this.$message.success('上传成功')
}
})
},
previewCrop() {
this.$refs.cropper.getCropBlob(data => {
data.name = this.fileList[0].name;
this.fileList[0].file = new window.File([data], data.name, {type: data.type})
this.fileList[0].file.uid = this.fileList[0].uid
})
setTimeout(() => document.querySelector('.v-modal').style.zIndex = 2000, 500)
this.$confirm('是否关闭图片预览器,并上传图片?', {type: "warning"}).then(() => {
this.submitUpload(this.fileList[0])
this.dialog = false
}).catch(() => 0)
},
/**
* 表单验证
* @param componentName
* @param eventName
* @param params
*/
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;
let name = parent.$options.componentName;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
}
}
</script>
<style lang="scss" scoped>
.uploader {
line-height: 1;
::v-deep.el-upload {
width: 100%;
text-align: start;
}
::v-deep.validError {
.el-button {
border-color: #f46;
color: #f46;
}
}
::v-deep.el-upload--picture-card {
border: none;
}
::v-deep .el-list-leave-active, ::v-deep .el-upload-list__item {
transition: all 0s !important;
}
::v-deep.el-upload-list--picture-card .el-upload-list__item {
width: 120px;
height: 120px;
border-radius: 4px;
}
::v-deep.el-upload--picture-card {
width: auto;
height: auto;
}
.el-upload__tip p {
color: #999;
line-height: 16px;
}
::v-deep.fileItem {
width: 100%;
height: 60px;
background: #FFFFFF;
border-radius: 2px;
border: 1px solid #D0D4DC;
display: flex;
align-items: center;
padding: 0 16px;
cursor: default;
.uploadFile {
text-align: start;
flex: 1;
min-width: 0;
display: flex;
color: #222;
.AiIcon {
width: 40px;
height: 40px;
}
.info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
margin-left: 8px;
margin-right: 40px;
line-height: 22px;
}
.size {
color: #888;
}
}
}
.uploaderBox {
width: 120px;
height: 120px;
line-height: 1;
background: #F3F4F7;
border-radius: 2px;
border: 1px solid #D0D4DC;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&:hover {
opacity: 0.6;
}
span {
font-size: 32px;
color: #8899bb;
&:hover {
color: #8899bb;
}
}
p {
margin: 0;
padding-top: 4px;
color: #555;
font-size: 12px;
text-align: center;
line-height: 1;
}
}
}
</style>

View File

@@ -1,25 +1,10 @@
// import {genAnti} from "@/api/genAnti";
// const popup = document.createElement("div")
// popup.innerText = "获取Anti"
// const styles = {
// position: "fixed",
// right: '10px',
// top: '60px',
// zIndex: 9999,
// padding: "8px",
// background: "#409EFF",
// color: "#fff",
// borderRadius: "8px",
// cursor: "pointer"
// }
// for (const e in styles) {
// popup.style[e] = styles[e]
// }
//
// popup.addEventListener('click', async () => {
// const anti = await genAnti.a()
// console.log(anti)
// })
// document.body.appendChild(popup)
function injectScript(file, node) {
var th = document.getElementsByTagName(node)[0];
var s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.setAttribute('src', file);
th.appendChild(s);
}
injectScript( chrome.runtime.getURL('/js/jszip.min.js'), 'body');
injectScript( chrome.runtime.getURL('/js/FileSaver.js'), 'body');
injectScript( chrome.runtime.getURL('/js/download.js'), 'body');

View File

@@ -39,11 +39,17 @@
"content_scripts": [
{
"matches": [
"<all_urls>"
"*://*.aliexpress.us/item/*"
],
"js": [
"/content.js"
]
}
],
"web_accessible_resources": [
{
"resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ],
"matches": [ "*://*.aliexpress.us/*" ]
}
]
}

View File

@@ -39,11 +39,17 @@
"content_scripts": [
{
"matches": [
"<all_urls>"
"*://*.aliexpress.us/item/*"
],
"js": [
"/content.js"
]
}
],
"web_accessible_resources": [
{
"resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ],
"matches": [ "*://*.aliexpress.us/*" ]
}
]
}

View File

@@ -85,16 +85,12 @@
</div>
</div>
<el-dialog
title="用户激活"
title="激活充值"
:visible="$store.state.activeDlgShow"
:close-on-click-modal="false"
width="1200"
:before-close="handleClose">
<ai-payment/>
<span slot="footer" class="dialog-footer">
<el-button @click="setActiveDlgShow(false)"> </el-button>
<el-button type="primary" @click="active"> </el-button>
</span>
</el-dialog>
</div>
</template>

View File

@@ -33,8 +33,7 @@
</ai-search-bar>
<ai-search-bar>
<template #left>
<el-button type="button" :class="'el-button el-button--primary'" @click="beforeCopy(1)">从TEMU复制</el-button>
<el-button type="button" :class="'el-button el-button--primary'" @click="beforeCopy(2)">从速卖通复制</el-button>
<el-button type="button" :class="'el-button el-button--primary'" @click="beforeCopy()">开始复制</el-button>
</template>
</ai-search-bar>
<ai-table
@@ -57,14 +56,14 @@
customFooter
@close="handleClose">
<el-form class="ai-form" :model="form" label-width="140px" ref="form">
<el-form-item label="商品来源:" v-show="false" style="width: 100%;" prop="type" :rules="[{ required: true, message: '请选择商品来源', trigger: 'blur' }]">
<el-form-item label="商品来源:" style="width: 100%;" prop="type" :rules="[{ required: true, message: '请选择商品来源', trigger: 'blur' }]">
<el-radio-group v-model="form.type" size="medium">
<el-radio :label="1">TEMU</el-radio>
<el-radio :label="2">速卖通</el-radio>
<!--<el-radio :label="2">速卖通</el-radio>-->
</el-radio-group>
</el-form-item>
<el-form-item label="商品地址:" style="width: 100%;" prop="url" :rules="[{ required: true, message: '请输入商品地址', trigger: 'blur' }]">
<el-input type="textarea" v-model="form.url"></el-input>
<el-input type="textarea" :rows="5" v-model="form.url"></el-input>
</el-form-item>
<el-form-item label="店铺:" style="width: 100%;" prop="targetMallId" :rules="[{ required: true, message: '请选择店铺', trigger: 'blur' }]">
<el-select style="width: 380px" v-model="form.targetMallId" placeholder="请选择">
@@ -248,7 +247,7 @@ const ImageEditor = require('tui-image-editor')
}
export default {
name: 'CopyProduct',
name: 'NiubiCopy',
data () {
return {
@@ -323,8 +322,8 @@ const ImageEditor = require('tui-image-editor')
handleClose() {
this.copyFromDlgShow = false
},
beforeCopy(type) {
this.form.type = type
beforeCopy() {
this.form.type = 1
this.form.url = ''
this.copyFromDlgShow = true
},