Commit 1a6d16c7 by linjinhong

feat:对接后端接口

parent 4fbb5e26
......@@ -4,8 +4,8 @@ import { app, protocol, BrowserWindow, globalShortcut } from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import { createServer } from "@/server/index.js";
import { autoUpdater } from "electron-updater";
const axios = require("axios");
const createDownloadQueue = require("@/utils/download-queue");
const { createBatchDownloadQueue } = require("@/utils/download-queue");
const fs = require("fs");
import path from "path"; // 引入 path 模块
......@@ -31,23 +31,32 @@ const winURL =
: `file://${__dirname}/index.html`;
// 全局唯一下载队列,服务启动时初始化一次
const downloadQueue = createDownloadQueue({
concurrency: 2,
const downloadQueue = createBatchDownloadQueue({
concurrency: 3,
retryTimes: 2,
// 根目录:系统下载目录/排版素材,可自行修改为固定盘符
basePath: path.join(app.getPath("downloads"), "自动排版素材"),
// 文件名规则,可自定义
fileNameRule: task => `${task.batchArrangeNum}_自动排版素材.zip`,
basePath: "",
// 单文件下载成功
onSuccess: task => {
console.log(`批次 ${task.batchArrangeNum} 下载完成`);
win.webContents.send("download:success", task.batchArrangeNum);
win?.webContents.send("download:file-success", {
batchArrangeNum: task.batchArrangeNum,
fileName: task.fileName
});
},
// 单文件下载失败
onError: (task, err) => {
console.error(`批次 ${task.batchArrangeNum} 下载失败:`, err.message);
win.webContents.send("download:error", {
win?.webContents.send("download:file-error", {
batchArrangeNum: task.batchArrangeNum,
fileName: task.fileName,
msg: err.message
});
},
// 批次校验失败(新增:返回所有异常批次)
onBatchInvalid: invalidList => {
win?.webContents.send("download:batch-invalid", invalidList);
},
// 全部任务完成
onIdle: () => {
win?.webContents.send("download:all-finish");
}
});
......@@ -504,31 +513,13 @@ async function createWindow() {
const { width, height } = win.getBounds();
win.webContents.send("window-size", { width, height });
});
// 1. 批量添加下载任务
ipcMain.on("download:addTasks", (event, tasks) => {
const BASE_URL = "";
// 给每个任务挂载获取下载地址的方法
const taskList = tasks.map(item => ({
...item,
fetchUrl: async () => {
const params = {};
const res = await axios({
method: "get",
url: `${BASE_URL}/material/getDownloadUrl`,
params
})({
batchArrangeNum: item.batchArrangeNum
});
return res.data.downloadUrl;
}
}));
downloadQueue.addTasks(taskList);
event.returnValue = { code: 200, msg: "已加入队列" };
// IPC 通信
ipcMain.on("download:submit-batch-list", (event, list) => {
downloadQueue.addBatchList(list);
event.returnValue = { code: 200, msg: "已处理" };
});
// 2. 查询队列运行状态
ipcMain.on("download:getStatus", event => {
ipcMain.on("download:get-status", event => {
event.returnValue = { isRunning: downloadQueue.isRunning };
});
}
......
......@@ -44,18 +44,6 @@
v-html="col.render(scope.row, scope.column, scope.$index)"
></span>
<!-- 2. tag标签 -->
<el-tag
v-else-if="col.type === 'tag'"
:type="col.getTagType ? col.getTagType(scope.row) : 'primary'"
:effect="col.tagEffect || 'light'"
size="mini"
>
{{
col.getTagText ? col.getTagText(scope.row) : scope.row[col.prop]
}}
</el-tag>
<!-- 3. 图片 -->
<el-image
v-else-if="col.type === 'image'"
......@@ -107,7 +95,7 @@
class="table-pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageInfo.pageNum"
:current-page="pageInfo.currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageInfo.pageSize"
layout="total, sizes, prev, pager, next, jumper"
......@@ -170,12 +158,12 @@ export default {
},
/**
* 分页信息
* { pageNum: 1, pageSize: 10, total: 0 }
* { currentPage: 1, pageSize: 10, total: 0 }
*/
pageInfo: {
type: Object,
default: () => ({
pageNum: 1,
currentPage: 1,
pageSize: 10,
total: 0
})
......
......@@ -34,7 +34,36 @@ export const pathMap = {
},
checkInventory: {
OP: "factory/podOrderOperation/check-inventory"
}
},
//烫画
//获取生产配置
productionConfig: "api/factory/production-config",
//更新生产配置
productionConfigUpdate: "/api/factory/production-config/update",
//排版列表(分页)
productionSoftware:
"/api/factory/podOrderBatchDownload/page-production-software",
//查询该批次下的所有素材
listMaterialsByBatch:
"/api/factory/podOrderBatchDownload/list-materials-by-batch",
//重新合成排版
psReComposingDesignImages:
"/api/factory/podOrderBatchDownload/psReComposingDesignImages",
//根据批次分页查询操作单
listOperationByBatch:
"/api/factory/podOrderBatchDownload/listOperationByBatch"
};
// 操作单状态枚举
export const statusMap = {
待排单: "PENDING_SCHEDULE",
待拣胚: "PENDING_PICK",
待补胚: "PENDING_REPLENISH",
生产中: "IN_PRODUCTION",
待配货: "PENDING_PACKING",
配货完成: "PACKING_COMPLETED",
已完成: "COMPLETED",
已取消: "CANCELLED",
已归档: "ARCHIVE"
};
export function autoRegisterRouter(router, funcKey, handler) {
......
......@@ -6,7 +6,7 @@ import {
copySingleImage,
createBatchFolder
} from "@/server/utils";
const { downloadPngList } = require("@/utils/download-queue");
const {
cropImageTransparentEdges,
cropTransparentEdges,
......@@ -668,12 +668,119 @@ export default {
},
downloadMaterial: async (req, res) => {
try {
const { downloadDir, isArray, basePath } = req.body;
res.send();
const { urls, targetPath } = req.body;
const data = await downloadPngList(urls, targetPath);
res.send(data);
} catch (error) {
console.log("downloadMaterial", error);
res.json({ code: 500, msg: error });
}
},
//获取生产配置
productionConfig: async (req, res) => {
env = getHostApi().apiApiHost;
const token = req.headers["jwt-token"];
let url = pathMap["productionConfig"];
try {
let { data } = await axios.get(`${env}/${url}`, {
headers: { "jwt-token": token }
});
res.send(data);
} catch (error) {
console.log("checkInventory", error);
res.json({ code: 500, msg: error });
}
},
//更新生产配置
productionConfigUpdate: async (req, res) => {
env = getHostApi().apiApiHost;
const token = req.headers["jwt-token"];
const params = req.body;
let url = pathMap["productionConfigUpdate"];
try {
let { data } = await axios.post(`${env}/${url}`, {
headers: { "jwt-token": token },
params
});
res.send(data);
} catch (error) {
console.log("checkInventory", error);
res.json({ code: 500, msg: error });
}
},
//排版列表(分页)
productionSoftware: async (req, res) => {
env = getHostApi().apiApiHost;
const token = req.headers["jwt-token"];
const params = req.body;
let url = pathMap["productionSoftware"];
try {
let { data } = await axios.post(`${env}/${url}`, {
headers: { "jwt-token": token },
params
});
res.send(data);
} catch (error) {
console.log("checkInventory", error);
res.json({ code: 500, msg: error });
}
},
//查询该批次下的所有素材
listMaterialsByBatch: async (req, res) => {
env = getHostApi().apiApiHost;
const token = req.headers["jwt-token"];
const params = req.body;
let url = pathMap["listMaterialsByBatch"];
try {
let { data } = await axios.get(`${env}/${url}`, {
headers: { "jwt-token": token },
params
});
res.send(data);
} catch (error) {
console.log("checkInventory", error);
res.json({ code: 500, msg: error });
}
},
//重新合成排版
psReComposingDesignImages: async (req, res) => {
env = getHostApi().apiApiHost;
const token = req.headers["jwt-token"];
const params = req.body;
let url = pathMap["psReComposingDesignImages"];
try {
let { data } = await axios.get(`${env}/${url}`, {
headers: { "jwt-token": token },
params
});
res.send(data);
} catch (error) {
console.log("checkInventory", error);
res.json({ code: 500, msg: error });
}
},
//根据批次分页查询操作单
listOperationByBatch: async (req, res) => {
env = getHostApi().apiApiHost;
const token = req.headers["jwt-token"];
const params = req.body;
let url = pathMap["listOperationByBatch"];
try {
let { data } = await axios.post(`${env}/${url}`, {
headers: { "jwt-token": token },
params
});
res.send(data);
} catch (error) {
console.log("checkInventory", error);
res.json({ code: 500, msg: error });
}
}
};
......@@ -60,6 +60,19 @@ router.post("/downloadMaterial", fn.downloadMaterial);
//复制文件夹下文件
router.post("/copySingleImageFn", fn.copySingleImageFn);
//获取生产配置
router.post("/productionConfig", fn.productionConfig);
//更新生产配置
router.post("/productionConfigUpdate", fn.productionConfigUpdate);
//排版列表(分页)
router.post("/productionSoftware", fn.productionSoftware);
//查询该批次下的所有素材
router.post("/productionSoftware", fn.productionSoftware);
//重新合成排版
router.post("/psReComposingDesignImages", fn.psReComposingDesignImages);
//根据批次分页查询操作单
router.post("/listOperationByBatch", fn.listOperationByBatch);
// 根据生产单号查询详情
autoRegisterRouter(router, "findByPodProductionNo", fn.findByPodProductionNo);
......
......@@ -215,13 +215,13 @@ module.exports = {
},
getDTFSetting: () =>
store.get("DTFSetting") || {
overWidthMode: "autoScale",
widthStrategy: "1",
// 最大素材数模式:batch / custom
maxPicMode: "batch",
materialStrategy: "1",
// 自定义素材数量
customPicNum: 30,
materialCount: 30,
// 自动排版规格 40+2 / 60 / none
autoLayoutType: "none",
autoLayoutStrategy: "3",
// 默认下载目录
downloadDir: ""
},
......
<script>
import { mapState } from "vuex";
const { getDesktopDevice, getDTFSetting } = require("@/server/utils/store");
const { getDTFSetting } = require("@/server/utils/store");
const { ipcRenderer } = require("electron");
export default {
......@@ -18,39 +17,13 @@ export default {
return {
dialogVisible: false,
dtfSetting: getDTFSetting(),
radio: ""
radio: "",
searchForm: {}
};
},
computed: {
...mapState([
"defaultProportion",
"countryList",
"orderType",
"grid",
"imgList"
])
},
mounted() {
this.$nextTick(() => {
this.$refs.searchRef?.focus();
if (this.desktopDevice !== 3) {
this.selectGridIndex = 0;
this.setting.gridValue = 0;
} else {
this.selectGridIndex = 5;
this.setting.gridValue = 5;
}
});
this.$store.commit("changeDesktopDevice", getDesktopDevice());
},
created() {
localStorage.setItem("desktoVersion", "print");
if (this.$dataStore.get("setting")) {
this.setting = this.$dataStore.get("setting");
} else {
this.$dataStore.set("setting", this.setting);
}
},
computed: {},
mounted() {},
created() {},
methods: {
dropdownCommand(v) {
......@@ -87,13 +60,10 @@ export default {
goBack() {
this.$router.push({ name: "design-dtf" });
},
goSetting() {
this.$router.push({
path: "/DTFsetting",
query: { id: 123 }
});
goSetting() {},
getDataInfo() {
this.$emit("search", this.searchForm);
},
getDataInfo() {},
productionCompleted() {
this.$confirm("确认完成生产?", "提示", {
confirmButtonText: "确定",
......@@ -106,13 +76,12 @@ export default {
changeTypesetting() {
this.dialogVisible = true;
},
submit() {
console.log(this.radio);
async submit() {
if (!this.radio) {
return this.$message.error("请选择排版宽度");
}
if (this.dtfSetting.overWidthMode === "biggerSize" && this.radio == 60) {
if (this.dtfSetting.widthStrategy == 3 && this.radio == 60) {
this.$confirm(
"由于排版设置中选择“按更大规格排版”仅适用于40+2,选60时,默认超60的规格不排版",
"提示",
......@@ -120,13 +89,19 @@ export default {
confirmButtonText: "确定",
type: "warning"
}
).then(() => {
this.dialogVisible = false;
this.$message(
"排版进行中,请查看处理状态,排版完成的素材至文件夹排版素材查看"
);
);
await this.$api.post("/psReComposingDesignImages", {
batchArrangeNum: this.templateBatchArrangeNum,
templateWidth: this.radio
});
this.$message(
"排版进行中,请查看处理状态,排版完成的素材至文件夹排版素材查看"
);
} else {
await this.$api.post("/psReComposingDesignImages", {
batchArrangeNum: this.templateBatchArrangeNum,
templateWidth: this.radio
});
this.$message(
"排版进行中,请查看处理状态,排版完成的素材至文件夹排版素材查看"
);
......@@ -161,8 +136,26 @@ export default {
>返回</el-button
></el-form-item
>
<el-form-item> <el-input></el-input></el-form-item>
<el-form-item label="操作单状态"> <el-input></el-input></el-form-item>
<el-form-item>
<el-input
placeholder="请扫描操作单"
v-model="searchForm.operationNo"
></el-input
></el-form-item>
<el-form-item label="操作单状态">
<el-select v-model="searchForm.status" placeholder="请选择" clearable>
<el-option
v-for="(value, label) in statusMap"
:key="value"
:label="label"
:value="value"
></el-option> </el-select
></el-form-item>
<el-form-item label="操作单排版状态">
<el-select v-model="searchForm.layout" placeholder="请选择">
<el-option label="是" :value="true"></el-option>
<el-option label="否" :value="false"> </el-option> </el-select
></el-form-item>
<el-form-item>
<el-button @click="getDataInfo" type="primary"
......
......@@ -18,12 +18,7 @@ export default {
}),
type: Object
},
factoryType: { type: String, default: "CN" },
cardConfig: {
imageSrc: "./src/assets/template-bg-1.jpg",
title: "title",
time: "time"
}
factoryType: { type: String, default: "CN" }
},
data() {
return {
......@@ -31,7 +26,7 @@ export default {
detailVisible: false,
logList: [],
pageInfo: {
pageNum: 1,
currentPage: 1,
pageSize: 10,
total: 2
},
......@@ -49,14 +44,14 @@ export default {
};
}),
detailRow: {
name: { label: "批次号", value: 111 },
name1: { label: "操作单数量", value: 111 },
name2: { label: "素材数量", value: 111 },
name3: { label: "工艺类型", value: 111 },
name6: { label: "规范素材", value: 111 },
name4: { label: "创建时间", value: 111 },
name5: { label: "排版状态", value: 111 },
name7: { label: "操作单状态", value: 111 }
batchArrangeNumber: { label: "批次号", value: 111 },
operationNum: { label: "操作单数量", value: 111 },
materialNum: { label: "素材数量", value: 111 },
craftType: { label: "工艺类型", value: 111 },
standardDesignImage: { label: "规范素材", value: 111 },
createTime: { label: "创建时间", value: 111 },
layoutStatus: { label: "排版状态", value: 111 },
status: { label: "操作单状态", value: 111 }
}
};
},
......@@ -180,30 +175,25 @@ export default {
{{ item.operationNo }}
</span>
</template>
<template #top_left>
<template #top_right>
<el-tooltip
v-if="item.outOfStock"
v-if="item.layout"
effect="light"
content="缺货"
content="排版完成"
placement="bottom"
>
<div
style="
background-color: #f56c6c;
background-color: #f0f9eb;
color: #fff;
padding: 2px 4px;
border-radius: 4px;
font-size: 12px;
"
>
</div>
</el-tooltip>
<span v-if="item.tagsId" class="flex-row flex-row-gap6">
<el-tag v-for="tag in getItemTags(item.tagsId)" :key="tag.id">
{{ tag.name }}
</el-tag>
</span>
</template>
<template #images>
......@@ -291,9 +281,9 @@ export default {
<div class="card-info-row full">
<span
class="info-value ellipsis"
:title="item.productName || ''"
:title="item.operationNo || ''"
>
{{ item.productName }}
{{ item.operationNo }}
</span>
</div>
<div class="card-info-row">
......
<script>
import { mapState } from "vuex";
const { getDesktopDevice } = require("@/server/utils/store");
export default {
props: {
user: {
......@@ -13,38 +11,13 @@ export default {
factoryType: { type: String, default: "CN" }
},
data() {
return {};
},
computed: {
...mapState([
"defaultProportion",
"countryList",
"orderType",
"grid",
"imgList"
])
},
mounted() {
this.$nextTick(() => {
this.$refs.searchRef?.focus();
if (this.desktopDevice !== 3) {
this.selectGridIndex = 0;
this.setting.gridValue = 0;
} else {
this.selectGridIndex = 5;
this.setting.gridValue = 5;
}
});
this.$store.commit("changeDesktopDevice", getDesktopDevice());
},
created() {
localStorage.setItem("desktoVersion", "print");
if (this.$dataStore.get("setting")) {
this.setting = this.$dataStore.get("setting");
} else {
this.$dataStore.set("setting", this.setting);
}
return {
searchForm: { batchArrangeNumber: "", layoutStatus: "", startTime: "" }
};
},
computed: {},
mounted() {},
created() {},
methods: {
dropdownCommand(v) {
......@@ -78,14 +51,7 @@ export default {
return "";
},
goBack() {
// Vue路由返回
this.$router.push({
name: "design"
});
// 如果需要关闭当前弹窗/子窗口,搭配:
// ipcRenderer.send("close-current-win");
},
goSetting() {
this.$router.push({
name: "dtf-setting"
......@@ -96,7 +62,9 @@ export default {
name: "dtf-batch-detail"
});
},
getDataInfo() {}
getDataInfo() {
this.$emit("search", this.searchForm);
}
}
};
</script>
......@@ -104,10 +72,39 @@ export default {
<template>
<div>
<div class="page-header">
<el-form style="display: flex;flex-wrap: nowrap;" inline>
<el-form-item label="批次号"> <el-input></el-input></el-form-item>
<el-form-item label="排版状态"> <el-input></el-input></el-form-item>
<el-form-item label="创建时间"> <el-input></el-input></el-form-item>
<el-form
style="display: flex;flex-wrap: nowrap;"
inline
:model="searchForm"
>
<el-form-item label="批次号">
<el-input
v-model="searchForm.batchArrangeNumber"
placeholder="请输入批次号"
></el-input
></el-form-item>
<el-form-item label="排版状态">
<el-select
v-model="searchForm.layoutStatus"
placeholder="请选择排版状态"
>
<el-option label="待排版" :value="1"></el-option>
<el-option label="排版中" :value="2"> </el-option>
<el-option label="排版成功" :value="3"> </el-option>
<el-option label="排版失败" :value="4"> </el-option>
<el-option label="部分成功" :value="5"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="searchForm.startTime"
type="datetime"
placeholder="选择创建时间"
format="yyyy 年 MM 月 dd 日"
value-format="yyyy-MM-dd"
>
</el-date-picker
></el-form-item>
<el-form-item>
<el-button @click="getDataInfo" type="primary"
>查询
......@@ -118,12 +115,6 @@ export default {
>DTF排版设置
</el-button></el-form-item
>
<el-form-item>
<el-button @click="goSetting1" type="success"
>详情页
</el-button></el-form-item
>
</el-form>
<div class="right-user">
......
......@@ -21,26 +21,24 @@
<div class="setting-group">
<div class="group-title">素材超排版宽度时:</div>
<el-radio-group v-model="form.overWidthMode">
<el-radio label="autoScale">自动缩小素材,适配烫画模宽度</el-radio>
<el-radio label="skip">超出排版宽度不排版</el-radio>
<el-radio label="biggerSize"
>超出排版宽度,使用更大规格排版</el-radio
>
<el-radio-group v-model="form.widthStrategy">
<el-radio :label="1">自动缩小素材,适配烫画模宽度</el-radio>
<el-radio :label="2">超出排版宽度不排版</el-radio>
<el-radio :label="3">超出排版宽度,使用更大规格排版</el-radio>
</el-radio-group>
</div>
<div class="setting-group">
<div class="group-title">单张排版最大素材数:</div>
<el-radio-group v-model="form.maxPicMode">
<el-radio label="batch">批次素材数</el-radio>
<el-radio-group v-model="form.materialStrategy">
<el-radio :label="1">批次素材数</el-radio>
<div class="custom-num-row">
<el-radio label="custom">自定义素材数(建议数量30):</el-radio>
<el-radio :label="2">自定义素材数(建议数量30):</el-radio>
<el-input
v-model.number="form.customPicNum"
v-model.number="form.materialCount"
placeholder="请输入素材数"
style="width: 180px; margin-left: 8px"
:disabled="form.maxPicMode !== 'custom'"
:disabled="form.materialStrategy !== '2'"
/>
</div>
</el-radio-group>
......@@ -48,10 +46,10 @@
<div class="setting-group">
<div class="group-title">自动排版设置</div>
<el-radio-group v-model="form.autoLayoutType">
<el-radio label="40+2">40+2</el-radio>
<el-radio label="60">60</el-radio>
<el-radio label="none">不执行自动排版</el-radio>
<el-radio-group v-model="form.autoLayoutStrategy">
<el-radio :label="1">40+2</el-radio>
<el-radio :label="2">60</el-radio>
<el-radio :label="3">不执行自动排版</el-radio>
</el-radio-group>
</div>
......@@ -78,25 +76,19 @@
<script>
const { ipcRenderer } = require("electron");
const {
getProductType,
setProductType,
setDTFSetting,
getDTFSetting
} = require("@/server/utils/store");
const { setDTFSetting, getDTFSetting } = require("@/server/utils/store");
export default {
name: "dtf-setting",
data() {
return {
// 表单配置,可从本地配置文件读取初始化
form: { ...getDTFSetting() },
activeName: getProductType()
form: { ...getDTFSetting() }
};
},
mounted() {
// 页面加载读取本地配置回填表单
this.loadLocalConfig();
// this.loadLocalConfig();
},
methods: {
// 返回上一页
......@@ -105,12 +97,13 @@ export default {
},
// 读取本地配置
async loadLocalConfig() {
ipcRenderer.send("read-layout-config");
ipcRenderer.once("layout-config-data", (_, cfg) => {
if (cfg) {
this.form = Object.assign({}, this.form, cfg);
}
});
try {
const { data } = await this.$api.post("/productionConfig");
this.form = { ...data };
setDTFSetting({ ...this.form });
} catch (error) {
console.log(error);
}
},
// 选择文件夹弹窗
selectFolder() {
......@@ -120,11 +113,8 @@ export default {
});
},
// 保存配置到本地文件
saveConfig() {
if (
this.form.autoLayoutType == "60" &&
this.form.overWidthMode === "biggerSize"
) {
async saveConfig() {
if (this.form.autoLayoutStrategy == 2 && this.form.widthStrategy == 3) {
this.$confirm(
"由于排版设置中选择“按更大规格排版”仅适用于40+2,选60时,默认超60的规格不排版",
"提示",
......@@ -132,17 +122,11 @@ export default {
confirmButtonText: "确定",
type: "warning"
}
).then(() => {
this.$message.success("排版设置保存成功!");
});
} else {
this.$message.success("排版设置保存成功!");
);
}
await this.$api.post("/productionConfigUpdate", this.form);
setDTFSetting({ ...this.form });
},
tabClick(tab) {
if (tab.name == "DTG") this.goBack();
setProductType(tab.name);
this.$message.success("排版设置保存成功!");
}
}
};
......
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