浏览代码

feat(mkl): add contract page initialization and debounce

malk 3 周之前
父节点
当前提交
c7e9f806b1
共有 2 个文件被更改,包括 220 次插入0 次删除
  1. 94 0
      doc/mankalong-contract-page-sync.js
  2. 126 0
      src/sample/mkl.js

+ 94 - 0
doc/mankalong-contract-page-sync.js

@@ -0,0 +1,94 @@
+/**
+ * 曼卡龙合同页面同步区(可复制到各合同页面 JS)。
+ *
+ * 使用说明:
+ * 1. 按当前页面修改 getMankalongContractFieldIds() 中的组件 ID。
+ * 2. didMount 中调用 initMankalongContractPage()。
+ * 3. “生成合同”按钮绑定 onClickContractGenerate。
+ * 4. “合同确认”按钮绑定 onClickContractConfirm。
+ *
+ * 依赖:页面已加载 mjs.corp.mkl(https://mc.cloudpure.cn/mjs/mkl/mjs.min.js)。
+ */
+
+/**
+ * @returns {Object} 当前合同页面固定配置
+ */
+function getMankalongContractPageConfig() {
+  return {
+    formUuid: 'FORM-BBFA15D85B2E4E8D832C2F0FE49CAF782GO3',
+    subDirectory: '工程类',
+    dingOrgId: '908563201',
+    corpId: 'ding3735baea6bea68ac24f2f5cc6abecb85',
+  };
+}
+
+/**
+ * @returns {Object} 当前合同页面组件 ID
+ */
+function getMankalongContractFieldIds() {
+  return {
+    uniqueId: 'textField_mte3gh61',
+    contractNo: 'textField_mrishceq',
+    mode: 'radioField_mryiusal',
+    type: 'textField_mspzgras',
+    masterNo: 'textField_mrylbq28',
+    name: 'textField_mryko9bh',
+    attachment: 'attachmentField_msv7rz7m',
+    generateButton: 'button_msiiyhct',
+    confirmButton: 'button_mtfaz1tq',
+  };
+}
+
+/**
+ * @returns {Promise<Object>} 初始化后的合同页面状态
+ */
+export async function initMankalongContractPage() {
+  await this._mklLoad();
+  return mjs.corp.mkl.initContractPage({
+    componentIds: getMankalongContractFieldIds(),
+  });
+}
+
+/**
+ * @returns {Promise<*>} 合同预览生成结果
+ */
+export async function onClickContractGenerate() {
+  await this._mklLoad();
+  const config = getMankalongContractPageConfig();
+  const ids = getMankalongContractFieldIds();
+  return mjs.corp.mkl.runContractGenerate({
+    componentIds: ids,
+    generateContract: () => mjs.corp.mkl.generateSubFormImages({
+      formUuid: config.formUuid,
+      type: 'preview',
+      componentIds: ids,
+      dingOrgId: config.dingOrgId,
+      corpId: config.corpId,
+    }),
+  });
+}
+
+/**
+ * @returns {Promise<Object|null>} 合同确认结果
+ */
+export async function onClickContractConfirm() {
+  await this._mklLoad();
+  const config = getMankalongContractPageConfig();
+  const ids = getMankalongContractFieldIds();
+  return mjs.corp.mkl.runContractConfirm({
+    componentIds: ids,
+    subDirectory: config.subDirectory,
+    generateMode: 'generate',
+    allowMissingInstanceId: true,
+    generateContract: (params) => this.generateMankalongContractFile(params),
+  });
+}
+
+/**
+ * @returns {void} 清理合同页面定时器
+ */
+export function didUnmount() {
+  if (window.mjs && mjs.corp && mjs.corp.mkl) {
+    mjs.corp.mkl.disposeContractPage();
+  }
+}

+ 126 - 0
src/sample/mkl.js

@@ -78,6 +78,29 @@ function _safeSetValue (componentId, value) {
   if (component && typeof component.setValue === "function") component.setValue(value);
 }
 
+function _contractState (page) {
+  if (!page.__mankalongContractState) {
+    page.__mankalongContractState = {
+      generated: false,
+      generating: false,
+      confirming: false,
+      resetTimer: null,
+    };
+  }
+  return page.__mankalongContractState;
+}
+
+function _setButtonBehavior (page, componentId, behavior) {
+  if (!componentId) return;
+  const button = page.$(componentId);
+  if (button && typeof button.setBehavior === "function") button.setBehavior(behavior);
+}
+
+function _normalizeError (error, fallback) {
+  if (error instanceof Error) return error;
+  return new Error(error && (error.message || error.msg) || String(error || fallback));
+}
+
 function _formDataFromFieldIds (fieldIds) {
   return (Array.isArray(fieldIds) ? fieldIds : []).map((fieldId) => ({
     structKey: fieldId,
@@ -308,6 +331,109 @@ export default {
     if (iframeUrl && ids.previewFrame) page.$(ids.previewFrame).set("src", iframeUrl);
   },
 
+  /**
+   * 初始化曼卡龙合同页面状态。
+   * 提交页延迟清空复制流程可能带入的合同编号和合同正文,确认按钮默认禁用。
+   * @param {Object} options 页面组件 ID
+   * @returns {Object} 当前页面合同状态
+   */
+  initContractPage (options = {}) {
+    const page = _page();
+    const ids = options.componentIds || {};
+    const state = _contractState(page);
+    state.generated = false;
+    state.generating = false;
+    state.confirming = false;
+    if (state.resetTimer) clearTimeout(state.resetTimer);
+    state.resetTimer = null;
+
+    _setButtonBehavior(page, ids.generateButton, "NORMAL");
+    _setButtonBehavior(page, ids.confirmButton, "DISABLED");
+
+    if (typeof mjs !== "undefined" && String(mjs.env) === "0") {
+      state.resetTimer = setTimeout(() => {
+        _safeSetValue(ids.contractNo, "");
+        _safeSetValue(ids.attachment, []);
+        state.generated = false;
+        _setButtonBehavior(page, ids.confirmButton, "DISABLED");
+        state.resetTimer = null;
+      }, 800);
+    }
+    return state;
+  },
+
+  /**
+   * 清理合同页面初始化定时器。
+   * @returns {void}
+   */
+  disposeContractPage () {
+    const page = _page();
+    const state = page.__mankalongContractState;
+    if (state && state.resetTimer) clearTimeout(state.resetTimer);
+    if (state) state.resetTimer = null;
+  },
+
+  /**
+   * 合同生成按钮防抖:请求期间禁用生成和确认,成功后解锁确认。
+   * @param {Object} options 生成参数
+   * @returns {Promise<*>} 生成结果
+   */
+  async runContractGenerate (options = {}) {
+    const page = _page();
+    const ids = options.componentIds || {};
+    const state = _contractState(page);
+    if (state.generating || state.confirming) return null;
+    if (typeof options.generateContract !== "function") {
+      throw new Error("必须传入合同生成回调");
+    }
+
+    state.generating = true;
+    _setButtonBehavior(page, ids.generateButton, "DISABLED");
+    _setButtonBehavior(page, ids.confirmButton, "DISABLED");
+    try {
+      const generated = await options.generateContract.call(page, options);
+      const fileUrl = typeof generated === "string"
+        ? generated
+        : generated && (generated.downloadUrl || generated.fileUrl || generated.url);
+      if (!fileUrl) throw new Error("合同生成接口未返回文件地址");
+      state.generated = true;
+      _setButtonBehavior(page, ids.confirmButton, "NORMAL");
+      page.utils.toast({ type: "success", title: "合同生成成功,可进行合同确认" });
+      return generated;
+    } catch (error) {
+      state.generated = false;
+      _setButtonBehavior(page, ids.confirmButton, "DISABLED");
+      const normalizedError = _normalizeError(error, "合同生成失败");
+      page.utils.toast({ type: "error", title: normalizedError.message });
+      throw normalizedError;
+    } finally {
+      state.generating = false;
+      _setButtonBehavior(page, ids.generateButton, "NORMAL");
+    }
+  },
+
+  /**
+   * 合同确认按钮防抖:仅允许合同生成成功后执行一次确认请求。
+   * @param {Object} options 确认参数
+   * @returns {Promise<Object|null>} 合同确认结果
+   */
+  async runContractConfirm (options = {}) {
+    const page = _page();
+    const ids = options.componentIds || {};
+    const state = _contractState(page);
+    if (state.generating || state.confirming) return null;
+    if (!state.generated) throw new Error("请先点击合同生成并等待生成成功");
+
+    state.confirming = true;
+    _setButtonBehavior(page, ids.confirmButton, "DISABLED");
+    try {
+      return await this.confirmContract(options);
+    } finally {
+      state.confirming = false;
+      _setButtonBehavior(page, ids.confirmButton, "NORMAL");
+    }
+  },
+
   /**
    * 合同确认完整流程:合同号 → 原合同生成回调 → OSS → 附件回写。
    * @param {Object} options 流程参数