调整
This commit is contained in:
@@ -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
244
public/js/FileSaver.js
Normal 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
75
public/js/download.js
Normal 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
13
public/js/jszip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -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() {
|
||||
|
||||
497
src/components/AiUploader.vue
Normal file
497
src/components/AiUploader.vue
Normal 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,支持jpg、jpeg、png格式</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>
|
||||
@@ -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');
|
||||
|
||||
@@ -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/*" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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/*" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user