Browse Source

采购标签

master
常熟吴彦祖 5 months ago
parent
commit
9b1738ccfa
  1. 55
      src/assets/scss/global.scss
  2. 224
      src/utils/directives.js
  3. 2
      src/views/main.vue
  4. 30
      src/views/modules/clodopLabel/kuCunLabel.js
  5. 4
      src/views/modules/print/PoPartPrint.vue
  6. 37
      src/views/modules/print/rePrintPoPart.vue

55
src/assets/scss/global.scss

@ -465,7 +465,7 @@ a:hover{
/* src/styles/element-custom.css */
.el-input.is-disabled .el-input__inner {
color: #212121 !important;
color: #8691A8 !important;
}
@ -498,3 +498,56 @@ a:hover{
animation: gradient-text-flow 3s ease-in-out infinite;
}
/* 点击烟花特效:粒子基础样式 */
.firework-particle {
position: fixed;
width: 6px;
height: 6px;
border-radius: 50%;
pointer-events: none;
transform: translate(-50%, -50%);
animation: firework-move 700ms ease-out forwards, firework-fade 700ms ease-out forwards;
z-index: 99999;
box-shadow: 0 0 8px rgba(255, 215, 0, 0.9), 0 0 16px rgba(255, 215, 0, 0.6);
}
@keyframes firework-move {
0% {
transform: translate(-50%, -50%) translate(0, 0) scale(1);
}
100% {
transform: translate(-50%, -50%) translate(var(--dx), var(--dy)) scale(0.8);
}
}
@keyframes firework-fade {
0% { opacity: 1; }
100% { opacity: 0; }
}
///* 路由切换全屏渐变覆盖效果 App.vue transition name="fade" 对应 */
//.fade-enter-active, .fade-leave-active {
// transition: opacity 300ms ease;
//}
//.fade-enter, .fade-leave-to {
// opacity: 0;
//}
///* 渐变滑动遮罩进入与离开时均出现一次时间短透明 */
//.fade-enter-active::after, .fade-leave-active::after {
// content: "";
// position: fixed;
// left: 0; top: 0; width: 100vw; height: 100vh;
// pointer-events: none;
// z-index: 99990; /* 低于烟花(99999),不干扰点击 */
// background: linear-gradient(120deg, #d94cf3, #ff0000, #fff200, #1360ff);
// background-size: 300% 100%;
// opacity: 0.22;
// animation: route-gradient-swipe 400ms ease forwards;
//}
//
//@keyframes route-gradient-swipe {
// 0% { transform: translateX(-100%); opacity: 0.22; }
// 50% { transform: translateX(0%); opacity: 0.22; }
// 100% { transform: translateX(100%); opacity: 0; }
//}
//

224
src/utils/directives.js

@ -78,3 +78,227 @@ Vue.directive('drag', {
}
}
})
//---------------以下都可删---------------------
// v-fireworks: 容器内按钮点击烟花特效(全局可复用)
Vue.directive('fireworks', {
bind(el, binding) {
const colors = ['#FFD700', '#DAA520', '#B8860B', '#C9A227', '#E6B800'];
const getSkyConfig = () => {
let type = 'rain';
let enabled = true;
const val = binding && binding.value;
if (typeof val === 'string') {
if (val === 'rain' || val === 'meteor') type = val;
if (val === 'none') enabled = false;
} else if (typeof val === 'object' && val) {
if (val.sky === 'rain' || val.sky === 'meteor') type = val.sky;
if (val.sky === 'none') enabled = false;
if (typeof val.skyEnabled === 'boolean') enabled = val.skyEnabled;
if (typeof val.enabled === 'boolean') enabled = val.enabled;
} else if (val === false) {
enabled = false;
}
const ds = el.getAttribute && el.getAttribute('data-sky');
if (ds === 'rain' || ds === 'meteor') type = ds;
if (ds === 'none') enabled = false;
const dse = el.getAttribute && el.getAttribute('data-sky-enabled');
if (dse === 'false' || dse === '0') enabled = false;
if (dse === 'true' || dse === '1') enabled = true;
return { type, enabled };
}
// ===== 全屏天空特效(雨/流星) =====
let skyCanvas = null;
let skyCtx = null;
let skyRaf = null;
let skyTimer = null;
let skyDelayTimer = null;
let skyParticles = [];
const ensureSkyCanvas = () => {
if (skyCanvas) return;
skyCanvas = document.createElement('canvas');
skyCanvas.className = 'sky-effect-canvas';
skyCanvas.style.position = 'fixed';
skyCanvas.style.left = '0';
skyCanvas.style.top = '0';
skyCanvas.style.width = '100vw';
skyCanvas.style.height = '100vh';
skyCanvas.style.pointerEvents = 'none';
skyCanvas.style.zIndex = '99998';
document.body.appendChild(skyCanvas);
skyCtx = skyCanvas.getContext('2d');
const resize = () => {
skyCanvas.width = window.innerWidth;
skyCanvas.height = window.innerHeight;
};
resize();
window.addEventListener('resize', resize);
skyCanvas.__resize__ = resize;
};
const clearSky = () => {
if (skyRaf) cancelAnimationFrame(skyRaf);
skyRaf = null;
if (skyTimer) clearTimeout(skyTimer);
skyTimer = null;
if (skyDelayTimer) clearTimeout(skyDelayTimer);
skyDelayTimer = null;
if (skyCanvas) {
window.removeEventListener('resize', skyCanvas.__resize__);
if (skyCanvas.parentNode) skyCanvas.parentNode.removeChild(skyCanvas);
}
skyCanvas = null;
skyCtx = null;
skyParticles = [];
};
const startRain = (duration = 3000) => {
ensureSkyCanvas();
const count = Math.min(140, Math.floor((window.innerWidth * window.innerHeight) / 12000));
skyParticles = new Array(count).fill(0).map(() => ({
x: Math.random() * skyCanvas.width,
y: Math.random() * skyCanvas.height,
len: 10 + Math.random() * 14,
speed: 3 + Math.random() * 6,
wind: 1 + Math.random() * 2
}));
const stroke = 'rgba(255, 215, 0, 0.8)';
const draw = () => {
if (!skyCtx) return;
skyCtx.clearRect(0, 0, skyCanvas.width, skyCanvas.height);
skyCtx.strokeStyle = stroke;
skyCtx.lineWidth = 1.2;
skyCtx.lineCap = 'round';
for (const p of skyParticles) {
skyCtx.beginPath();
skyCtx.moveTo(p.x, p.y);
skyCtx.lineTo(p.x + p.wind, p.y + p.len);
skyCtx.stroke();
p.x += p.wind;
p.y += p.speed;
if (p.y > skyCanvas.height || p.x > skyCanvas.width) {
p.x = Math.random() * skyCanvas.width;
p.y = -20;
}
}
skyRaf = requestAnimationFrame(draw);
};
draw();
skyTimer = setTimeout(clearSky, duration);
};
const startMeteor = (duration = 3000) => {
ensureSkyCanvas();
const count = 8;
skyParticles = new Array(count).fill(0).map(() => newMeteor());
function newMeteor() {
const startX = Math.random() * skyCanvas.width;
const startY = Math.random() * (skyCanvas.height * 0.3);
const speed = 6 + Math.random() * 6;
const angle = Math.PI / 3; // 60° 斜向
const vx = Math.cos(angle) * speed;
const vy = Math.sin(angle) * speed;
const len = 120 + Math.random() * 120;
const life = 40 + Math.random() * 40;
return { x: startX, y: startY, vx, vy, len, life, maxLife: life };
}
const draw = () => {
if (!skyCtx) return;
skyCtx.clearRect(0, 0, skyCanvas.width, skyCanvas.height);
for (let i = 0; i < skyParticles.length; i++) {
const m = skyParticles[i];
const grad = skyCtx.createLinearGradient(m.x, m.y, m.x - m.vx * 10, m.y - m.vy * 10);
grad.addColorStop(0, 'rgba(255,215,0,0.9)');
grad.addColorStop(1, 'rgba(255,215,0,0.0)');
skyCtx.strokeStyle = grad;
skyCtx.lineWidth = 2;
skyCtx.beginPath();
skyCtx.moveTo(m.x, m.y);
skyCtx.lineTo(m.x - (m.vx * (m.len / 10)), m.y - (m.vy * (m.len / 10)));
skyCtx.stroke();
m.x += m.vx;
m.y += m.vy;
m.life -= 1;
if (m.life <= 0 || m.x > skyCanvas.width + 100 || m.y > skyCanvas.height + 100) {
skyParticles[i] = newMeteor();
}
}
skyRaf = requestAnimationFrame(draw);
};
draw();
skyTimer = setTimeout(clearSky, duration);
};
const startSkyEffect = () => {
const cfg = getSkyConfig();
if (!cfg.enabled) return;
// 若已有画布或定时器,刷新计时即可,避免叠加
if (skyTimer) {
clearTimeout(skyTimer);
skyTimer = null;
}
if (skyDelayTimer) {
clearTimeout(skyDelayTimer);
skyDelayTimer = null;
}
if (cfg.type === 'meteor') {
startMeteor(3500);
} else {
// 雨滴延迟1秒出现,持续时间为1秒
skyDelayTimer = setTimeout(() => {
startRain(1000);
}, 1000);
}
};
const isButtonLike = (node) => {
if (!node) return false;
if (node.closest) {
const match = node.closest('button, .el-button, [role="button"], input[type="button"], input[type="submit"], a.el-button, a');
return !!match;
}
return false;
}
const spawnFireworks = (x, y) => {
const count = 14;
for (let i = 0; i < count; i++) {
const particle = document.createElement('span');
particle.className = 'firework-particle';
const angle = (Math.PI * 2 * i) / count + Math.random() * 0.3;
const distance = 60 + Math.random() * 60;
const dx = Math.cos(angle) * distance;
const dy = Math.sin(angle) * distance;
particle.style.left = x + 'px';
particle.style.top = y + 'px';
particle.style.background = colors[i % colors.length];
particle.style.setProperty('--dx', dx + 'px');
particle.style.setProperty('--dy', dy + 'px');
document.body.appendChild(particle);
setTimeout(() => {
if (particle && particle.parentNode) {
particle.parentNode.removeChild(particle);
}
}, 700);
}
};
const handler = (e) => {
if (!isButtonLike(e.target)) return;
const x = e.clientX;
const y = e.clientY;
spawnFireworks(x, y);
startSkyEffect();
};
el.__fireworksHandler__ = handler;
el.addEventListener('click', handler, false);
},
unbind(el) {
if (el.__fireworksHandler__) {
el.removeEventListener('click', el.__fireworksHandler__, false);
delete el.__fireworksHandler__;
}
}
})

2
src/views/main.vue

@ -1,5 +1,5 @@
<template>
<div
<div v-fireworks="false"
class="site-wrapper"
:class="{ 'site-sidebar--fold': sidebarFold }"
v-loading.fullscreen.lock="loading"

30
src/views/modules/clodopLabel/kuCunLabel.js

@ -0,0 +1,30 @@
import getLodop from '@/utils/LodopFuncs.js'
// 打印
export function kuCunLabelPrint(dataList,type) {
const LODOP = getLodop()
if (LODOP) {
for (const row of dataList) {
if(type==='A'){
LODOP.NewPage()
LODOP.SET_PRINT_PAGESIZE(0,600,300,"");
LODOP.SET_PRINT_MODE("PRINT_NOCOLLATE",1);
LODOP.ADD_PRINT_BARCODE(8,5,80,85,"QRCode",row.rollNo);
LODOP.SET_PRINT_STYLEA(0,"FontSize",8);
LODOP.ADD_PRINT_TEXT(11,72,153,22,"Roll No:"+row.rollNo);
LODOP.SET_PRINT_STYLEA(0,"FontName","@微软雅黑");
LODOP.ADD_PRINT_TEXT(32,72,157,20,"Part No:"+row.partNo);
LODOP.ADD_PRINT_TEXT(53,72,155,20,"Product Date:"+row.manufactureDate);
}
}
LODOP.PRINT_DESIGN();
// LODOP.PREVIEW();
// LODOP.PRINT();
}
}

4
src/views/modules/print/PoPartPrint.vue

@ -1,5 +1,5 @@
<template>
<div class="mod-config" >
<div class="mod-config">
<el-form :inline="true" label-position="top" label-width="100px" style="margin-top: 0px;" >
<el-row>
<el-col :span="24" style="">
@ -211,7 +211,7 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="本次发行数量" class="gradient-label">
<el-form-item label="本次发行数量" >
<el-input v-model="addModelData.nowRollQty" disabled style="width: 100%"></el-input>
</el-form-item>
</el-col>

37
src/views/modules/print/rePrintPoPart.vue

@ -43,7 +43,7 @@
<el-row >
<el-form-item style="margin-top: 5px">
<el-button @click="getMainData()" type="primary">查询</el-button>
<el-button @click="getDataList()" type="primary">打印</el-button>
<el-button @click="printLabelModel()" type="primary">打印</el-button>
</el-form-item>
</el-row>
</el-form>
@ -90,6 +90,25 @@
</el-table>
<el-dialog title="补打标签" :close-on-click-modal="false" v-drag :visible.sync="addModelFlag" width="300px">
<el-form :model="addModelData" label-position="top" style="margin-top: -5px;">
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="标签样式" >
<el-select v-model="addModelData.type" >
<el-option label="A" value="A"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer" style="text-align: center;">
<el-button type="success" @click="printLabel()">补打</el-button>
<el-button type="primary" @click="addModelFlag=false">取消</el-button>
</div>
</el-dialog>
</div>
@ -100,6 +119,7 @@
import {getCRollInfoList} from '@/api/crollinfo/crollinfo.js'
import {rollPrint} from '@/api/finishedProductWarehouse/rollPrint.js'
import {getInboundQcResultData, getKuCunLabelData} from '../../../api/wms/wms'
import {kuCunLabelPrint} from '../clodopLabel/kuCunLabel'
export default {
data() {
@ -374,8 +394,11 @@ export default {
fixed: false
},
],
addModelData:{
type:'A',
},
dataList: [],
addModelFlag: false,
dataListLoading: false,
selectionDataList:[],
}
@ -423,6 +446,16 @@ export default {
this.dataListLoading = false
})
},
printLabelModel(){
if(this.selectionDataList.length===0){
this.$message.error('未选择标签!');
return false;
}
this.addModelFlag=true;
},
printLabel(){
kuCunLabelPrint(this.selectionDataList,"A")
},
},
created() {

Loading…
Cancel
Save