Commit 67b322c3 by linjinhong

feat:添加静态图片

parent 1a6d16c7
{
"test": {
"apiApiHost": "http://172.16.19.100:8060/api",
"fileApiUrl": "http://172.16.19.100:8060/upload/factory",
"apiApiHost": "http://172.16.19.230:8060/api",
"fileApiUrl": "http://172.16.19.230:8060/upload/factory",
"visionUrl": "http://console.jomalls.com",
"configPath": "D:\\work\\electron-printer\\config\\env.json"
},
......
......@@ -37,14 +37,14 @@ const downloadQueue = createBatchDownloadQueue({
basePath: "",
// 单文件下载成功
onSuccess: task => {
win?.webContents.send("download:file-success", {
win.webContents.send("download:file-success", {
batchArrangeNum: task.batchArrangeNum,
fileName: task.fileName
});
},
// 单文件下载失败
onError: (task, err) => {
win?.webContents.send("download:file-error", {
win.webContents.send("download:file-error", {
batchArrangeNum: task.batchArrangeNum,
fileName: task.fileName,
msg: err.message
......@@ -52,11 +52,11 @@ const downloadQueue = createBatchDownloadQueue({
},
// 批次校验失败(新增:返回所有异常批次)
onBatchInvalid: invalidList => {
win?.webContents.send("download:batch-invalid", invalidList);
win.webContents.send("download:batch-invalid", invalidList);
},
// 全部任务完成
onIdle: () => {
win?.webContents.send("download:all-finish");
win.webContents.send("download:all-finish");
}
});
......@@ -520,7 +520,17 @@ async function createWindow() {
});
ipcMain.on("download:get-status", event => {
event.returnValue = { isRunning: downloadQueue.isRunning };
try {
// 无论正常异常都保证回复,避免前端挂起
event.reply("download:status-reply", {
isRunning: downloadQueue.isRunning
});
} catch (err) {
event.reply("download:status-reply", {
isRunning: false,
error: err.message
});
}
});
}
......
......@@ -213,8 +213,8 @@ export default {
}
},
mounted() {
// console.log("tableConfig", this.tableConfig);
// console.log("tableData", this.tableData);
console.log("tableConfig", this.tableConfig);
console.log("tableData", this.tableData);
}
};
</script>
......
......@@ -37,21 +37,18 @@ export const pathMap = {
},
//烫画
//获取生产配置
productionConfig: "api/factory/production-config",
productionConfig: "factory/production-config/get",
//更新生产配置
productionConfigUpdate: "/api/factory/production-config/update",
productionConfigUpdate: "factory/production-config/update",
//排版列表(分页)
productionSoftware:
"/api/factory/podOrderBatchDownload/page-production-software",
productionSoftware: "factory/podOrderBatchDownload/page-production-software",
//查询该批次下的所有素材
listMaterialsByBatch:
"/api/factory/podOrderBatchDownload/list-materials-by-batch",
listMaterialsByBatch: "factory/podOrderBatchDownload/list-materials-by-batch",
//重新合成排版
psReComposingDesignImages:
"/api/factory/podOrderBatchDownload/psReComposingDesignImages",
"factory/podOrderBatchDownload/psReComposingDesignImages",
//根据批次分页查询操作单
listOperationByBatch:
"/api/factory/podOrderBatchDownload/listOperationByBatch"
listOperationByBatch: "factory/podOrderBatchDownload/listOperationByBatch"
};
// 操作单状态枚举
export const statusMap = {
......@@ -67,10 +64,20 @@ export const statusMap = {
};
export function autoRegisterRouter(router, funcKey, handler) {
const configGroup = pathMap[funcKey];
// 遍历配置自动注册路由
Object.values(configGroup).forEach(el => {
router.post(`/${el}`, (req, res) => {
const pathConfig = pathMap[funcKey];
// 根据类型收集所有需要注册的接口路径
let pathList = [];
if (typeof pathConfig === "string") {
// 字符串类型:单一路径(如 productionConfig)
pathList = [pathConfig];
} else if (typeof pathConfig === "object" && pathConfig !== null) {
// 对象类型:多站点路径集合(如 findByPodProductionNo)
pathList = Object.values(pathConfig);
}
// 批量注册路由
pathList.forEach(path => {
router.post(`/${path}`, (req, res) => {
handler(req, res);
});
});
......
[
{
"name": "Shopify",
"lowercase": "shopify",
"type": "SHOPIFY",
"icon": "@/assets/images/icon/logo-1.png",
"cycle": "today",
"route": "store_profits_shopify"
},
{
"name": "AliExpress",
"lowercase": "aliExpress",
"type": "AE",
"icon": "@/assets/images/icon/logo-3.png",
"cycle": "today",
"route": "store_profits_aliexpress"
},
{
"name": "Amazon",
"lowercase": "amazon",
"type": "AMAZON",
"icon": "@/assets/images/icon/logo-2.png",
"cycle": "yesterday",
"route": "store_profits_amazon"
},
{
"name": "Magento",
"lowercase": "magento",
"type": "MAGENTO",
"icon": "@/assets/images/icon/logo-6.png",
"cycle": "today",
"route": "store_profits_magento"
},
{
"name": "SHOPLINE",
"lowercase": "shopline",
"type": "SHOPLINE",
"cycle": "today",
"icon": "@/assets/images/icon/logo-4.png",
"route": "store_profits_shopline"
},
{
"name": "Shoplazza",
"lowercase": "shoplazza",
"type": "SHOPLAZZA",
"cycle": "today",
"icon": "@/assets/images/icon/logo-5.png",
"route": "store_profits_shoplazza"
},
{
"name": "temu",
"lowercase": "temu",
"type": "TEMU",
"cycle": "today",
"icon": "@/assets/images/icon/temu.png",
"route": "store_profits_temu"
},
{
"name": "eBay",
"lowercase": "ebay",
"type": "EBAY",
"cycle": "today",
"icon": "@/assets/images/icon/eBay.png",
"route": "store_profits_ebay"
},
{
"name": "Etsy",
"lowercase": "etsy",
"type": "ETSY",
"cycle": "today",
"icon": "@/assets/images/icon/etsy.png",
"route": "store_profits_etsy"
},
{
"name": "Alibaba",
"lowercase": "alibaba",
"type": "ALIBABA",
"cycle": "today",
"icon": "@/assets/images/icon/alibaba.png",
"route": "store_profits_alibaba"
},
{
"name": "walmart",
"lowercase": "walmart",
"type": "WALMART",
"cycle": "today",
"icon": "@/assets/images/icon/walmart.png",
"route": "store_profits_walmart"
},
{
"name": "tiktokshop",
"lowercase": "tiktok",
"type": "TIKTOK",
"cycle": "today",
"icon": "@/assets/images/icon/tiktokshop.png",
"route": "store_profits_tiktokshop"
},
{
"name": "Customize",
"lowercase": "customize",
"type": "CUSTOMIZE",
"cycle": "today",
"icon": "@/assets/images/icon/customize.png",
"route": "store_profits_customize"
},
{
"name": "1688",
"type": "ALIBABA_DOMESTIC",
"cycle": "today",
"icon": "@/assets/images/icon/1688.png",
"route": "store_profits_1688"
}
]
......@@ -385,7 +385,6 @@ export default {
try {
env = getHostApi().apiApiHost;
console.log(`${env}/factory/login`);
let { data } = await axios.post(`${env}/factory/login`, req.body);
res.send(data);
} catch (err) {
......@@ -701,9 +700,8 @@ export default {
let url = pathMap["productionConfigUpdate"];
try {
let { data } = await axios.post(`${env}/${url}`, {
headers: { "jwt-token": token },
params
let { data } = await axios.post(`${env}/${url}`, params, {
headers: { "jwt-token": token }
});
res.send(data);
} catch (error) {
......@@ -719,9 +717,8 @@ export default {
let url = pathMap["productionSoftware"];
try {
let { data } = await axios.post(`${env}/${url}`, {
headers: { "jwt-token": token },
params
let { data } = await axios.post(`${env}/${url}`, params, {
headers: { "jwt-token": token }
});
res.send(data);
} catch (error) {
......@@ -773,9 +770,8 @@ export default {
let url = pathMap["listOperationByBatch"];
try {
let { data } = await axios.post(`${env}/${url}`, {
headers: { "jwt-token": token },
params
let { data } = await axios.post(`${env}/${url}`, params, {
headers: { "jwt-token": token }
});
res.send(data);
} catch (error) {
......
......@@ -61,17 +61,21 @@ router.post("/downloadMaterial", fn.downloadMaterial);
router.post("/copySingleImageFn", fn.copySingleImageFn);
//获取生产配置
router.post("/productionConfig", fn.productionConfig);
autoRegisterRouter(router, "productionConfig", fn.productionConfig);
//更新生产配置
router.post("/productionConfigUpdate", fn.productionConfigUpdate);
autoRegisterRouter(router, "productionConfigUpdate", fn.productionConfigUpdate);
//排版列表(分页)
router.post("/productionSoftware", fn.productionSoftware);
autoRegisterRouter(router, "productionSoftware", fn.productionSoftware);
//查询该批次下的所有素材
router.post("/productionSoftware", fn.productionSoftware);
autoRegisterRouter(router, "listMaterialsByBatch", fn.listMaterialsByBatch);
//重新合成排版
router.post("/psReComposingDesignImages", fn.psReComposingDesignImages);
autoRegisterRouter(
router,
"psReComposingDesignImages",
fn.psReComposingDesignImages
);
//根据批次分页查询操作单
router.post("/listOperationByBatch", fn.listOperationByBatch);
autoRegisterRouter(router, "listOperationByBatch", fn.listOperationByBatch);
// 根据生产单号查询详情
autoRegisterRouter(router, "findByPodProductionNo", fn.findByPodProductionNo);
......
<script>
const { getDTFSetting } = require("@/server/utils/store");
const { ipcRenderer } = require("electron");
const { statusMap } = require("@/config/index.js");
export default {
props: {
user: {
......@@ -18,7 +18,8 @@ export default {
dialogVisible: false,
dtfSetting: getDTFSetting(),
radio: "",
searchForm: {}
searchForm: {},
statusMap: statusMap
};
},
computed: {},
......
......@@ -3,6 +3,8 @@ import BaseCard from "@/components/BaseCard.vue";
import DTFhead from "./components/detailHead.vue";
import DetailDialog from "@/components/detailDialog.vue";
const { remote } = require("electron");
const { pathMap } = require("@/config/index.js");
import platformJson from "@/json/platform.json";
import LogList from "@//components/LogList.vue";
const { Menu } = remote;
import dayjs from "dayjs";
......@@ -30,21 +32,10 @@ export default {
pageSize: 10,
total: 2
},
cardList: Array.from({ length: 10 }, (_, index) => {
const isDtg = index % 2 === 0;
return {
id: index + 1,
batchNo: index + 1,
status: index % 3 === 0 ? 0 : 1,
img: isDtg ? "/static/dtg.jpg" : "/static/dtf.jpg",
subOrderNumber: index % 4 !== 0,
num: isDtg ? 120 + index * 2 : 86 + index,
failedReason: "",
active: false
};
}),
cardList: [],
detailRow: {
batchArrangeNumber: { label: "批次号", value: 111 },
batchArrangeNum: { label: "批次号", value: 111 },
operationNum: { label: "操作单数量", value: 111 },
materialNum: { label: "素材数量", value: 111 },
craftType: { label: "工艺类型", value: 111 },
......@@ -52,15 +43,47 @@ export default {
createTime: { label: "创建时间", value: 111 },
layoutStatus: { label: "排版状态", value: 111 },
status: { label: "操作单状态", value: 111 }
}
},
platformJson: platformJson
};
},
mounted() {
console.log(this.cardList);
this.loadRowData();
},
methods: {
loadData() {
// 请求列表接口
async loadRowData() {
try {
const params = this.$route.params;
console.log("params", params);
Object.keys(this.detailRow).forEach(key => {
// 路由里有对应值就赋值,没有则保留默认值
if (params[key] !== undefined) {
this.detailRow[key].value = params[key];
}
});
await this.getCardList({ batchArrangeNumber: params.batchArrangeNum });
} catch (error) {
console.log(error);
}
},
async getCardList(value) {
let params = {
currentPage: this.pageInfo.currentPage,
pageSize: this.pageInfo.pageSize
};
if (value) {
params = { ...params, ...value };
}
try {
const { data } = await this.$api.post(
pathMap["listOperationByBatch"],
params
);
this.cardList = data.records;
console.log("listOperationByBatch", data);
} catch (error) {
console.log(error);
}
},
handleSelect(rows) {
console.log("选中行", rows);
......@@ -75,8 +98,10 @@ export default {
this.loadData();
},
copyText(text) {
navigator.clipboard.writeText(text);
// ElMessage.success("复制成功");
const { clipboard } = window.require("electron").remote;
// 复制文本,同步方法,调用即生效
clipboard.writeText(text);
this.$message.success(`复制成功`);
},
getOrderDelayText(createTime) {
if (!createTime) return "--";
......@@ -114,7 +139,37 @@ export default {
getItemTags(tagsId) {},
setProductMark(tagsId) {},
parseImageAry(tagsId) {},
parseImageAry(imageAry) {
if (typeof imageAry !== "string" || !imageAry.trim()) return [];
const trimmed = imageAry.trim();
if (trimmed.startsWith("http")) {
return trimmed
.split(",")
.map(url => ({ url: url.trim() }))
.filter(item => item.url);
}
try {
const parsed = JSON.parse(trimmed);
if (!Array.isArray(parsed)) return [{ url: trimmed }];
const result = [];
for (const item of parsed) {
if (typeof item === "string" && item) {
result.push({ url: item });
} else if (item && typeof item === "object" && "url" in item) {
const url = item.url;
if (url) {
result.push({
url,
title: item.title
});
}
}
}
return result;
} catch {
return [{ url: trimmed }];
}
},
openLogDialog(tagsId) {
console.log(999);
......@@ -129,6 +184,19 @@ export default {
} catch (e) {
console.error(e);
}
},
getPlatformImg(code) {
const lowerCode = code.toLowerCase();
const item = platformJson.find(el =>
el.type.toLowerCase().includes(lowerCode)
);
if (item) {
console.log(item.icon);
return item.icon.split("/").pop();
}
return "";
}
}
};
......@@ -144,8 +212,8 @@ export default {
style="display: flex;
flex-direction: column; align-items: center;"
>
<div>{{ item.label }}</div>
<div>{{ item.value }}</div>
<div style="min-height: 22px;">{{ item.label }}</div>
<div style="min-height: 22px;">{{ item.value }}</div>
</div>
</div>
</div>
......@@ -185,10 +253,10 @@ export default {
<div
style="
background-color: #f0f9eb;
color: #fff;
padding: 2px 4px;
font-size: 12px;
color: #6fc844;
border-radius: 4px;
padding:5px;
font-size: 20px;
"
>
......@@ -231,6 +299,7 @@ export default {
text-overflow: ellipsis;
width: 100%;
display: inline-block;
margin-right: 8px;
"
@click.stop="copyText(String(item?.userMark || ''))"
>
......@@ -239,8 +308,8 @@ export default {
</el-tooltip>
<img
v-if="item.platform"
:src="''"
style="width: 30px; height: 30px"
:src="`/images/icon/${getPlatformImg(item.platform)}`"
style="width: 30px"
/>
</div>
</div>
......@@ -248,12 +317,7 @@ export default {
<template #operations>
<div class="flex-row flex-row-gap6">
<div
class="quantity-badge"
:class="
item.customizedQuantity === 1
? 'single-quantity-badge-color'
: 'multiple-quantity-badge-color'
"
class="quantity-badge multiple-quantity-badge-color"
:title="
`类型:${item.customizedQuantity === 1 ? '单面' : '双面'}`
"
......@@ -491,13 +555,13 @@ export default {
.card-info-grid {
display: grid;
grid-template-columns: 1fr 150px;
grid-template-columns: auto auto;
gap: 4px;
font-size: 12px;
margin-top: 6px;
.full {
grid-column: 1 / -1;
grid-column: span 2;
}
}
......@@ -591,23 +655,23 @@ export default {
}
@media (max-width: 1920px) {
.card-grid {
grid-template-columns: repeat(7, minmax(0, 1fr));
grid-template-columns: repeat(6, minmax(0, 1fr));
}
}
@media (max-width: 1750px) {
.card-grid {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
.card-info-grid {
grid-template-columns: 1fr 180px;
}
// .card-info-grid {
// grid-template-columns: 1fr 180px;
// }
}
@media (max-width: 1550px) {
.card-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.card-info-grid {
grid-template-columns: 1fr 200px;
}
// .card-info-grid {
// grid-template-columns: 1fr 200px;
// }
}
</style>
......@@ -4,7 +4,7 @@ const { remote, ipcRenderer } = require("electron");
const { getDTFSetting } = require("@/server/utils/store");
const { Menu } = remote;
const path = require("path");
const { pathMap } = require("@/config/index.js");
import DTFhead from "./components/head.vue";
export default {
name: "design-dtf",
......@@ -25,7 +25,9 @@ export default {
selectionList: [],
radio: "",
templateBatchArrangeNum: "",
pollTimer: null,
dtfSetting: getDTFSetting(),
isFetching: false,
pageInfo: {
currentPage: 1,
pageSize: 10,
......@@ -36,7 +38,7 @@ export default {
{
prop: "batchArrangeNum",
label: "批次号",
width: 100,
width: 140,
slotName: "batchArrangeNum"
},
{
......@@ -52,8 +54,7 @@ export default {
{
prop: "craftType",
label: "工艺类型",
width: 100,
slotName: "craftType"
width: 100
},
{
prop: "standardDesignImage",
......@@ -91,7 +92,8 @@ export default {
{
label: "操作",
width: 260,
slotName: "operation"
slotName: "operation",
prop: "operation"
}
],
layoutStatus: {
......@@ -105,7 +107,7 @@ export default {
},
mounted() {
this.fetchBatchList();
this.pollTimer = setInterval(() => this.fetchList(), 300000);
// this.pollTimer = setInterval(() => this.fetchBatchList(), 300000);
// 单文件下载成功
ipcRenderer.on("download:file-success", (_, data) => {
......@@ -128,35 +130,61 @@ export default {
});
},
beforeDestroy() {
clearInterval(this.pollTimer);
if (this.pollTimer) {
clearInterval(this.pollTimer);
this.pollTimer = null;
}
ipcRenderer.removeAllListeners("download:status-reply");
ipcRenderer.removeAllListeners("download:file-success");
ipcRenderer.removeAllListeners("download:file-error");
ipcRenderer.removeAllListeners("download:batch-invalid");
ipcRenderer.removeAllListeners("download:all-finish");
},
methods: {
getDownloadStatus() {
return new Promise(resolve => {
// 只监听一次回复,避免重复绑定
ipcRenderer.once("download:status-reply", (_, status) => {
resolve(status);
});
// 发送请求
ipcRenderer.send("download:get-status");
});
},
//定时任务
async fetchBatchList(value) {
// 先判断:有下载任务在跑,本轮直接跳过
const status = ipcRenderer.sendSync("download:get-status");
if (status.isRunning) return;
let params = {
currentPage: this.pageInfo.currentPage,
pageSize: this.pageInfo.pageSize
};
console.log("this.isFetching", this.isFetching);
if (value) {
params = { ...params, ...value };
}
if (this.isFetching) return;
this.isFetching = true;
try {
const res = await await this.$api.post("/productionSoftware", params);
const status = await this.getDownloadStatus();
console.log("status", status);
if (status.isRunning) return;
let params = {
currentPage: this.pageInfo.currentPage,
pageSize: this.pageInfo.pageSize
};
if (value) {
params = { ...params, ...value };
}
const res = await this.$api.post(pathMap["productionSoftware"], params);
if (res.code === 200) {
this.tableData = res.data.records || [];
this.tableList = res.data.records || [];
console.log(this.tableList);
this.pageInfo.total = res.data.total;
ipcRenderer.sendSync("download:submit-batch-list", this.tableData);
ipcRenderer.sendSync("download:submit-batch-list", this.tableList);
}
} catch (err) {
console.error("批次列表拉取失败", err);
} finally {
this.isFetching = false;
}
},
......@@ -235,7 +263,7 @@ export default {
type: "warning"
}
);
await this.$api.post("/psReComposingDesignImages", {
await this.$api.post(pathMap["psReComposingDesignImages"], {
batchArrangeNum: this.templateBatchArrangeNum,
templateWidth: this.radio
});
......@@ -243,7 +271,7 @@ export default {
"排版进行中,请查看处理状态,排版完成的素材至文件夹排版素材查看"
);
} else {
await this.$api.post("/psReComposingDesignImages", {
await this.$api.post(pathMap["psReComposingDesignImages"], {
batchArrangeNum: this.templateBatchArrangeNum,
templateWidth: this.radio
});
......@@ -258,7 +286,7 @@ export default {
this.$router.push({
name: "dtf-batch-detail",
params: {
batchArrangeNum: value
...value
}
});
},
......@@ -266,7 +294,7 @@ export default {
//下载批次原素材
async downloadFile(value) {
try {
const { data } = await this.$api.post("/listMaterialsByBatch", {
const { data } = await this.$api.post(pathMap["listMaterialsByBatch"], {
batchArrangeNum: value
});
const res = await this.$api.post("/downloadMaterial", {
......@@ -314,7 +342,7 @@ export default {
>
<!-- 自定义插槽示例 -->
<template #batchArrangeNum="scope">
<a href="javascript:;" @click="toDetail(scope.row.batchArrangeNum)">{{
<a href="javascript:;" @click="toDetail(scope.row)">{{
scope.row.batchArrangeNum
}}</a>
</template>
......
......@@ -88,7 +88,7 @@ export default {
},
mounted() {
// 页面加载读取本地配置回填表单
// this.loadLocalConfig();
this.loadLocalConfig();
},
methods: {
// 返回上一页
......@@ -115,7 +115,7 @@ export default {
// 保存配置到本地文件
async saveConfig() {
if (this.form.autoLayoutStrategy == 2 && this.form.widthStrategy == 3) {
this.$confirm(
await this.$confirm(
"由于排版设置中选择“按更大规格排版”仅适用于40+2,选60时,默认超60的规格不排版",
"提示",
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment