diff --git a/changelog.md b/changelog.md
index 8e97940c..e8cf8452 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,7 @@
+## 3.1.2026072315
+
+- fix: 问题修复
+ - 工艺路线表单残留问题根治:xtSelect外部清空值时同步清空显示文字(残留主因);画布/右侧新增弹框加key每次打开强制重建实例;route_form编辑时sort不再被count+1覆盖;无routeId不再全量拉辅料 [caoqianming]
## 3.1.2026072314
- fix: 问题修复
diff --git a/src/components/xtFlowEditor.vue b/src/components/xtFlowEditor.vue
index 4c871628..90c93998 100644
--- a/src/components/xtFlowEditor.vue
+++ b/src/components/xtFlowEditor.vue
@@ -61,6 +61,8 @@
:default-viewport="{ zoom: 0.9 }"
:min-zoom="0.2"
:max-zoom="2"
+ :connection-radius="8"
+ :connect-on-click="false"
:nodes-draggable="true"
:nodes-connectable="!readonly"
:elements-selectable="true"
@@ -87,12 +89,14 @@
-
+
@@ -141,6 +145,8 @@ export default {
edges: [],
count: 0,
dialogVisible: false,
+ dialogSeq: 0,
+ formPrefill: null,
// 左侧物料面板
matType: "30",
matKeyword: "",
@@ -151,6 +157,7 @@ export default {
// 连线手势内部状态
connectSource: null,
connectMade: false,
+ connectStartPos: null,
// 仅初次加载自动适配一次,避免编辑时视图跳动
hasFitted: false,
};
@@ -282,9 +289,12 @@ export default {
if (pid) routeNodeIds.add(pid);
this.seedNodes = this.seedNodes.filter((s) => !routeNodeIds.has(s.id));
+ const prevCount = this.nodes.length;
this.edges = edges;
this.nodes = layoutGraph(routeNodes.concat(this.seedNodes), edges);
this.syncStore();
+ // 节点增减后 dagre 会整体重排,重新适配视野,避免“看着是空白其实有节点”导致拉线误吸附
+ if (this.hasFitted && this.nodes.length !== prevCount) this.doFit();
},
/** 把本地 nodes/edges 命令式同步到 Vue Flow store(先节点后边,避免边找不到端点) */
@@ -374,11 +384,18 @@ export default {
onConnectStart(params) {
this.connectSource = (params && (params.nodeId || params.source)) || null;
this.connectMade = false;
+ const oe = params && params.event;
+ this.connectStartPos = oe && oe.clientX != null ? { x: oe.clientX, y: oe.clientY } : null;
},
/** 连到已有节点:新建一条 Route,预填输入/输出物料 */
onConnect(conn) {
this.connectMade = true;
if (this.readonly) return;
+ // 误吸附保护:吸回起点自身或目标无效时,按“拉到空白”处理,只带输入
+ if (!conn.target || conn.target === conn.source) {
+ this.openAddFrom(conn.source);
+ return;
+ }
const src = this.nodes.find((n) => n.id === conn.source);
const tgt = this.nodes.find((n) => n.id === conn.target);
// 注意:id 为雪花大整数,必须保持字符串,切勿 Number() 否则精度丢失
@@ -390,16 +407,28 @@ export default {
});
},
/** 拉线到空白处:新建工序,输出物料留空由后端自动生成下一节点 */
- onConnectEnd() {
+ onConnectEnd(evt) {
const src = this.connectSource;
const made = this.connectMade;
+ const startPos = this.connectStartPos;
this.connectSource = null;
this.connectMade = false;
+ this.connectStartPos = null;
if (this.readonly || made || !src) return;
- const node = this.nodes.find((n) => n.id === src);
+ // 单纯点击手柄(几乎无位移)不算拉线,不弹新增表单
+ const oe = evt && evt.clientX != null ? evt : evt && evt.event;
+ if (startPos && oe && oe.clientX != null) {
+ const dist = Math.hypot(oe.clientX - startPos.x, oe.clientY - startPos.y);
+ if (dist < 8) return;
+ }
+ this.openAddFrom(src);
+ },
+ /** 以某节点为输入新建工序:只带输入物料,其余字段一律默认值 */
+ openAddFrom(srcId) {
+ const node = this.nodes.find((n) => n.id === srcId);
// id 为雪花大整数,保持字符串
this.openForm("add", {
- material_in: src,
+ material_in: srcId,
material_in_name: node ? node.data.label : "",
});
},
@@ -477,12 +506,13 @@ export default {
this.openForm("add", null);
},
- /** 打开单步表单;prefill 为 null 表示纯新增 */
+ /** 打开单步表单;prefill 为 null 表示纯新增。预填经 prop 传入,在表单挂载 open 时一次性应用 */
openForm(mode, prefill) {
+ this.dialogSeq += 1;
+ this.formPrefill = prefill || null;
this.dialogVisible = true;
this.$nextTick(() => {
- const inst = this.$refs.routeForm.open(mode);
- if (prefill) inst.setData(prefill);
+ this.$refs.routeForm.open(mode);
});
},
diff --git a/src/components/xtSelect/index.vue b/src/components/xtSelect/index.vue
index 83405748..8eef005f 100644
--- a/src/components/xtSelect/index.vue
+++ b/src/components/xtSelect/index.vue
@@ -123,8 +123,18 @@ onMounted(() => {
const init = () => {
if (props.label) {
selectLabel.value = props.label;
- } else {
- if (props.multiple) {
+ return;
+ }
+ // 外部把值清空(表单重置/实例复用)时同步清空显示文字,否则输入框会残留上次选择的内容
+ const emptyVal =
+ props.modelValue == null ||
+ props.modelValue === "" ||
+ (Array.isArray(props.modelValue) && props.modelValue.length === 0);
+ if (emptyVal) {
+ selectLabel.value = "";
+ return;
+ }
+ if (props.multiple) {
if (isFixOptions.value) {
selectLabel.value = props.options
.filter((item) =>
@@ -149,7 +159,6 @@ const init = () => {
selectLabel.value = props.obj[props.labelField];
}
}
- }
}
const isFixOptions = ref(false);
diff --git a/src/config/index.js b/src/config/index.js
index 1c57920e..6b7ff619 100644
--- a/src/config/index.js
+++ b/src/config/index.js
@@ -6,7 +6,7 @@ const DEFAULT_CONFIG = {
DASHBOARD_URL: "/dashboard",
//版本号
- APP_VER: "3.1.2026072314",
+ APP_VER: "3.1.2026072315",
//内核版本号
CORE_VER: "1.6.9",
diff --git a/src/views/mtm/route_form.vue b/src/views/mtm/route_form.vue
index 2d620ae0..aefbcd5d 100644
--- a/src/views/mtm/route_form.vue
+++ b/src/views/mtm/route_form.vue
@@ -305,6 +305,8 @@ export default {
props: {
count: { type: Number, default : 0 },
routepack: { type: String, default: "" },
+ // 打开时的预填数据(画布拉线传入):挂载即确定,避免事后setData在任何时序下带入脏数据
+ prefill: { type: Object, default: null },
},
emits: ["success", "closed"],
data() {
@@ -397,6 +399,11 @@ export default {
},
getroutemats(){
let that = this;
+ // 无 routeId(画布拉线预填等新增场景)时不请求,避免拉回全量辅料
+ if (!that.routeId) {
+ that.routemats = [];
+ return;
+ }
that.$API.mtm.routemat.list.req({ route: that.routeId,page: 0}).then((res) => {
that.routemats = res;
});
@@ -498,9 +505,11 @@ export default {
let that = this;
that.mode = mode;
that.resetForm();
+ if (that.prefill) that.setData(that.prefill);
that.visible = true;
that.$nextTick(() => {
- if(that.count){
+ // 仅新增时按现有数量预填排序;编辑时保留 setData 带入的原 sort
+ if(that.count && mode === "add"){
that.form.sort = that.count+1;
}
that.$refs.dialogForm && that.$refs.dialogForm.clearValidate();
diff --git a/src/views/mtm/routepack_form.vue b/src/views/mtm/routepack_form.vue
index 0ea87702..f5806356 100644
--- a/src/views/mtm/routepack_form.vue
+++ b/src/views/mtm/routepack_form.vue
@@ -184,6 +184,7 @@
{
this.$refs.saveDialog.open("add");
});
},
table_edit(row) {
+ this.dialogSeq += 1;
this.dialog.save = true;
this.$nextTick(() => {
this.$refs.saveDialog.open("edit").setData(row);