|
|
|
|
@ -145,12 +145,127 @@ export default {
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
flows: {},
|
|
|
|
|
tempFlowList: []
|
|
|
|
|
tempFlowList: [],
|
|
|
|
|
// fill_flow_title 自动填充 watcher(监听组件内部 form,而不是父组件)
|
|
|
|
|
_unwatchFillFlowTitle: null,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
getToken,
|
|
|
|
|
request,
|
|
|
|
|
_parseMultiValue(raw) {
|
|
|
|
|
if (raw === null || raw === undefined) return [];
|
|
|
|
|
if (Array.isArray(raw)) return raw.map((v) => String(v).trim()).filter(Boolean);
|
|
|
|
|
const s = String(raw).trim();
|
|
|
|
|
if (!s) return [];
|
|
|
|
|
// 后端常见:数组被 filterRequestColumns 拼成 "|";部分场景可能为 ","(兼容)
|
|
|
|
|
const parts = s.includes("|") ? s.split("|") : (s.includes(",") ? s.split(",") : [s]);
|
|
|
|
|
return parts.map((v) => String(v).trim()).filter(Boolean);
|
|
|
|
|
},
|
|
|
|
|
_getOptionLabelFromSelectionModelItems(field, value) {
|
|
|
|
|
const items = field?.selection_model_items;
|
|
|
|
|
if (!Array.isArray(items) || items.length === 0) return null;
|
|
|
|
|
const v = String(value);
|
|
|
|
|
const hit = items.find((it) => String(it?.id ?? it?.value ?? it?.key ?? "") === v) || null;
|
|
|
|
|
if (!hit) return null;
|
|
|
|
|
return hit?.name ?? hit?.label ?? hit?.title ?? (hit?.id !== undefined ? String(hit.id) : null);
|
|
|
|
|
},
|
|
|
|
|
_getOptionLabelFromStub(field, value) {
|
|
|
|
|
const stub = field?.stub;
|
|
|
|
|
if (!stub) return null;
|
|
|
|
|
const lines = String(stub).split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
|
|
|
const v = String(value);
|
|
|
|
|
// 目前 stub 主要是“每行一个选项”,值=显示文本
|
|
|
|
|
const hit = lines.find((line) => line === v) || null;
|
|
|
|
|
return hit;
|
|
|
|
|
},
|
|
|
|
|
_formatSelectFillValue(field, rawValue) {
|
|
|
|
|
const values = this._parseMultiValue(rawValue);
|
|
|
|
|
if (values.length === 0) return "";
|
|
|
|
|
// 多选:label只出现一次(字段label - value1、value2)
|
|
|
|
|
if (values.length > 1) {
|
|
|
|
|
return `${field.label || field.name} - ${values.join("、")}`;
|
|
|
|
|
}
|
|
|
|
|
// 单选:选项label - value
|
|
|
|
|
const value = values[0];
|
|
|
|
|
const optionLabel =
|
|
|
|
|
this._getOptionLabelFromSelectionModelItems(field, value) ||
|
|
|
|
|
this._getOptionLabelFromStub(field, value) ||
|
|
|
|
|
value;
|
|
|
|
|
return `${optionLabel} - ${value}`;
|
|
|
|
|
},
|
|
|
|
|
setupFillFlowTitleWatcher() {
|
|
|
|
|
try {
|
|
|
|
|
if (typeof this._unwatchFillFlowTitle === "function") {
|
|
|
|
|
this._unwatchFillFlowTitle();
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// ignore
|
|
|
|
|
}
|
|
|
|
|
this._unwatchFillFlowTitle = null;
|
|
|
|
|
|
|
|
|
|
// 只在新建流程时生效(有 flow_id 代表待办/编辑/详情)
|
|
|
|
|
if (this.$route?.query?.flow_id) return;
|
|
|
|
|
|
|
|
|
|
const list = Array.isArray(this.fields) ? this.fields : [];
|
|
|
|
|
const allowedTypes = new Set(["text", "textarea", "select"]);
|
|
|
|
|
const fillField = list.find((f) => Number(f?.fill_flow_title) === 1 && allowedTypes.has(f?.type) && f?.name);
|
|
|
|
|
if (!fillField) return;
|
|
|
|
|
|
|
|
|
|
const fieldName = fillField.name;
|
|
|
|
|
this._unwatchFillFlowTitle = this.$watch(
|
|
|
|
|
() => (this.form ? this.form[fieldName] : undefined),
|
|
|
|
|
(newVal) => {
|
|
|
|
|
// 保留 isFirstNode 判断
|
|
|
|
|
if (!this.isFirstNode || this.$route?.query?.flow_id) return;
|
|
|
|
|
let v = "";
|
|
|
|
|
if (fillField.type === "select") {
|
|
|
|
|
v = this._formatSelectFillValue(fillField, newVal);
|
|
|
|
|
} else {
|
|
|
|
|
v = newVal === null || newVal === undefined ? "" : String(newVal).trim();
|
|
|
|
|
}
|
|
|
|
|
if (!v) return;
|
|
|
|
|
this.$set(this.form, "flow_title", v);
|
|
|
|
|
},
|
|
|
|
|
{ immediate: true }
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
// 给自定义脚本注册的事件监听加保护,避免脚本内部抛错导致页面整体报错
|
|
|
|
|
installSafeEventListenerGuard() {
|
|
|
|
|
if (window.__oa_safe_listener_guard_installed) return;
|
|
|
|
|
window.__oa_safe_listener_guard_installed = true;
|
|
|
|
|
|
|
|
|
|
const map = new WeakMap();
|
|
|
|
|
const origAdd = EventTarget && EventTarget.prototype && EventTarget.prototype.addEventListener;
|
|
|
|
|
const origRemove = EventTarget && EventTarget.prototype && EventTarget.prototype.removeEventListener;
|
|
|
|
|
if (!origAdd || !origRemove) return;
|
|
|
|
|
|
|
|
|
|
EventTarget.prototype.addEventListener = function (type, listener, options) {
|
|
|
|
|
if (typeof listener === "function") {
|
|
|
|
|
let wrapped = map.get(listener);
|
|
|
|
|
if (!wrapped) {
|
|
|
|
|
wrapped = function (...args) {
|
|
|
|
|
try {
|
|
|
|
|
return listener.apply(this, args);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("[OA Custom Script] event listener error:", e);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
map.set(listener, wrapped);
|
|
|
|
|
}
|
|
|
|
|
return origAdd.call(this, type, wrapped, options);
|
|
|
|
|
}
|
|
|
|
|
return origAdd.call(this, type, listener, options);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
EventTarget.prototype.removeEventListener = function (type, listener, options) {
|
|
|
|
|
if (typeof listener === "function") {
|
|
|
|
|
const wrapped = map.get(listener);
|
|
|
|
|
return origRemove.call(this, type, wrapped || listener, options);
|
|
|
|
|
}
|
|
|
|
|
return origRemove.call(this, type, listener, options);
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
async validate() {
|
|
|
|
|
this.customValidate()
|
|
|
|
|
const $elForm = this.$refs['elForm']
|
|
|
|
|
@ -184,6 +299,8 @@ export default {
|
|
|
|
|
watch: {
|
|
|
|
|
originalForm(newVal) {
|
|
|
|
|
this.form = deepCopy(newVal)
|
|
|
|
|
// 原始表单更新后,重新绑定 watcher
|
|
|
|
|
this.$nextTick(() => this.setupFillFlowTitleWatcher());
|
|
|
|
|
// let copyForm = deepCopy(newVal);
|
|
|
|
|
// for (let key in copyForm) {
|
|
|
|
|
// Object.defineProperty(this.form, key, {
|
|
|
|
|
@ -194,12 +311,20 @@ export default {
|
|
|
|
|
// })
|
|
|
|
|
// }
|
|
|
|
|
},
|
|
|
|
|
fields: {
|
|
|
|
|
handler() {
|
|
|
|
|
// 字段配置变化(含 fill_flow_title)时,重新绑定 watcher
|
|
|
|
|
this.$nextTick(() => this.setupFillFlowTitleWatcher());
|
|
|
|
|
},
|
|
|
|
|
deep: true
|
|
|
|
|
},
|
|
|
|
|
scriptContent(newVal) {
|
|
|
|
|
if (newVal) {
|
|
|
|
|
try {
|
|
|
|
|
// 使用 $nextTick 确保 DOM 已经渲染完成
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
try {
|
|
|
|
|
this.installSafeEventListenerGuard();
|
|
|
|
|
new Function(newVal).bind(this)();
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error('脚本执行错误:', err);
|
|
|
|
|
|