This commit is contained in:
liushiwei
2024-10-25 18:33:21 +08:00
17 changed files with 113528 additions and 1276 deletions

55930
node_modules/vue-plugin-hiprint/dist/vue-plugin-hiprint.js generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -8,14 +8,17 @@
},
"dependencies": {
"@antv/g2plot": "^2.4.25",
"@babel/standalone": "^7.25.8",
"axios": "^1.4.0",
"bi-vue-mindmap": "^0.6.12",
"core-js": "^3.8.3",
"crypto-js": "^4.0.0",
"dayjs": "^1.11.9",
"element-ui": "^2.15.13",
"eval5": "^1.4.8",
"file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
"jsbarcode": "^3.11.6",
"query-string": "^9.0.0",
"spark-md5": "^3.0.2",
"v-viewer": "^1.6.4",

View File

@@ -347,3 +347,36 @@ table.hiprint-printElement-tableTarget {
text-align: left;
clear: both;
}
.temuBarCode {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
width: 100%;
height: 100%;
padding: 10pt 10pt;
border: 2pt solid #000;
}
.temuBarCode-code {
width: 100%;
height: 100%;
}
.temuBarCode-code svg {
width: 100%;
}
.temuBarCode-top,
.temuBarCode-bottom {
display: flex;
align-items: center;
justify-content: space-between;
width: 93%;
}
.temuBarCode-middle {
width: 85%;
height: 60%;
}

View File

@@ -1,18 +1,56 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" type="text/css" media="print" href="<%= BASE_URL %>css/print-lock.css">
<title>TEMU助手</title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" type="text/css" media="print" href="<%= BASE_URL %>css/print-lock.css">
<title>TEMU助手</title>
<style>
.temuBarCode {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
width: 100%;
height: 100%;
padding: 10pt 10pt;
border: 2pt solid #000;
}
.temuBarCode-code {
width: 100%;
height: 100%;
}
.temuBarCode-code svg {
width: 100%;
}
.temuBarCode-top,
.temuBarCode-bottom {
display: flex;
align-items: center;
justify-content: space-between;
width: 93%;
}
.temuBarCode-middle {
width: 85%;
height: 60%;
}
</style>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -1,21 +1,22 @@
@import "./styles.scss";
@font-face {
font-family: 'iconfont'; /* project id 1995974 */
font-family: 'iconfont';
/* project id 1995974 */
src: url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.eot');
src: url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.eot?#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.woff2') format('woff2'),
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.woff') format('woff'),
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.ttf') format('truetype'),
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.svg#iconfont') format('svg');
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.woff2') format('woff2'),
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.woff') format('woff'),
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.ttf') format('truetype'),
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.svg#iconfont') format('svg');
}
@font-face {
font-family: "iconfont";
src: url('https://at.alicdn.com/t/c/font_4680344_rxl7gevvsys.woff2?t=1725970465332') format('woff2'),
url('https://at.alicdn.com/t/c/font_4680344_rxl7gevvsys.woff?t=1725970465332') format('woff'),
url('https://at.alicdn.com/t/c/font_4680344_rxl7gevvsys.ttf?t=1725970465332') format('truetype');
url('https://at.alicdn.com/t/c/font_4680344_rxl7gevvsys.woff?t=1725970465332') format('woff'),
url('https://at.alicdn.com/t/c/font_4680344_rxl7gevvsys.ttf?t=1725970465332') format('truetype');
}
.iconfont {
@@ -28,8 +29,10 @@
}
html {
line-height: 1; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
line-height: 1;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
}
body {
@@ -43,14 +46,19 @@ h1 {
hr {
-webkit-box-sizing: content-box;
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
box-sizing: content-box;
/* 1 */
height: 0;
/* 1 */
overflow: visible;
/* 2 */
}
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
a {
@@ -58,10 +66,13 @@ a {
}
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
border-bottom: none;
/* 1 */
text-decoration: underline;
/* 2 */
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted; /* 2 */
text-decoration: underline dotted;
/* 2 */
}
b,
@@ -72,8 +83,10 @@ strong {
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
small {
@@ -105,14 +118,19 @@ input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
font-family: inherit;
/* 1 */
font-size: 100%;
/* 1 */
line-height: 1.15;
/* 1 */
margin: 0;
/* 2 */
}
button,
input { /* 1 */
input {
/* 1 */
overflow: visible;
font-family: SJsuqian;
}
@@ -124,7 +142,8 @@ input::placeholder {
}
button,
select { /* 1 */
select {
/* 1 */
text-transform: none;
}
@@ -156,12 +175,18 @@ fieldset {
legend {
-webkit-box-sizing: border-box;
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
box-sizing: border-box;
/* 1 */
color: inherit;
/* 2 */
display: table;
/* 1 */
max-width: 100%;
/* 1 */
padding: 0;
/* 3 */
white-space: normal;
/* 1 */
}
progress {
@@ -175,8 +200,10 @@ textarea {
[type="checkbox"],
[type="radio"] {
-webkit-box-sizing: border-box;
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
box-sizing: border-box;
/* 1 */
padding: 0;
/* 2 */
}
[type="number"]::-webkit-inner-spin-button,
@@ -185,8 +212,10 @@ textarea {
}
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
[type="search"]::-webkit-search-decoration {
@@ -194,8 +223,10 @@ textarea {
}
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
details {
@@ -214,7 +245,10 @@ template {
display: none;
}
h1, h2, h3, h4 {
h1,
h2,
h3,
h4 {
font-weight: normal;
font-size: 14px;
padding: 0;
@@ -232,7 +266,8 @@ a {
transition: all .3s ease;
}
ul, li {
ul,
li {
list-style: none;
margin: 0;
padding: 0;
@@ -246,7 +281,8 @@ img {
vertical-align: middle;
}
html, body {
html,
body {
width: 100%;
min-height: 100vh;
}
@@ -276,7 +312,8 @@ img {
display: flex;
}
.flex-align, .flex-center {
.flex-align,
.flex-center {
display: flex;
align-items: center;
}
@@ -312,11 +349,13 @@ img {
flex: 1;
}
.fade-enter-active, .fade-leave-active {
.fade-enter-active,
.fade-leave-active {
transition: opacity .3s ease-in-out;
}
.fade-enter, .fade-leave-to {
.fade-enter,
.fade-leave-to {
opacity: 0;
}
@@ -387,7 +426,8 @@ img {
line-height: 17px;
margin-bottom: 14px;
font-size: 14px;
font-family: SJsuqian;;
font-family: SJsuqian;
;
label {
margin-right: 6px;
@@ -437,7 +477,8 @@ img {
background-color: #1FBAD6;
}
.el-button--danger:focus, .el-button.el-button--danger.is-link:not(.is-disabled):hover {
.el-button--danger:focus,
.el-button.el-button--danger.is-link:not(.is-disabled):hover {
color: #fff !important;
border-color: #FA5555;
background-color: #FA5555;
@@ -478,17 +519,17 @@ img {
.search-item {
display: flex;
align-items: center;
margin: 0 16px 12px;
margin: 0 25px 10px 0;
label {
&>label {
width: 80px;
font-size: 14px;
color: #666;
font-weight: 500;
width: 100px;
}
input {
width: 240px;
// width: 240px;
}
}

View File

@@ -1,6 +1,6 @@
<template>
<section class="ai-dialog__wrapper">
<el-dialog custom-class="ai-dialog" v-on="$listeners" v-bind="$attrs" :visible.sync="dialog">
<el-dialog custom-class="ai-dialog" v-on="$listeners" v-bind="$attrs" :visible.sync="dialog" :close-on-click-modal="false">
<div class="ai-dialog__header fill" slot="title" v-text="title"/>
<div class="ai-dialog__content">
<div class="ai-dialog__content--wrapper">

View File

@@ -1,6 +1,6 @@
<template>
<div class="print">
<div class="print-wrapper">
<div class="print-wrapper" v-if="!isPrint">
<div class="left">
<div class="left-wrapper">
<div class="title">基础元素</div>
@@ -9,10 +9,6 @@
<i class="iconfont">&#xe649;</i>
<span>文本</span>
</div>
<div v-if="false" class="ep-draggable-item item" tid="defaultModule.image">
<i class="iconfont">&#xe61e;</i>
<span>图片</span>
</div>
<div class="ep-draggable-item item" tid="defaultModule.longText">
<i class="iconfont">&#xe7dc;</i>
<span>长文</span>
@@ -22,7 +18,7 @@
<span>表格</span>
</div>
<div class="ep-draggable-item item" tid="defaultModule.html">
<i class="iconfont">&#xe633;</i>
<i class="iconfont">&#xea3f;</i>
<span>html</span>
</div>
</div>
@@ -47,21 +43,19 @@
</div>
<div class="title">常用元素</div>
<div class="left-item__wrapper" id="custom-provider">
<div class="ep-draggable-item item" tid="defaultModule.hline">
<i class="iconfont">&#xe7dd;</i>
<span>横线</span>
</div>
<div class="ep-draggable-item item" tid="defaultModule.vline">
<i class="iconfont">&#xe70f;</i>
<span>竖线</span>
</div>
<div class="ep-draggable-item item" tid="defaultModule.rect">
<i class="iconfont">&#xe620;</i>
<span>矩形</span>
</div>
<div class="ep-draggable-item item" tid="defaultModule.oval">
<i class="iconfont">&#xe76a;</i>
<span>圆形</span>
</div>
<div class="title">
<span>动态数据如日期</span>
<el-button type="primary" size="mini" @click="addField">添加</el-button>
</div>
<div class="left-item__wrapper">
<div
class="item"
v-for="(item, index) in dynamicFromList"
:key="index"
style="cursor: pointer;"
@click="addItemToCanvas(item.fieldValue)">
<div>{{ item.fieldValue }}</div>
</div>
</div>
</div>
@@ -112,14 +106,26 @@
<el-button @click="isShowPreview = false">取消</el-button>
</div>
</ai-dialog>
<ai-dialog
:visible.sync="isShowDynamicForm"
title="动态数据"
width="590px"
@confirm="onConfirm">
<el-form :model="dynamicFrom" ref="form" label-width="100px">
<el-form-item
label="数据名称:"
:prop="`field${dynamicFromList.length}`"
:rules="[{ required: true, message: '请再次输入密码', trigger: 'blur' }]">
<el-input placeholder="请输入数据名称" type="text" v-model="dynamicFrom[`field${dynamicFromList.length}`]"></el-input>
</el-form-item>
</el-form>
</ai-dialog>
</div>
</template>
<script>
import { hiprint, defaultElementTypeProvider, disAutoConnect } from 'vue-plugin-hiprint'
import { newHiprintPrintTemplate } from '@/utils/template-helper'
import template from './template'
import printData from './printData'
import { customProvider } from './customProvider'
disAutoConnect()
@@ -131,6 +137,41 @@
default: () => {
return []
}
},
printData: {
type: Object,
default: () => {
return {
}
}
},
template: {
type: Object,
default: () => {
return {
"index": 0,
"name": 1,
"height": 200,
"width": 200,
"paperHeader": 0,
"paperFooter": 547,
"printElements": [],
"paperNumberLeft": 500,
"paperNumberTop": 530,
"paperNumberDisabled": true,
"paperNumberContinue": true,
"fontFamily": "Microsoft YaHei",
"scale": 1,
"watermarkOptions": {}
}
}
},
isPrint: {
type: Boolean,
default: false
}
},
@@ -171,8 +212,14 @@
}
},
paperPopVisible: false,
paperWidth: '80',
paperHeight: '60'
paperWidth: 200,
paperHeight: 200,
isShowDynamicForm: false,
dynamicFrom: {
},
dynamicFromList: [],
panel: null
}
},
@@ -196,22 +243,84 @@
providers: [defaultElementTypeProvider(), customProvider({})]
})
this.buildLeftElement()
this.buildDesigner()
if (this.isPrint) {
this.hiprintTemplate = newHiprintPrintTemplate('temulables', {
template: this.template
})
} else {
this.buildLeftElement()
this.buildDesigner()
}
},
methods: {
addField() {
this.$set(this.dynamicFrom, `field${this.dynamicFromList.length}`, '')
this.isShowDynamicForm = true
},
addItemToCanvas(name) {
this.panel.addPrintText({
options: {
left: 200,
field: name,
testData: name,
title: '',
left: 70.5,
top: 58.5,
height: 18,
width: 116,
coordinateSync: false,
widthHeightSync: false,
hideTitle: true,
fontFamily: 'Microsoft YaHei',
fontWeight: '700',
textContentVerticalAlign: 'middle',
contentPaddingLeft: 5.25,
qrCodeLevel: 0,
right: 186.5,
bottom: 73.5,
vCenter: 128.5,
hCenter: 64.5
},
printElementType: {
title: '文本',
type: 'text'
}
})
const el = this.hiprintTemplate.printPanels[0].printElements.at(-1)
const designPaper = this.hiprintTemplate.printPanels[0].designPaper
this.hiprintTemplate.printPanels[0].appendDesignPrintElement(designPaper, el, true)
el.design(void 0, designPaper)
},
onConfirm() {
this.$refs.form.validate((valid) => {
if (valid) {
this.dynamicFromList.push({
fieldName: `field${this.dynamicFromList.length}`,
fieldValue: this.dynamicFrom[`field${this.dynamicFromList.length}`]
})
this.isShowDynamicForm = false
}
})
},
buildLeftElement() {
// eslint-disable-next-line no-undef
hiprint.PrintElementTypeManager.buildByHtml($('.ep-draggable-item'))
// eslint-disable-next-line no-undef
$('#custom-provider').empty()
// eslint-disable-next-line no-undef
hiprint.PrintElementTypeManager.build($('#custom-provider'), 'customProvider')
},
buildDesigner() {
// eslint-disable-next-line no-undef
$('#hiprint-printTemplate').empty()
console.log(template)
this.hiprintTemplate = newHiprintPrintTemplate('temulables', {
template: template,
template: this.template,
settingContainer: '#PrintElementOptionSetting',
onImageChooseClick: (target) => {
let input = document.createElement('input')
@@ -219,7 +328,6 @@
input.click()
input.onchange = function () {
var file = this.files[0]
var reader = new FileReader()
if (file) {
var reader = new FileReader()
reader.readAsDataURL(file)
@@ -232,10 +340,13 @@
}
})
this.$nextTick(() => {
this.hiprintTemplate.design('#hiprint-printTemplate', {
!this.isPrint && this.hiprintTemplate.design('#hiprint-printTemplate', {
grid: true
})
// this.panel = this.hiprintTemplate.printPanels[0]
})
},
@@ -262,39 +373,34 @@
},
print() {
let options = { leftOffset: 0, topOffset: 0 }
let ext = {
callback: () => {
console.log('浏览器打印窗口已打开')
},
this.hiprintTemplate.print(this.printData)
},
styleHandler: () => {
return '<style></style>'
}
}
const list = this.labels
this.hiprintTemplate.print(list)
// js打印不显示设计界面
toPrint (template, printData) {
this.hiprintTemplate.update(template)
this.hiprintTemplate.print(printData)
},
elementToString(el) {
const node = document.createElement('div')
node.appendChild(el)
node.innerHTML = el.html()
return node.innerHTML
document.querySelector('body').appendChild(node)
const html = node.innerHTML
document.querySelector('body').removeChild(node)
return html
},
savePdf() {
const list = this.labels
this.hiprintTemplate.toPdf(printData, '测试导出pdf')
this.hiprintTemplate.toPdf(this.printData, '测试导出pdf',{scale:2 }).then(v => {
console.log(v)
})
},
getHtml() {
const list = this.labels
this.html = this.elementToString(this.hiprintTemplate.getHtml(list)[0])
console.log(this.html)
this.html = this.elementToString(this.hiprintTemplate.getHtml(this.printData))
this.isShowPreview = true
},
@@ -312,6 +418,12 @@
.print {
height: 100%;
.temuBarCode {
display: flex;
flex-direction: column;
padding: 1pt 3pt;
}
.print-wrapper {
display: flex;
height: calc(100vh - 180px);
@@ -380,6 +492,10 @@
overflow-y: auto;
.title {
display: flex;
align-items: center;
justify-content: space-between;
width: 320px;
margin: 14px 0;
}

View File

@@ -1,23 +1,79 @@
import { hiprint } from 'vue-plugin-hiprint'
export const customProvider = function (options) {
var addElementTypes = function (context) {
const addElementTypes = function (context) {
context.removePrintElementTypes('customProvider')
context.addPrintElementTypes('customProvider', [
new hiprint.PrintElementTypeGroup('', [
{
tid: 'providerModule1.date',
title: '业务日期',
data: '2020-01-01',
type: 'text',
tid: 'providerModule1.html',
title: 'temu条码',
data: 'XS888888888',
type: 'html',
formatter: function (data, options, templateData) {
console.log(data, options, templateData)
const elId = options.elId || 'barCode-' + new Date().getTime()
const codeWidth = parseInt((options.width - 22) * 0.85)
options.elId = `${elId}`
// eslint-disable-next-line no-undef
$('body').append(`<div id="codewrapper-${elId}" style="width: ${codeWidth}pt">
<svg id="${elId}" width="100%" display="block" height="100%" class="hibarcode_imgcode" preserveAspectRatio="none slice"></svg>
</div>`)
// eslint-disable-next-line no-undef
JsBarcode('#'+ elId, '96778555251', {
format: "CODE128B",
width: 2,
height: parseInt(hinnn.pt.toPx(options.height - 22).toString()) * 0.6,
margin: 0,
displayValue: false
})
// eslint-disable-next-line no-undef
const codeHtml = $(`#codewrapper-${elId}`).html()
// eslint-disable-next-line no-undef
$(`body>#codewrapper-${elId}`).remove()
// eslint-disable-next-line no-undef
const resizeObserver = new ResizeObserver(() => {
JsBarcode('#'+ elId, '96778555251', {
format: "CODE128B",
width: 2,
height: parseInt(hinnn.pt.toPx(options.height - 22).toString()) * 0.6,
margin: 0,
displayValue: false
})
})
setTimeout(() => {
const node = document.getElementById(`temuBarCode-${elId}`)
if (node) {
resizeObserver.observe(node)
}
}, 0)
var html = `
<div class="temuBarCode" id="temuBarCode-${elId}">
<div class="temuBarCode-top">
<div class="hiprint-printElement-text-content hiprint-printElement-content">(AA+AAA)*20PCS</div>
<div class="hiprint-printElement-text-content hiprint-printElement-content">AA 20PCS+AAA 20PCS</div>
</div>
<div class="temuBarCode-middle">
<div class="hiprint-printElement-text-content hiprint-printElement-content temuBarCode-code" style="width: 100%">
${codeHtml}
</div>
</div>
<div class="temuBarCode-bottom">
<div class="hiprint-printElement-text-content hiprint-printElement-content">1034130097</div>
<div class="hiprint-printElement-text-content hiprint-printElement-content">Made in China</div>
</div>
</div>
`
return html
},
options: {
field: 'date',
testData: '2020-01-01',
height: 16,
fontSize: 6.75,
fontWeight: '700',
textAlign: 'left',
textContentVerticalAlign: 'middle',
hideTitle: true
width: 316,
height: 120,
elId: ''
},
printElementType: {
}
},
{
@@ -53,7 +109,7 @@ export const customProvider = function (options) {
},
{
tid: 'providerModule1.image',
title: 'Logo',
title: '图片',
data: 'https://foruda.gitee.com/avatar/1677050350324030848/5400665_ccsimple_1591166830.png!avatar200',
type: 'image'
}
@@ -61,6 +117,6 @@ export const customProvider = function (options) {
])
}
return {
addElementTypes: addElementTypes
addElementTypes
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -21,6 +21,24 @@ Vue.prototype.$base = "https://seller.kuajingmaihuo.com"
Object.keys(utils).forEach(v => Vue.prototype[`$${v}`] = utils[v])
Vue.prototype.$http = instance
utils.initWindow()
Vue.directive('throttle', {
bind: function (el, obj) {
let timerId = null
let flag = true
el.addEventListener('input', function () {
if (!flag) return
flag = false
timerId && clearTimeout(timerId)
timerId = setTimeout(function () {
flag = true
obj.value()
}, 800)
})
}
})
new Vue({
store,

View File

@@ -1,6 +1,9 @@
import request from '../api'
import store from '../store'
import { Message } from 'element-ui'
import JsBarcode from 'jsbarcode'
import { Interpreter } from 'eval5'
import { transform } from "@babel/standalone"
const dict = {
url: "/api/dictionary/queryValsByCodeList",
@@ -118,11 +121,30 @@ const sleepSync = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds));
}
const initWindow = () => {
const transformCode = (codeStr) => {
return transform(codeStr, { presets: ['env'] }).code
}
window.JsBarcode = JsBarcode
window.eval = (code, context) => {
const interpreter = new Interpreter(context || window, {
timeout: 1000,
})
try {
interpreter.evaluate(transformCode(code))
} catch (err) {
console.log(err)
}
}
}
export default {
dict,
dateUtil,
sleepSync,
userCheck
userCheck,
initWindow
}

View File

@@ -297,8 +297,6 @@ export default {
},
created() {
window.eval = () => {
}
const devVersion = require('../manifest.development.json').version
const prodVersion = require('../manifest.production.json').version
this.version = process.env.NODE_ENV === 'production' ? prodVersion : devVersion
@@ -399,7 +397,7 @@ export default {
}
await detalAction(res);
console.log("--fileList--", fileList)
},
},
gotoKefu() {
window.open('https://work.weixin.qq.com/kfid/kfcaa4208f661131eba', '_blank')
},

View File

@@ -1,13 +1,15 @@
<template>
<AiDetail class="add-label">
<template #title>
<ai-title title="添加标签" isShowBack :isShowBottomBorder="true" @onBackClick="cancel">
<ai-title title="添加模板" isShowBack :isShowBottomBorder="true" @onBackClick="cancel">
<template #rightBtn>
<label>模板名称</label>
<el-input placeholder="请输入模板名称" size="small" v-model="name" style="width: 200px; margin-right: 300px;"></el-input>
<el-button @click="preview" size="small" type="danger">预览</el-button>
<el-button @click="savePdf" size="small" type="primary">下载pdf</el-button>
<el-button @click="saveTemplate" size="small" type="primary">保存</el-button>
<el-button @click="print" size="small">打印</el-button>
<el-button @click="clearPaper" size="small" type="danger">清空纸张</el-button>
<el-button @click="saveTemplate" size="small" type="primary">保存</el-button>
</template>
</ai-title>
</template>
@@ -15,7 +17,7 @@
<ai-card title="标签模板" class="card" :hideTitle="true">
<template #content>
<div class="add-label__wrapper">
<Print ref="printRef" :labels="labels"></Print>
<Print ref="printRef" :template="template" :isPrint="false"></Print>
</div>
</template>
</ai-card>
@@ -25,6 +27,7 @@
<script>
import Print from '@/components/print/Print'
import template from '@/components/print/template'
export default {
components: {
@@ -33,7 +36,8 @@
data () {
return {
labels: []
name: '',
template: template
}
},
@@ -55,6 +59,10 @@
},
saveTemplate () {
if (!this.name) {
return this.$message.error('模板名称不能为空')
}
const json = this.$refs.printRef.exportJson()
console.log(json)
},

View File

@@ -2,45 +2,98 @@
<ai-list class="Learning">
<ai-title
slot="title"
title="新手园地"
title="标签打印"
isShowBottomBorder>
</ai-title>
<template slot="content">
<ai-search-bar>
<template #left>
<el-radio-group v-model="search.categoryId" @change="onChange">
<el-radio-button label="">全部</el-radio-button>
<el-radio-button label="isFavorite">我的收藏</el-radio-button>
<el-radio-button :label="item.id" :key="item.id" v-for="item in cateList">{{ item.name }}</el-radio-button>
</el-radio-group>
</template>
<template #right>
</template>
</ai-search-bar>
<div class="search-item__wrapper">
<div class="left">
<div class="search-item">
<label>添加方式</label>
<el-radio-group v-model="type" size="small" @change="onSearchRest">
<el-radio-button label="1">按备货单打印</el-radio-button>
<el-radio-button label="2">按SKC打印</el-radio-button>
<el-radio-button label="3">按SKU打印</el-radio-button>
</el-radio-group>
</div>
<div class="search-item">
<label>店铺</label>
<el-select v-model="search.mallId" placeholder="请选择店铺" size="small">
<el-option
v-for="item in $store.state.mallList"
:key="item.mallId"
:label="item.mallName"
:value="item.mallId">
</el-option>
</el-select>
</div>
</div>
<div class="right"></div>
</div>
<div class="search-item__wrapper">
<div class="left">
<div class="search-item" v-show="addType === '1'">
<label>备货单</label>
<el-button style="margin-left: 10px;" @click="onCateChange" size="small" :disabled="!search.mallId" :loading="isLoading">查询</el-button>
</div>
<div class="search-item" v-show="addType === '2'">
<label>SKC</label>
<el-input
v-model="search.SKC"
style="width: 250px"
size="small"
placeholder="多个查询请用户逗号分割"
clearable
suffix-icon="iconfont iconSearch">
</el-input>
<el-button style="margin-left: 10px;" @click="getSkuList" size="small" :disabled="!search.mallId" :loading="isLoading">查询</el-button>
</div>
<div class="search-item" v-show="addType === '3'">
<label>SKU</label>
<el-input
v-if="addType === '3'"
v-model="search.SKU"
style="width: 250px"
size="small"
clearable
placeholder="多个查询请用户逗号分割"
suffix-icon="iconfont iconSearch">
</el-input>
<el-button style="margin-left: 10px;" @click="getSkuList" size="small" :disabled="!search.mallId" :loading="isLoading">查询</el-button>
</div>
</div>
</div>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
:current.sync="search.current"
:size.sync="search.size"
style="margin-top: 8px;"
:isShowPagination="false"
@getList="getList">
<el-table-column slot="options" label="操作" align="center" fixed="right" width="140px">
<template v-slot="{ row }">
<div class="table-options">
<el-button type="text" @click="collection(row.id, row.isFavorite)">{{ row.isFavorite === '0' ? '收藏' : '取消收藏' }}</el-button>
<el-button type="text">打印</el-button>
<el-button type="text" @click="toDetail(row.url)">详情</el-button>
</div>
</template>
</el-table-column>
</ai-table>
<Print ref="printRef" :isPrint="true"></Print>
</template>
</ai-list>
</template>
<script>
import Print from '@/components/print/Print'
export default {
name: 'Learning',
name: 'PrintPage',
components: {
Print
},
data () {
return {
@@ -49,83 +102,27 @@
{ prop: 'createTime', label: '发布时间', align: 'center' },
],
tableData: [],
total: 0,
search: {
current: 1,
size: 10,
categoryId: ''
mallId: '',
SKC: '',
SKU: ''
},
cateList: [],
isFavorite: 0
type: '1',
isLoading: false
}
},
created () {
this.$store.dispatch('getUserInfo').then(e => {
console.log(e)
})
this.getCateList()
this.getList()
},
methods: {
toDetail (url) {
window.open(url)
},
onChange (e) {
if (e === 'isFavorite') {
this.$http.post('/api/learning/favoritePage', null, {
params: {
...this.search
}
}).then(res => {
if (res.code === 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
} else {
this.search.current = 1
this.getList()
}
},
collection (id, isFavorite) {
this.$confirm(isFavorite === '0' ? '确定收藏该文章?' : '确定取消收藏?', '温馨提示', {
confirmButtonText: '确定',
callback: action => {
if (action === 'confirm') {
this.$http.post(isFavorite === '0' ? `/api/learning/addFavorite?id=${id}` : `/api/learning/delFavorite?id=${id}`).then(res => {
if (res.code === 0) {
this.$message.success(isFavorite === '0' ? '收藏成功' : '取消成功')
this.getList()
}
})
}
}
})
},
getCateList () {
this.$http.post('/api/learningCategory/page?size=50').then(res => {
if (res.code === 0) {
this.cateList = res.data.records
}
})
toPrint (template, printData) {
this.$refs.printData.print(template, printData)
},
getList () {
this.$http.post('/api/learning/pluginPage', null, {
params: {
...this.search
}
}).then(res => {
if (res.code === 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
}
}
}

View File

@@ -10,19 +10,22 @@
<template slot="content">
<ai-search-bar>
<template #left>
<el-button type="primary" size="small" @click="isShow = true">添加</el-button>
<el-button type="primary" size="small" @click="chooseSkuList = [], isShow = true">添加</el-button>
<el-button type="warning" size="small" @click="toAdd(row.url)">导入</el-button>
<el-button type="danger" size="small" @click="toAdd(row.url)">导出</el-button>
</template>
<template #right>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:tableData="skuList"
:col-configs="colConfigs"
:total="total"
:current.sync="search.current"
:size.sync="search.size"
style="margin-top: 8px;"
@getList="getList">
@getList="getList"
@selection-change="handleSelectionChange">
<el-table-column slot="productName" width="300px" :show-overflow-tooltip='true' label="商品名称" fixed="left">
<template slot-scope="scope">
<div>
@@ -31,7 +34,7 @@
</div>
</template>
</el-table-column>
<el-table-column slot="options" label="操作" align="center" fixed="right" width="140px">
<el-table-column slot="options" label="操作" align="center" fixed="right" width="240px">
<template v-slot="{ row }">
<div class="table-options">
<el-button type="text" @click="toAdd(row.url)">编辑</el-button>
@@ -45,31 +48,90 @@
title="添加SKU"
width="1400px"
@confirm="onConfirm">
<ai-search-bar>
<template #left>
<el-select v-model="skuSearch.mallId" placeholder="请选择店铺" size="small" @change="onMallChange">
<el-option
v-for="item in $store.state.mallList"
:key="item.mallId"
:label="item.mallName"
:value="item.mallId">
</el-option>
</el-select>
</template>
<template #right>
</template>
</ai-search-bar>
<div class="search-item__wrapper">
<div class="left">
<div class="search-item">
<label>添加方式</label>
<el-radio-group v-model="addType" size="small" @change="onSearchRest">
<el-radio-button label="1">按类目添加</el-radio-button>
<el-radio-button label="2">按SKC添加</el-radio-button>
<el-radio-button label="3">按SKU添加</el-radio-button>
</el-radio-group>
</div>
<div class="search-item">
<label>店铺</label>
<el-select v-model="lableSearch.mallId" placeholder="请选择店铺" size="small">
<el-option
v-for="item in $store.state.mallList"
:key="item.mallId"
:label="item.mallName"
:value="item.mallId">
</el-option>
</el-select>
</div>
</div>
<div class="right"></div>
</div>
<div class="search-item__wrapper">
<div class="left">
<div class="search-item" v-show="addType === '1'">
<label>商品分类</label>
<el-cascader
style="width: 280px;"
v-model="targetCatId"
:props="props"
size="small"
filterable
:show-all-levels="false"
collapse-tags
clearable>
</el-cascader>
<el-button style="margin-left: 10px;" @click="onCateChange" size="small" :disabled="!lableSearch.mallId" :loading="isLoading">查询</el-button>
</div>
<div class="search-item" v-show="addType === '2'">
<label>SKC</label>
<el-input
v-model="skuReqParams.SKC"
style="width: 250px"
size="small"
v-throttle="() => {getSkuList()}"
placeholder="多个查询请用户逗号分割"
clearable
@clear="getSkuList()"
suffix-icon="iconfont iconSearch">
</el-input>
<el-button style="margin-left: 10px;" @click="getSkuList" size="small" :disabled="!lableSearch.mallId" :loading="isLoading">查询</el-button>
</div>
<div class="search-item" v-show="addType === '3'">
<label>SKU</label>
<el-input
v-if="addType === '3'"
v-model="skuReqParams.SKU"
style="width: 250px"
size="small"
v-throttle="() => {getSkuList()}"
placeholder="多个查询请用户逗号分割"
clearable
@clear="getSkuList()"
suffix-icon="iconfont iconSearch">
</el-input>
<el-button style="margin-left: 10px;" @click="getSkuList" size="small" :disabled="!lableSearch.mallId" :loading="isLoading">查询</el-button>
</div>
</div>
</div>
<ai-table
height="400"
:tableData="skuList"
height="370"
:tableData="lableList"
:col-configs="colConfigs"
:total="skuTotal"
:current.sync="skuSearch.current"
:size.sync="skuSearch.size"
:total="lableTotal"
:current.sync="lableSearch.current"
:size.sync="lableSearch.size"
style="margin-top: 8px;"
@getList="getSkuList"
:pageSizes="[10, 20, 50, 100, 500, 1000]"
v-loading="isLoading">
v-loading="isLoading"
:isShowPagination="false"
@getList="() => {}"
@selection-change="handleSelectionChange">
<el-table-column slot="productName" width="300px" :show-overflow-tooltip="true" label="商品名称" fixed="left">
<template slot-scope="scope">
<div>
@@ -87,11 +149,12 @@
<script>
import { sendChromeAPIMessage } from '@/api/chromeApi'
export default {
name: 'Template',
name: 'SkuManage',
data () {
return {
colConfigs: [
{ type: 'selection' },
// { slot: 'productName', label: '商品名称', width: '300px', align: 'left', fixed: 'left' },
// { prop: 'category', label: '分类', width: '140px', align: 'left', fixed: 'left' },
{ prop: 'mallName', label: '店铺名称', align: 'left' },
@@ -102,25 +165,55 @@
{ prop: 'skuExtCode', label: 'SKU货号', align: 'center' },
{ prop: 'skuSpecName', label: '次销售属性', align: 'center' }
],
tableData: [],
total: 0,
search: {
current: 1,
size: 100
},
skuSearch: {
lableSearch: {
current: 1,
size: 100,
mallId: ''
},
skuTotal: 0,
skuList: [],
lableTotal: 0,
lableList: [],
isShow: false,
skuReqParams: {
page: 1,
pageSize: 100
pageSize: 100,
SKC: '',
SKU: ''
},
isLoading: false
isLoading: false,
addType: '1',
props: {
value: 'catId',
label: 'catName',
multiple: true,
checkStrictly: true,
lazy: true,
lazyLoad (value, resolve) {
sendChromeAPIMessage({
url: 'bg-anniston-mms/category/children/list',
needMallId: true,
data: {
parentCatId: value.level === 0 ? '' : value.value
}
}).then(res => {
if (res.errorCode === 1000000) {
resolve(res.result.categoryNodeVOS.map(v => {
return {
...v,
leaf: v.isLeaf
}
}))
}
})
}
},
targetCatId: [],
skuList: [],
chooseSkuList: []
}
},
@@ -130,7 +223,7 @@
return {}
}
return this.$store.state.mallList.filter(v => v.mallId === this.skuSearch.mallId)[0]
return this.$store.state.mallList.filter(v => v.mallId === this.lableSearch.mallId)[0]
}
},
@@ -143,20 +236,92 @@
this.$router.push('/addLabelsTemplate')
},
requestSKUList () {
sendChromeAPIMessage({
onSearchRest() {
this.skuReqParams.SKC = ''
this.skuReqParams.SKU = ''
},
handleSelectionChange(e) {
console.log(e)
this.chooseSkuList = e
},
getSKCList(catIds, page) {
return new Promise(resolve => {
sendChromeAPIMessage({
url: 'bg-visage-mms/product/skc/pageQuery',
needMallId: true,
mallId: this.lableSearch.mallId,
anti: true,
data: {
page: 1,
pageSize: 200,
catIds: catIds
}
}).then(res => {
if (res.errorCode == 1000000) {
resolve({
list: res.result.pageItems.map(v => v.productSkcId),
isHasNext: page * 200 < res.result.total
})
} else {
resolve({ list: [], isHasNext: false })
}
}).catch(() => {
resolve({ list: [], isHasNext: false })
})
})
},
async onCateChange() {
this.$userCheck(this.lableSearch.mallId).then(async () => {
let page = 1
let list = []
let isHasNext = true
this.lableList = []
this.isLoading = true
while (isHasNext) {
const result = await this.getSKCList([].concat(this.targetCatId.flat()), page)
page = page + 1
isHasNext = result.isHasNext ? true : false
list.push(...result.list)
await this.$sleepSync(5000)
}
const skcList = [...new Set(list)]
const len = Math.ceil(skcList.length / 100)
for (let i = 0; i < len; i++) {
this.skuReqParams.page = 1
this.skuReqParams.SKC = [...new Set(list)].slice(i * 100, i * 100 + 100).join(',')
await this.requestSKUList(true)
await this.$sleepSync(2000)
}
console.log(111)
this.isLoading = false
}).catch(() => {
this.lableSearch.mallId = ''
})
},
requestSKUList(flag) {
return sendChromeAPIMessage({
url: 'bg-visage-mms/labelcode/pageQuery',
needMallId: true,
mallId: this.skuSearch.mallId,
mallId: this.lableSearch.mallId,
anti: true,
data: {
page: this.skuSearch.size > 100 ? this.skuReqParams.page : this.skuSearch.current,
pageSize: this.skuSearch.size > 100 ? 100 : this.skuSearch.size
page: this.skuReqParams.page,
pageSize: 200,
productSkcIdList: (['2', '1'].includes(this.addType)) ? this.skuReqParams.SKC.split(',') : [],
productSkuIdList: this.addType === '3' ? this.skuReqParams.SKU.split(',') : []
}
}).then(async (res) => {
if (res.errorCode == 1000000) {
const list = res.result.pageItems.map(v => {
return {
mallId: this.lableSearch.mallId,
mallName: this.currMall.mallName,
productName: v.productName,
productSkuId: v.labelCodeVO.productSkuId,
@@ -167,50 +332,32 @@
}).join(',')
}
})
this.skuTotal = res.result.total
this.skuList.push(...list)
this.lableTotal = res.result.total
this.lableList.push(...list)
if (this.skuSearch.size > 100 && (res.result.total > this.skuList.length)) {
if (res.result.total > this.lableList.length) {
this.skuReqParams.page++
await this.$sleepSync(5000)
this.requestSKUList()
await this.requestSKUList()
} else {
this.isLoading = false
!flag && (this.isLoading = false)
}
}
})
},
onMallChange (e) {
if (!e) {
this.skuList = []
return false
}
this.$userCheck(this.skuSearch.mallId).then(() => {
this.skuList = []
this.skuReqParams.page = 1
this.isLoading = true
this.requestSKUList()
}).catch(() => {
this.skuSearch.mallId = ''
})
},
getSkuList () {
if (!this.skuSearch.mallId) {
if (!this.lableSearch.mallId) {
return this.$message.error('请选择店铺')
}
this.$userCheck(this.skuSearch.mallId).then(() => {
this.skuList = []
this.$userCheck(this.lableSearch.mallId).then(() => {
this.lableList = []
this.skuReqParams.page = 1
this.isLoading = true
this.requestSKUList()
}).catch(() => {
this.skuSearch.mallId = ''
this.lableSearch.mallId = ''
})
},
@@ -228,11 +375,24 @@
},
onConfirm () {
this.skuList = this.chooseSkuList
this.isShow = false
}
}
}
</script>
<style scoped lang="scss">
.Template {
.search-item__wrapper {
display: flex;
align-items: center;
justify-content: space-between;
&>div {
display: flex;
align-items: center;
}
}
}
</style>

View File

@@ -1051,6 +1051,11 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/standalone@^7.25.8":
version "7.25.8"
resolved "https://registry.npmmirror.com/@babel/standalone/-/standalone-7.25.8.tgz#054a0c7c28275527f05cba4c17fe45cab8e9c638"
integrity sha512-UvRanvLCGPRscJ5Rw9o6vUBS5P+E+gkhl6eaokrIN+WM1kUkmj254VZhyihFdDZVDlI3cPcZoakbJJw24QPISw==
"@babel/template@^7.25.0", "@babel/template@^7.25.7":
version "7.25.7"
resolved "https://registry.npmmirror.com/@babel/template/-/template-7.25.7.tgz#27f69ce382855d915b14ab0fe5fb4cbf88fa0769"
@@ -1387,6 +1392,13 @@
resolved "https://registry.npmmirror.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
"@types/acorn@^4.0.5":
version "4.0.6"
resolved "https://registry.npmmirror.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22"
integrity sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==
dependencies:
"@types/estree" "*"
"@types/body-parser@*":
version "1.19.5"
resolved "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4"
@@ -1435,6 +1447,11 @@
resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
"@types/estree@0.0.41":
version "0.0.41"
resolved "https://registry.npmmirror.com/@types/estree/-/estree-0.0.41.tgz#fd90754150b57432b72bf560530500597ff04421"
integrity sha512-rIAmXyJlqw4KEBO7+u9gxZZSQHaCNnIzYrnNmYVpgfJhxTqO0brCX0SYpqUTkVI5mwwUwzmtspLBGBKroMeynA==
"@types/express-serve-static-core@*", "@types/express-serve-static-core@^5.0.0":
version "5.0.0"
resolved "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.0.tgz#91f06cda1049e8f17eeab364798ed79c97488a1c"
@@ -2103,7 +2120,7 @@ acorn@8.0.4:
resolved "https://registry.npmmirror.com/acorn/-/acorn-8.0.4.tgz#7a3ae4191466a6984eee0fe3407a4f3aa9db8354"
integrity sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==
acorn@^7.4.0:
acorn@^7.1.0, acorn@^7.4.0:
version "7.4.1"
resolved "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
@@ -3989,6 +4006,16 @@ etag@~1.8.1:
resolved "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
eval5@^1.4.8:
version "1.4.8"
resolved "https://registry.npmmirror.com/eval5/-/eval5-1.4.8.tgz#efa3f1da7dfa7e152b58b9571e5aa415b01a556b"
integrity sha512-sdc04TAeklUHrITxBWksrDsDBWqAvYs9VCS2cpSHrSqzTdva4JkILV+x7kVlyoUqp/g7kMyGS+4RMYgfkGciAw==
dependencies:
"@babel/runtime" "^7.8.4"
"@types/acorn" "^4.0.5"
"@types/estree" "0.0.41"
acorn "^7.1.0"
event-pubsub@4.3.0:
version "4.3.0"
resolved "https://registry.npmmirror.com/event-pubsub/-/event-pubsub-4.3.0.tgz#f68d816bc29f1ec02c539dc58c8dd40ce72cb36e"
@@ -5134,7 +5161,7 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
jsbarcode@^3.11.5:
jsbarcode@^3.11.5, jsbarcode@^3.11.6:
version "3.11.6"
resolved "https://registry.npmmirror.com/jsbarcode/-/jsbarcode-3.11.6.tgz#96e8fbc3395476e162982a6064b98a09b5ea02c0"
integrity sha512-G5TKGyKY1zJo0ZQKFM1IIMfy0nF2rs92BLlCz+cU4/TazIc4ZH+X1GYeDRt7TKjrYqmPfTjwTBkU/QnQlsYiuA==