Commit a19250fe by qinjianhui

feat: 手动排版时接口超时显示进度,提示用户已下载成功了

parent 362269f4
...@@ -148,7 +148,7 @@ export default { ...@@ -148,7 +148,7 @@ export default {
fs.writeFileSync(p, JSON.stringify(data)); fs.writeFileSync(p, JSON.stringify(data));
res.json({ code: 200 }); res.json({ code: 200 });
} catch (e) { } catch (e) {
res.json({ code: 500, msg: e }); res.json({ code: 500, msg: e.message });
} }
}, },
...@@ -242,7 +242,7 @@ export default { ...@@ -242,7 +242,7 @@ export default {
res.setHeader("Act-Request-URL", `${env}/${url}`); res.setHeader("Act-Request-URL", `${env}/${url}`);
res.json(data); res.json(data);
} catch (err) { } catch (err) {
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
getCompanyList: async (req, res) => { getCompanyList: async (req, res) => {
...@@ -254,7 +254,7 @@ export default { ...@@ -254,7 +254,7 @@ export default {
res.send(data); res.send(data);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
commitApply: async () => {}, commitApply: async () => {},
...@@ -287,7 +287,7 @@ export default { ...@@ -287,7 +287,7 @@ export default {
res.send(data); res.send(data);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
downloadByDesignId: async (req, res) => { downloadByDesignId: async (req, res) => {
...@@ -323,7 +323,7 @@ export default { ...@@ -323,7 +323,7 @@ export default {
}); });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
uploadImage: async (req, res) => { uploadImage: async (req, res) => {
...@@ -354,7 +354,7 @@ export default { ...@@ -354,7 +354,7 @@ export default {
}); });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
getPngImg: async (req, res) => { getPngImg: async (req, res) => {
...@@ -384,7 +384,7 @@ export default { ...@@ -384,7 +384,7 @@ export default {
}); });
} }
} catch (err) { } catch (err) {
res.send({ code: 500, msg: err }); res.send({ code: 500, msg: err.message });
} }
}, },
login: async (req, res) => { login: async (req, res) => {
...@@ -395,7 +395,7 @@ export default { ...@@ -395,7 +395,7 @@ export default {
res.send(data); res.send(data);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
toPrint: (req, res) => { toPrint: (req, res) => {
...@@ -409,7 +409,7 @@ export default { ...@@ -409,7 +409,7 @@ export default {
res.send({ code: 200, msg: "操作成功" }); res.send({ code: 200, msg: "操作成功" });
}) })
.catch(err => { .catch(err => {
res.send({ code: 500, msg: err }); res.send({ code: 500, msg: err.message });
}); });
}, },
checkUpdate: async (req, res) => { checkUpdate: async (req, res) => {
...@@ -430,7 +430,7 @@ export default { ...@@ -430,7 +430,7 @@ export default {
} }
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
...@@ -558,7 +558,7 @@ export default { ...@@ -558,7 +558,7 @@ export default {
}); });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
//获取国家名称及代码 //获取国家名称及代码
...@@ -572,7 +572,7 @@ export default { ...@@ -572,7 +572,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
//复制文件夹下文件 //复制文件夹下文件
...@@ -583,7 +583,7 @@ export default { ...@@ -583,7 +583,7 @@ export default {
res.json({ code: 200 }); res.json({ code: 200 });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
...@@ -616,7 +616,7 @@ export default { ...@@ -616,7 +616,7 @@ export default {
res.json({ code: 200, data: result }); res.json({ code: 200, data: result });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.json({ code: 500, msg: err }); res.json({ code: 500, msg: err.message });
} }
}, },
scanProduce: async (req, res) => { scanProduce: async (req, res) => {
...@@ -638,7 +638,7 @@ export default { ...@@ -638,7 +638,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("scanProduce", error); console.log("scanProduce", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
checkInventory: async (req, res) => { checkInventory: async (req, res) => {
...@@ -659,7 +659,7 @@ export default { ...@@ -659,7 +659,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("checkInventory", error); console.log("checkInventory", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
createBatchFolder: async (req, res) => { createBatchFolder: async (req, res) => {
...@@ -670,7 +670,7 @@ export default { ...@@ -670,7 +670,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("createBatchFolder", error); console.log("createBatchFolder", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
...@@ -688,7 +688,7 @@ export default { ...@@ -688,7 +688,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("productionConfig", error); console.log("productionConfig", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
//更新生产配置 //更新生产配置
...@@ -705,7 +705,7 @@ export default { ...@@ -705,7 +705,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("productionConfigUpdate", error); console.log("productionConfigUpdate", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
//排版列表(分页) //排版列表(分页)
...@@ -722,7 +722,7 @@ export default { ...@@ -722,7 +722,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("productionSoftware", error); console.log("productionSoftware", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
//查询该批次下的所有素材 //查询该批次下的所有素材
...@@ -740,7 +740,7 @@ export default { ...@@ -740,7 +740,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("listMaterialsByBatch", error); console.log("listMaterialsByBatch", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
//重新合成排版 //重新合成排版
...@@ -758,7 +758,7 @@ export default { ...@@ -758,7 +758,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("psReComposingDesignImages", error); console.log("psReComposingDesignImages", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
//根据批次分页查询操作单 //根据批次分页查询操作单
...@@ -775,7 +775,7 @@ export default { ...@@ -775,7 +775,7 @@ export default {
res.send(data); res.send(data);
} catch (error) { } catch (error) {
console.log("listOperationByBatch", error); console.log("listOperationByBatch", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
replenishmentComposingDesignImages: async (req, res) => { replenishmentComposingDesignImages: async (req, res) => {
...@@ -807,7 +807,7 @@ export default { ...@@ -807,7 +807,7 @@ export default {
res.json({ code: 200, data: result }); res.json({ code: 200, data: result });
} catch (error) { } catch (error) {
console.log("replenishmentComposingDesignImages", error); console.log("replenishmentComposingDesignImages", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
podOrderBatchDownload: async (req, res) => { podOrderBatchDownload: async (req, res) => {
...@@ -824,7 +824,7 @@ export default { ...@@ -824,7 +824,7 @@ export default {
res.json({ code: 200, data }); res.json({ code: 200, data });
} catch (error) { } catch (error) {
console.log("podOrderBatchDownload", error); console.log("podOrderBatchDownload", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
}, },
getPodOrderLog: async (req, res) => { getPodOrderLog: async (req, res) => {
...@@ -842,7 +842,7 @@ export default { ...@@ -842,7 +842,7 @@ export default {
res.json({ code: 200, data }); res.json({ code: 200, data });
} catch (error) { } catch (error) {
console.log("getPodOrderLog", error); console.log("getPodOrderLog", error);
res.json({ code: 500, msg: error }); res.json({ code: 500, msg: error.message });
} }
} }
}; };
...@@ -30,11 +30,11 @@ service.interceptors.request.use( ...@@ -30,11 +30,11 @@ service.interceptors.request.use(
if (user) { if (user) {
config.headers["jwt-token"] = user.token; config.headers["jwt-token"] = user.token;
} }
startLoading(); if (!config.skipLoading) startLoading();
return config; return config;
}, },
error => { error => {
endLoading(); if (!error.config?.skipLoading) endLoading();
// do something with request error // do something with request error
return Promise.reject(error); return Promise.reject(error);
} }
...@@ -45,7 +45,7 @@ service.interceptors.response.use( ...@@ -45,7 +45,7 @@ service.interceptors.response.use(
async response => { async response => {
// do something with response data // do something with response data
const res = response.data; const res = response.data;
endLoading(); if (!response.config.skipLoading) endLoading();
if (res.code) { if (res.code) {
if (res.code !== 200) { if (res.code !== 200) {
if (res.code === 411 || res.code === 205 || res.code === 301) { if (res.code === 411 || res.code === 205 || res.code === 301) {
...@@ -82,7 +82,7 @@ service.interceptors.response.use( ...@@ -82,7 +82,7 @@ service.interceptors.response.use(
return Promise.resolve(res); return Promise.resolve(res);
}, },
error => { error => {
endLoading(); if (!error.config?.skipLoading) endLoading();
let errMsg = "请求失败,请稍后重试"; let errMsg = "请求失败,请稍后重试";
// 1. 有服务端响应:提取后端返回的 msg // 1. 有服务端响应:提取后端返回的 msg
......
...@@ -16,6 +16,7 @@ import { ...@@ -16,6 +16,7 @@ import {
getTypesettingDownloadStatus, getTypesettingDownloadStatus,
onTypesettingStatusChange onTypesettingStatusChange
} from "@/utils/download-api"; } from "@/utils/download-api";
import { startLoading, endLoading } from "@/utils/axios";
export default { export default {
name: "design-dtf", name: "design-dtf",
...@@ -41,7 +42,9 @@ export default { ...@@ -41,7 +42,9 @@ export default {
isDownloading: false, isDownloading: false,
TypeDownloading: false, TypeDownloading: false,
dtfSetting: getDTFSetting(), dtfSetting: getDTFSetting(),
removeStatusListener: null, // 保存取消监听函数 removeStatusListener: null,
composingTasks: [],
composingPollTimer: null,
pageInfo: { pageInfo: {
currentPage: 1, currentPage: 1,
...@@ -120,6 +123,7 @@ export default { ...@@ -120,6 +123,7 @@ export default {
} }
}; };
}, },
computed: {},
async mounted() { async mounted() {
const savedPage = Number(this.$route.query.page); const savedPage = Number(this.$route.query.page);
if (savedPage > 0) { if (savedPage > 0) {
...@@ -139,7 +143,8 @@ export default { ...@@ -139,7 +143,8 @@ export default {
beforeDestroy() { beforeDestroy() {
if (this.removeStatusListener) this.removeStatusListener(); if (this.removeStatusListener) this.removeStatusListener();
if (this.removeListener) this.removeListener(); if (this.removeListener) this.removeListener();
// 取消待执行的防抖任务,避免销毁后执行报错 this.stopComposingPoll();
this.composingTasks.forEach(t => clearTimeout(t.dismissTimer));
this.downloadFile.cancel?.(); this.downloadFile.cancel?.();
}, },
methods: { methods: {
...@@ -232,6 +237,10 @@ export default { ...@@ -232,6 +237,10 @@ export default {
//打开手动排版弹窗 //打开手动排版弹窗
changeTypesetting(value) { changeTypesetting(value) {
if (this.TypeDownloading) {
this.$message.warning("其他排版下载中,请等待完成后再操作");
return;
}
if (![2].includes(value.layoutStatus)) { if (![2].includes(value.layoutStatus)) {
this.dialogVisible = true; this.dialogVisible = true;
this.radio = ""; this.radio = "";
...@@ -242,63 +251,166 @@ export default { ...@@ -242,63 +251,166 @@ export default {
//提交手动排版 //提交手动排版
async submit() { async submit() {
if (this.TypeDownloading) {
this.$message.warning("其他排版下载中,请等待完成后再操作");
return;
}
if (!this.radio) { if (!this.radio) {
return this.$message.error("请选择排版宽度"); return this.$message.error("请选择排版宽度");
} }
try {
this.TypeDownloading = true;
if (this.dtfSetting.widthStrategy == 3 && this.radio == 60) { if (this.dtfSetting.widthStrategy == 3 && this.radio == 60) {
this.$confirm( try {
await this.$confirm(
"由于排版设置中选择“按更大规格排版”仅适用于40+2,选60时,默认超60的规格不排版", "由于排版设置中选择“按更大规格排版”仅适用于40+2,选60时,默认超60的规格不排版",
"提示", "提示",
{ { confirmButtonText: "确定", type: "warning" }
confirmButtonText: "确定",
type: "warning"
}
); );
await this.$api.post(pathMap["psReComposingDesignImages"], { } catch {
return;
}
}
const taskId = this.templateBatchArrangeNum;
const templateId = this.templateId;
startLoading();
try {
await this.$api.post(
pathMap["psReComposingDesignImages"],
{
batchArrangeNum: this.templateBatchArrangeNum, batchArrangeNum: this.templateBatchArrangeNum,
templateWidth: this.radio templateWidth: this.radio
}); },
{ skipLoading: true }
);
} catch (error) {
console.warn("排版请求超时:", error.message);
}
endLoading();
this.dialogVisible = false;
const task = {
id: taskId,
batchArrangeNum: taskId,
templateId: templateId,
step: "composing",
progress: "正在检查排版状态...",
dismissTimer: null
};
this.composingTasks = this.composingTasks.filter(t => t.id !== taskId);
this.composingTasks.push(task);
const batch = await this.fetchBatchByNo(taskId);
this.checkTaskStatus(task, batch);
this.fetchBatchList(this.searchForm);
},
async fetchBatchByNo(batchArrangeNum) {
try {
const res = await this.$api.post(
pathMap["productionSoftware"],
{ currentPage: 1, pageSize: 1, batchArrangeNum },
{ skipLoading: true }
);
const list = res.code === 200 ? res.data.records || [] : [];
return list[0] || null;
} catch {
return null;
}
},
checkTaskStatus(task, batch) {
if (batch && [3, 5].includes(batch.layoutStatus)) {
task.step = "downloading";
task.progress = "排版完成,正在下载素材...";
this.doComposingDownload(task.id);
} else if (batch && batch.layoutStatus === 4) {
task.step = "error";
task.progress = "排版失败:" + (batch.failReason || "未知原因");
} else { } else {
await this.$api.post(pathMap["psReComposingDesignImages"], { task.progress = "排版处理中,等待完成后自动下载...";
batchArrangeNum: this.templateBatchArrangeNum, this.ensureComposingPoll();
templateWidth: this.radio
});
} }
const { data } = await this.$api.post( },
pathMap["podOrderBatchDownload"],
{ getTask(taskId) {
id: this.templateId return this.composingTasks.find(t => t.id === taskId);
},
setTaskDone(taskId, progress) {
const task = this.getTask(taskId);
if (!task) return;
task.step = "done";
task.progress = progress;
task.dismissTimer = setTimeout(() => this.removeTask(taskId), 5000);
},
removeTask(taskId) {
const task = this.getTask(taskId);
if (task) clearTimeout(task.dismissTimer);
this.composingTasks = this.composingTasks.filter(t => t.id !== taskId);
if (!this.composingTasks.some(t => t.step === "composing")) {
this.stopComposingPoll();
} }
},
ensureComposingPoll() {
if (this.composingPollTimer) return;
this.composingPollTimer = setInterval(
() => this.pollComposingStatus(),
15000
); );
},
stopComposingPoll() {
if (this.composingPollTimer) {
clearInterval(this.composingPollTimer);
this.composingPollTimer = null;
}
},
async pollComposingStatus() {
const polling = this.composingTasks.filter(t => t.step === "composing");
if (polling.length === 0) {
this.stopComposingPoll();
return;
}
try {
for (const task of polling) {
const batch = await this.fetchBatchByNo(task.batchArrangeNum);
this.checkTaskStatus(task, batch);
}
if (!this.composingTasks.some(t => t.step === "composing")) {
this.stopComposingPoll();
}
} catch (err) {
console.error("轮询排版状态失败", err);
}
},
const res = await submitTypesettingDownload({ async doComposingDownload(taskId) {
const task = this.getTask(taskId);
if (!task) return;
try {
this.TypeDownloading = true;
const { data } = await this.$api.post(
pathMap["podOrderBatchDownload"],
{ id: task.templateId },
{ skipLoading: true }
);
await submitTypesettingDownload({
urlStr: data.data.spUrl, urlStr: data.data.spUrl,
targetPath: path.join( targetPath: path.join(
getDTFSetting().downloadDir, getDTFSetting().downloadDir,
`批次号:${this.templateBatchArrangeNum}`, `批次号:${task.batchArrangeNum}`,
"手动排版素材" "手动排版素材"
), ),
batchArrangeNum: this.templateBatchArrangeNum batchArrangeNum: task.batchArrangeNum
}); });
console.log(res); task.progress = "素材下载中...";
if (res.code == 200) {
this.$message(res.msg);
} else {
this.TypeDownloading = false;
this.$message.error(res.msg);
}
this.dialogVisible = false;
this.fetchBatchList(this.searchForm);
} catch (error) { } catch (error) {
console.log(error); console.error(error);
this.TypeDownloading = false; this.TypeDownloading = false;
if (task) {
task.step = "error";
task.progress = "下载失败:" + (error.message || "未知错误");
}
} }
}, },
...@@ -355,9 +467,7 @@ export default { ...@@ -355,9 +467,7 @@ export default {
), ),
batchArrangeNum: value batchArrangeNum: value
}); });
if (res.code == 200) { if (res.code !== 200) {
this.$message(res.msg);
} else {
this.isDownloading = false; this.isDownloading = false;
this.$message.error(res.msg); this.$message.error(res.msg);
} }
...@@ -379,6 +489,20 @@ export default { ...@@ -379,6 +489,20 @@ export default {
if (!status.isRunning && status.result) { if (!status.isRunning && status.result) {
const { success, failed } = status.result; const { success, failed } = status.result;
const { currentBatchNo } = status; const { currentBatchNo } = status;
const task =
type === "typesetting" &&
this.composingTasks.find(t => t.batchArrangeNum === currentBatchNo);
if (task) {
const msg = failed.length
? `下载完成:成功 ${success.length} 个,失败 ${failed.length} 个`
: `下载完成:成功 ${success.length} 个文件`;
this.setTaskDone(task.id, msg);
this.fetchBatchList(this.searchForm);
return;
}
this.$message.success( this.$message.success(
`批次号:${currentBatchNo},下载完成:成功 ${success.length} 个,失败 ${failed.length} 个` `批次号:${currentBatchNo},下载完成:成功 ${success.length} 个,失败 ${failed.length} 个`
); );
...@@ -388,6 +512,18 @@ export default { ...@@ -388,6 +512,18 @@ export default {
} }
}, },
stepActive(task) {
if (task.step === "composing") return 0;
if (task.step === "downloading") return 1;
if (task.step === "done") return 3;
return task.progress.includes("排版") ? 0 : 1;
},
stepStatus(task) {
if (task.step === "error") return "error";
if (task.step === "done") return "success";
return "process";
},
/** /**
* 同步当前状态 * 同步当前状态
*/ */
...@@ -507,6 +643,32 @@ export default { ...@@ -507,6 +643,32 @@ export default {
<el-button type="primary" @click="submit">确 定</el-button> <el-button type="primary" @click="submit">确 定</el-button>
</span> </span>
</el-dialog> </el-dialog>
<!-- 排版进度浮层(多任务) -->
<transition-group name="composing-slide" tag="div" class="composing-panels">
<div
v-for="task in composingTasks"
:key="task.id"
class="composing-progress-panel"
>
<div class="cp-header">
<span class="cp-batch">批次号:{{ task.batchArrangeNum }}</span>
<i class="el-icon-close cp-close" @click="removeTask(task.id)"></i>
</div>
<el-steps
:active="stepActive(task)"
:process-status="stepStatus(task)"
finish-status="success"
size="mini"
class="cp-steps"
>
<el-step title="排版"></el-step>
<el-step title="下载"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<div v-if="task.progress" class="cp-msg">{{ task.progress }}</div>
</div>
</transition-group>
</div> </div>
</template> </template>
...@@ -541,4 +703,70 @@ export default { ...@@ -541,4 +703,70 @@ export default {
filter: grayscale(100%); filter: grayscale(100%);
opacity: 0.3; opacity: 0.3;
} }
.composing-panels {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 2001;
display: flex;
flex-direction: column-reverse;
gap: 10px;
}
.composing-progress-panel {
width: 360px;
background: #fff;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
padding: 14px 16px 10px;
}
.cp-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.cp-batch {
font-size: 13px;
font-weight: 600;
color: #303133;
}
.cp-close {
cursor: pointer;
color: #909399;
font-size: 14px;
&:hover {
color: #606266;
}
}
.cp-steps {
margin-bottom: 6px;
}
::v-deep .cp-steps {
.el-step__title {
font-size: 12px;
line-height: 20px;
}
.el-step__icon {
width: 18px;
height: 18px;
}
.el-step__icon-inner {
font-size: 10px;
}
}
.cp-msg {
font-size: 12px;
color: #909399;
padding-left: 2px;
}
.composing-slide-enter-active,
.composing-slide-leave-active {
transition: all 0.3s ease;
}
.composing-slide-enter,
.composing-slide-leave-to {
opacity: 0;
transform: translateY(20px);
}
</style> </style>
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