diff --git a/track-uniapp/src/pages/scan/detail.vue b/track-uniapp/src/pages/scan/detail.vue
index 4640b66..c7087f9 100644
--- a/track-uniapp/src/pages/scan/detail.vue
+++ b/track-uniapp/src/pages/scan/detail.vue
@@ -103,6 +103,10 @@
@tap="handleTaskAction({ task: activeTask, type: 'receive' })">
✅ 接收任务
+
@@ -235,50 +239,69 @@
-
+
-
+
-
-
- 下一道工序 *
-
-
-
- {{ transferForm.next_task_name || '请选择下一道工序' }}
-
- ▾
-
-
+
+
+
+
+
+
+ 工序 *
+ onBranchProcessChange(idx, e)">
+
+
+ {{ branch.task_name || '请选择工序' }}
+
+ ▾
+
+
+
+
+
+
+ 接收人 *
+ onBranchUserChange(idx, e)">
+
+
+ {{ branchUserName(idx) || '请选择接收人' }}
+
+ ▾
+
+
+
+
+
+ 📦 入库分支 — 直接归档,无需指定接收人
+
-
-
- 接收人 *
-
-
-
- {{ selectedUserName || '请选择接收人' }}
-
- ▾
-
-
+
+
+
+
+
+
+
+
+ 将创建 {{ transferForm.branches.length }} 个并行任务:
+
+ {{ i + 1 }}. {{ b.task_name || '—' }} → {{ branchUserName(i) || (isBranchWarehouse(i) ? '仓库' : '未选') }}
+
-
-
- 📦 该任务将直接入库,任务状态变为「已入库」
-
-
-
-
-
- {{ isWarehouse ? '产品将入库并从个人待办中移除' : '将创建 1 个「' + transferForm.next_task_name + '」任务指派给 ' + (selectedUserName || '—') }}
-
@@ -334,7 +357,7 @@ export default {
actionPopup: { visible: false, type: "", task: null },
actionLoading: false,
rejectReason: "",
- transferForm: { next_task_name: "", assignees: [], selectedUserId: "", warehouse: false, note: "" },
+ transferForm: { branches: [{ task_name: "", assignee_id: "" }], note: "" },
};
},
computed: {
@@ -346,12 +369,12 @@ export default {
if (!this.currentUser) return true;
return this.currentUser.username === this.recordPopup.task.assignee_id;
},
- selectedUserName() {
- const u = this.userOptions.find(u => u.id === this.transferForm.selectedUserId);
- return u ? u.name : "";
- },
- isWarehouse() {
- return this.transferForm.next_task_name === "🏭 入库 (virtual_warehouse)";
+ canSubmitTransfer() {
+ return this.transferForm.branches.every(b => {
+ if (!b.task_name) return false;
+ if (b.task_name === "🏭 入库 (virtual_warehouse)") return true;
+ return !!b.assignee_id;
+ });
},
activeTask() {
// 查找树中第一个 WIP 或 PENDING 任务作为底部 Footer 的操作目标
@@ -658,7 +681,7 @@ export default {
this.actionPopup = { visible: true, type, task };
this.rejectReason = "";
- this.transferForm = { next_task_name: "", assignees: [], selectedUserId: "", warehouse: false, note: "" };
+ this.transferForm = { branches: [{ task_name: "", assignee_id: "" }], note: "" };
},
handleViewRecords(task) {
uni.navigateTo({ url: `/pages/scan/records?taskId=${task.id}` });
@@ -683,28 +706,46 @@ export default {
this.doQuery(this.product.serial_number);
} catch {} finally { this.actionLoading = false; }
},
- onProcessChange(e) {
- this.transferForm.next_task_name = this.processOptions[e.detail.value];
- },
- onUserChange(e) {
- const user = this.userOptions[e.detail.value];
- if (user) {
- this.transferForm.selectedUserId = user.id;
- this.transferForm.assignees = [user.id];
+ // ---- 多分支操作 ----
+ addBranch() {
+ if (this.transferForm.branches.length >= 5) {
+ uni.showToast({ title: "最多 5 个并行分支", icon: "none" }); return;
}
+ this.transferForm.branches.push({ task_name: "", assignee_id: "" });
+ },
+ removeBranch(idx) {
+ if (this.transferForm.branches.length <= 1) return;
+ this.transferForm.branches.splice(idx, 1);
+ },
+ onBranchProcessChange(idx, e) {
+ this.transferForm.branches[idx].task_name = this.processOptions[e.detail.value];
+ // 切换工序时清空接收人
+ this.transferForm.branches[idx].assignee_id = "";
+ },
+ onBranchUserChange(idx, e) {
+ const user = this.userOptions[e.detail.value];
+ if (user) this.transferForm.branches[idx].assignee_id = user.id;
+ },
+ isBranchWarehouse(idx) {
+ return this.transferForm.branches[idx].task_name === "🏭 入库 (virtual_warehouse)";
+ },
+ branchUserName(idx) {
+ const u = this.userOptions.find(u => u.id === this.transferForm.branches[idx].assignee_id);
+ return u ? u.name : "";
},
async doTransfer() {
this.actionLoading = true;
- const finalAssignees = this.isWarehouse
- ? ["virtual_warehouse"]
- : [...this.transferForm.assignees];
+ const branches = this.transferForm.branches.filter(b => b.task_name);
try {
await post(`/tasks/${this.actionPopup.task.id}/transfer`, {
- next_assignees: finalAssignees,
- next_task_name: this.transferForm.next_task_name.trim(),
+ next_tasks: branches.map(b => ({
+ task_name: b.task_name,
+ assignees: b.task_name === "🏭 入库 (virtual_warehouse)"
+ ? ["virtual_warehouse"] : [b.assignee_id],
+ })),
note: this.transferForm.note.trim() || undefined,
});
- uni.showToast({ title: this.isWarehouse ? "已入库" : "转交成功", icon: "success" });
+ uni.showToast({ title: `已派发 ${branches.length} 个分支`, icon: "success" });
this.closeActionPopup();
this.doQuery(this.product.serial_number);
} catch {} finally { this.actionLoading = false; }
@@ -793,6 +834,14 @@ export default {
.warehouse-hint { font-size: 13px; background: #ede9fe; color: #7c3aed; padding: 10px 14px; border-radius: 10px; margin: 8px 0; text-align: center; }
.preview-hint { font-size: 12px; background: #f0fdf4; color: #16a34a; padding: 8px 10px; border-radius: 8px; margin: 6px 0; }
+/* 多分支裂变 */
+.branch-item { background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 10px; padding: 12px; margin-bottom: 10px; }
+.branch-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
+.branch-label { font-size: 13px; font-weight: 700; color: #374151; }
+.branch-del { font-size: 12px; color: #ef4444; font-weight: 600; padding: 2px 8px; }
+.btn-add-branch { width: 100%; height: 40px; border: 2px dashed #93c5fd; border-radius: 10px; background: #eff6ff; color: #2563eb; font-size: 14px; font-weight: 700; line-height: 40px; margin: 4px 0; }
+.btn-add-branch::after { border: none; }
+
/* Picker & 表单 */
.field-label { font-size: 14px; font-weight: 600; color: #374151; margin-top: 10px; margin-bottom: 4px; }
.required { color: #ef4444; }
@@ -826,6 +875,7 @@ export default {
.footer-transfer { background: #dcfce7; color: #16a34a; }
.footer-record { background: #eff6ff; color: #2563eb; }
.footer-receive { background: #dbeafe; color: #1d4ed8; }
+.footer-reject { background: #fce4ec; color: #dc2626; }
/* Picker 选择器 */
.form-item { margin: 10px 0; }