@steedos-labs/plugin-workflow 3.0.37 → 3.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/designer/dist/assets/{index-DkVFo_s4.js → index-Qp1zkbew.js} +2 -2
- package/designer/dist/index.html +1 -1
- package/main/default/objects/flows/buttons/design_form_layout.button.js +4 -0
- package/main/default/objects/flows/flows.object.yml +4 -0
- package/main/default/routes/am.router.js +4 -0
- package/package.json +1 -1
|
@@ -711,8 +711,8 @@ if (!rows || rows.length === 0) {
|
|
|
711
711
|
form.message.error('请至少添加一行明细');
|
|
712
712
|
return false;
|
|
713
713
|
}
|
|
714
|
-
\`\`\``}const xbe=["设置某个字段的默认值为当前日期","根据条件隐藏某些字段","从API获取数据并填充字段","初始化子表默认行"],ybe=["根据字段值联动显示/隐藏其他字段","当某个字段变化时自动计算另一个字段","级联下拉:选择后动态加载子选项","子表行变化时汇总到主表字段"],wbe=["校验某些字段不能为空","校验数值范围是否合法","提交前调用外部API验证","校验子表至少有一行数据"],Cbe=()=>{const{formName:e,formDescription:t,setFormName:n,setFormDescription:r,fields:a,loadForm:o,toJSON:i}=Jt(),s=Jt(Ue=>Ue.formId),u=Jt(Ue=>Ue.setFormId),f=Jt(Ue=>Ue.viewMode),h=Jt(Ue=>Ue.tableColumns),p=Jt(Ue=>Ue.formEvents),b=d.useMemo(()=>pbe(a),[a]),v=d.useMemo(()=>gbe(b),[b]),w=d.useMemo(()=>vbe(b),[b]),S=d.useMemo(()=>bbe(b),[b]),x=Jt(Ue=>Ue.setFormEvents),C=Jt(Ue=>Ue.selectField),_=Jt(Ue=>Ue.selectedFieldId),$=Jt(Ue=>Ue.setFlowSteps),j=Aw(Ue=>Ue.saveVersion),O=Aw(Ue=>Ue.loadVersions),R=$0(Ue=>Ue.saveVersion),k=$0(Ue=>Ue.loadVersions),P=Xv(Ue=>Ue.backups),A=Xv(Ue=>Ue.loadBackups),T=Xv(Ue=>Ue.createBackup),L=Xv(Ue=>Ue.fetchBackup),V=Xv(Ue=>Ue.removeBackup),q=Jt(Ue=>Ue.isDirty),I=Jt(Ue=>Ue.markClean),B=Jt(Ue=>Ue.canUndo),M=Jt(Ue=>Ue.canRedo),D=Jt(Ue=>Ue.undo),H=Jt(Ue=>Ue.redo);d.useEffect(()=>{const Ue=kt=>{(kt.metaKey||kt.ctrlKey)&&(kt.key==="z"&&!kt.shiftKey?(kt.preventDefault(),D()):(kt.key==="z"&&kt.shiftKey||kt.key==="y")&&(kt.preventDefault(),H()))};return window.addEventListener("keydown",Ue),()=>window.removeEventListener("keydown",Ue)},[D,H]);const Y=d.useRef(null),G=d.useRef(null),[F,K]=d.useState(!1),[Q,X]=d.useState(!1),[Z,te]=d.useState(""),[ne,J]=d.useState(!1),[ae,ue]=d.useState(null),[oe,re]=d.useState(null),[le,ce]=d.useState(!1),[se,fe]=d.useState(""),[xe,Ce]=d.useState(""),[Ae,Le]=d.useState([]),[ye,Me]=d.useState(""),[je,pe]=d.useState(!1),Ne=d.useRef(null),[ke,Ve]=d.useState(""),[Fe,Pe]=d.useState(null),[Ge,$e]=d.useState(""),[Ee,Ke]=d.useState(!1),[Te,He]=d.useState(""),[tt,Ye]=d.useState(""),[Ze,lt]=d.useState([]),[xt,Ot]=d.useState(""),[gt,Lt]=d.useState(!1),Gt=d.useRef(null),[Bt,Pt]=d.useState(!0),[tn,an]=d.useState(!1),[De,Qe]=d.useState(!1),[ct,et]=d.useState(null),[Je,at]=d.useState(!0),[Ct,qt]=d.useState(!1),[Ht,sn]=d.useState(""),[Et,yt]=d.useState(""),[Yt,dn]=d.useState(""),[Nn,Cn]=d.useState(""),[Zt,Dt]=d.useState(!1),[en,mt]=d.useState(!1),[$t,At]=d.useState(!1),[Nt,Tt]=d.useState(null),xn=d.useRef(null),Vn=d.useCallback(Ue=>{const kt=xn.current;if(kt&&document.activeElement===kt.element){const Ft=kt.element,pt=Ft.selectionStart??0,ht=Ft.selectionEnd??0,jn=p[kt.eventKey]||"",In=jn.substring(0,pt)+Ue+jn.substring(ht);x({...p,[kt.eventKey]:In}),requestAnimationFrame(()=>{Ft.focus(),Ft.selectionStart=Ft.selectionEnd=pt+Ue.length})}else navigator.clipboard.writeText(Ue);Tt(Ue),setTimeout(()=>Tt(null),1e3)},[p,x]),[Un,Xt]=d.useState(!1),[nn,hn]=d.useState(!1),[Qn,Kn]=d.useState("desktop"),[ur,Or]=d.useState(""),[dr,tr]=d.useState(!1),[Dr,Zr]=d.useState(""),Nr=d.useRef(void 0),[yn,Kt]=d.useState(null),[_t,wn]=d.useState(null),[Vt,Ut]=d.useState(!1);d.useEffect(()=>{Ne.current?.scrollIntoView({behavior:"smooth"})},[ye]),d.useEffect(()=>{Gt.current?.scrollIntoView({behavior:"smooth"})},[xt]);const fn=d.useCallback((Ue,kt="info")=>{Nr.current&&clearTimeout(Nr.current),ue({message:Ue,type:kt}),Nr.current=setTimeout(()=>ue(null),kt==="error"?4e3:2500)},[]);d.useEffect(()=>{ow()&&FD().then(J);const kt=new URLSearchParams(window.location.search).get("flowId");!kt||!ow()||(X(!0),te(""),LD(kt).then(Ft=>{const{form:pt,flow:ht}=Ft;if(ht&&(Or(ht.name||""),$(ht.current?.steps||[]),wn(ht)),pt&&(Kt(pt),u(pt._id),n(pt.name||""),r(pt.description||""),A(pt._id),pt.current?.fields)){const jn=pt.current.fields;if(pt.current?.version!=="v2")re({rawFields:jn});else{const cn=pt.current?.events||{};o({_id:pt._id,name:pt.name||"",description:pt.description||"",fields:jn,events:cn}),O(pt._id),j(pt._id,jn,cn,"服务器加载","init")}}}).catch(Ft=>{te(Ft?.response?.data?.message||Ft?.message||"加载失败")}).finally(()=>{X(!1)}))},[]);const qn=async()=>{if(!s||!yn){j(s,a,p,"本地保存","manual"),fn("已保存到本地版本(未连接服务器)","info");return}K(!0);try{const Ue=a.map(Ft=>{const pt=Ft,ht=pt.serverField||{};return{...ht,...Ft,fields:Ft.type==="table"?Ft.children:null,code:Ft.name,name:Ft.name,label:Ft.label,type:ht.type||Ft.type,is_required:Ft.required,is_wide:(Ft.colspan||6)>=12,is_list_display:pt.is_list_display??ht.is_list_display,is_searchable:pt.is_searchable??ht.is_searchable,is_multiselect:pt.is_multiselect??ht.is_multiselect,description:Ft.description||ht.description||""}}),kt={...yn,id:yn._id,name:e,description:t,current:{...yn.current,version:"v2",viewMode:f,tableColumns:h,fields:Ue,events:p}};if(delete kt._id,await zR(kt),Vt&&_t)try{const Ft=(_t.current?.steps||[]).map(ht=>{const jn={...ht,id:ht._id||ht.id};return delete jn._id,jn.lines&&(jn.lines=jn.lines.map(In=>{const cn={...In,id:In._id||In.id};return delete cn._id,cn})),jn}),pt={..._t,id:_t._id,current:{..._t.current,steps:Ft}};delete pt._id,await gE(pt),Ut(!1)}catch(Ft){console.warn("Failed to save flow data:",Ft),fn("表单已保存,但流程数据保存失败: "+(Ft?.message||"未知错误"),"error")}j(s,a,p,"手动保存","manual"),I(),fn("保存成功","success")}catch(Ue){fn("保存失败: "+(Ue?.response?.data?.message||Ue?.response?.data||Ue?.message||"未知错误"),"error")}finally{K(!1)}},yr=(Ue,kt)=>{const Ft={},pt={},ht=In=>{for(const cn of In){const fa=cn.code||cn.name,Ln=cn.name||cn.label||cn.code||"";fa&&(pt[Ln]||(pt[Ln]=[]),pt[Ln].push(cn)),cn.type==="table"&&Array.isArray(cn.fields)&&ht(cn.fields),cn.type==="section"&&Array.isArray(cn.fields)&&ht(cn.fields)}};ht(Ue);const jn=In=>{for(const cn of In){const fa=cn.name,Ln=cn.label||cn.name||"";if(fa&&Ln&&pt[Ln])for(const fr of pt[Ln]){const Fo=fr.code||fr.name;Fo&&Fo!==fa&&(Ft[Fo]=fa)}cn.type==="table"&&Array.isArray(cn.children)&&jn(cn.children),cn.type==="section"&&Array.isArray(cn.children)&&jn(cn.children)}};return jn(kt),Ft},Wr=(Ue,kt)=>{if(!Ue||!Array.isArray(Ue))return Ue;const Ft=()=>{const ht=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return ht()+ht()+ht()},pt=Object.keys(kt).length===0;return Ue.map(ht=>{const jn=ht._id||Ft();if(pt)return ht._id?ht:{...ht,_id:jn};if(!ht.permissions||typeof ht.permissions!="object")return{...ht,_id:jn};const In={};for(const[cn,fa]of Object.entries(ht.permissions)){const Ln=kt[cn]||cn;In[Ln]=fa}return{...ht,_id:jn,permissions:In}})},or=async(Ue,kt)=>{if(!_t?.current?.steps)return _t;const Ft=yr(Ue,kt),pt=Wr(_t.current.steps,Ft),ht={..._t,current:{..._t.current,steps:pt}};return wn(ht),$(pt),Ut(!0),ht},Qr=(Ue,kt)=>{const Ft=JSON.stringify(Ue,null,2);return["请将以下旧版表单字段完整升级为新版 v2 格式,要求如下:","1. 字段名称(name)使用英文小写字母+下划线的命名规范,不要使用中文或特殊字符;","2. 字段标签(label):优先以审批单模板(instance_template)中的实际显示文本为准,若模板中未出现则保留旧版字段的中文含义;","3. 字段类型(type)根据旧版类型进行合理映射,如 text、number、date、select、checkbox、table、formula 等;","4. 公式字段需转为 formula 类型,表达式语法参考新版规范(支持 +、-、*、/、IF、SUM、CONCAT、DATEDIF、RMB 等函数);","5. 子表字段(table)的子字段同样按以上规范处理;","6. 可见性规则(visibilityRules)中的 field 引用需更新为新版对应的字段 name;","7. 下拉选项(options)保留,格式为 [{label,value}];","8. 请输出所有字段,不要遗漏,也不要添加原来没有的字段。","9. 新版已不再支持 instance_template(审批单模板)、form_script(表单脚本)、flow_events(流程事件),请分析这些旧版数据中的业务逻辑,将其功能迁移到新版的 events(onInit / onValueChange / onSubmit)、字段的 visibilityRules、requiredRules、formula 等新版机制中实现。不要在输出中返回 instance_template、form_script、flow_events 字段。","10. 字段布局是升级的核心目标,新版显示效果必须尽可能精确还原旧版审批单模板的视觉布局:"," - 首先统计模板 HTML 表格展开所有 colspan 后的实际最大总列数(包含标签列和数据列),然后选择布局方案:"," - ⭐ **优先使用【复杂表格布局】(grid 网格字段)**。只有模板表格极其简单(总列数 ≤ 6 且无任何 rowspan/colspan)时才考虑简单布局。如果你不确定用哪个,请用 grid。"," - 【简单布局】仅适用于:模板表格总列数 ≤ 6、每行最多 3 个输入字段、且无任何 rowspan 或 colspan 合并。使用 tableColumns + tableColspan 方案。如果模板中出现任何 rowspan 或 colspan,则不得使用简单布局,必须使用 grid。",' - 【复杂表格布局(grid)】模板有 rowspan/colspan、或总列数 > 6、或有多级表头:必须使用 grid 网格字段。将 HTML 表格每个 td 映射为 cellType:"label" 或 cellType:"input",rowspan/colspan 直接映射。绝大多数审批单模板都应使用此方案。'," - 若模板无法判断 colspan 则按旧版 is_wide 属性决定(is_wide=true 为 tableColumns,否则为 1)",' - 模板中的分类标题(如“工程费用”“其他费用”):简单布局时转为 section 字段并设置合适的 colorScheme;复杂表格布局时作为 grid 中的 cellType:"label" 静态文本',' - 【列数精确匹配】grid 的 gridCols 必须等于 HTML 表格展开所有 colspan 后的实际最大列数,禁止合并或删减列。如果表头"预算"或"决算"下方有多个子列,必须全部保留'," - 【单元格完整覆盖】gridData 的每行每列必须被覆盖(有 gridData 条目或被其他单元格的 rowspan/colspan 覆盖),不允许空洞。如果某列在表头有 colspan=2,数据行只需 1 列内容时也要设 colspan=2","11. 动态必填规则(requiredRules)中的 field 引用同样需更新为新版对应的字段 name;",...kt?.trim()?["",`补充要求:${kt.trim()}`]:[],"","旧版字段数据(JSON):",Ft].join(`
|
|
715
|
-
`)},$n=()=>{const Ue={},kt=_t?.instance_template_backup||_t?.instance_template;return kt&&(Ue.instance_template=kt),yn?.current?.form_script&&(Ue.form_script=yn.current.form_script),_t?.events&&(Ue.flow_events=typeof _t.events=="string"?_t.events:JSON.stringify(_t.events)),Object.keys(Ue).length>0?Ue:void 0},Mt=async(Ue,kt)=>{if(Ue.events&&typeof Ue.events=="object"){const ht={onInit:Ue.events.onInit||"",onValueChange:Ue.events.onValueChange||"",onSubmit:Ue.events.onSubmit||""};x(ht)}const Ft=kt||_t;let pt=!1;if(Ft){const ht={...Ft};ht.instance_template&&(ht.instance_template="",pt=!0),ht.events&&(ht.events="",pt=!0),pt&&(wn(ht),Ut(!0))}if(yn?.current?.form_script){const ht={...yn,current:{...yn.current,form_script:""}};Kt(ht)}},Wt=async()=>{if(oe){ce(!0),fe(""),Ce("正在准备..."),Le([]),Me(""),pe(!1);try{s&&(O(s),j(s,oe.rawFields,p||{},"AI 升级前备份(旧版表单)","auto")),_t?._id&&_t?.current?.steps&&(k(_t._id),R(_t._id,_t.current.steps,"AI 升级前备份(旧版流程)","auto")),s&&yn&&await T({name:`AI 升级前备份 — ${e||s}`,formId:s,flowId:_t?._id,backupType:"ai_upgrade",formSnapshot:yn,flowSnapshot:_t||void 0});const Ue=Qr(oe.rawFields,ke),kt=$n(),Ft=await iw([],{},Ue,void 0,kt,ht=>{Ce({prepare:"准备中...",calling:"连接 AI...",streaming:"AI 生成中...",fallback:"切换请求...",parsing:"解析中...",validating:"校验中...",complete:"完成!"}[ht.stage]||ht.stage),ht.stage!=="streaming"&&Le(In=>[...In,ht.message]),ht.accumulated&&Me(ht.accumulated)});if(Ft?.error)throw new Error(Ft.error);if(!Ft?.fields||!Array.isArray(Ft.fields)||Ft.fields.length===0)throw new Error(Ft?.message||"AI 未返回有效字段数据");o({_id:s||void 0,name:e,description:t,fields:Ft.fields,tableColumns:typeof Ft.tableColumns=="number"?Ft.tableColumns:void 0}),s&&(O(s),j(s,Ft.fields,Ft.events||{},"版本升级(AI 转换)","init"));const pt=await or(oe.rawFields,Ft.fields);await Mt(Ft,pt),Pe(oe.rawFields),$e(""),He(""),Pt(!0),re(null),fn("表单已成功升级,请检查字段后点击「保存」按钮","success")}catch(Ue){const kt=Ue?.response?.data,Ft=(typeof kt=="string"?kt:null)||kt?.error||kt?.message||(typeof kt=="object"?JSON.stringify(kt):null)||Ue?.message||"未知错误";fe(Ft)}finally{ce(!1),Ce("")}}},kn=async()=>{if(Fe){Ke(!0),He(""),Ye("正在准备..."),lt([]),Ot(""),Lt(!1);try{s&&a.length>0&&j(s,a,p||{},"重新转换前备份","auto"),_t?._id&&_t?.current?.steps&&R(_t._id,_t.current.steps,"重新转换前备份(流程)","auto");const Ue=Qr(Fe,Ge),kt=$n(),Ft=await iw([],{},Ue,void 0,kt,ht=>{Ye({prepare:"准备中...",calling:"连接 AI...",streaming:"AI 生成中...",fallback:"切换请求...",parsing:"解析中...",validating:"校验中...",complete:"完成!"}[ht.stage]||ht.stage),ht.stage!=="streaming"&<(In=>[...In,ht.message]),ht.accumulated&&Ot(ht.accumulated)});if(Ft?.error)throw new Error(Ft.error);if(!Ft?.fields||!Array.isArray(Ft.fields)||Ft.fields.length===0)throw new Error(Ft?.message||"AI 未返回有效字段数据");o({_id:s||void 0,name:e,description:t,fields:Ft.fields,tableColumns:typeof Ft.tableColumns=="number"?Ft.tableColumns:void 0}),s&&j(s,Ft.fields,Ft.events||{},"版本升级(重新转换)","ai");let pt;Fe&&(pt=await or(Fe,Ft.fields)),await Mt(Ft,pt),$e(""),fn("重新转换完成,请检查字段后点击「保存」按钮","success")}catch(Ue){const kt=Ue?.response?.data,Ft=(typeof kt=="string"?kt:null)||kt?.error||kt?.message||(typeof kt=="object"?JSON.stringify(kt):null)||Ue?.message||"未知错误";He(Ft)}finally{Ke(!1),Ye("")}}},rr=()=>{Y.current?.click()},Er=Ue=>{const kt=Ue.target.files?.[0];if(!kt)return;const Ft=new FileReader;Ft.onload=pt=>{try{const ht=JSON.parse(pt.target?.result);ht&&Array.isArray(ht.fields)?(a.length>0&&j(s,a,p,"导入前备份","auto"),o(ht),fn("导入成功","success")):fn("JSON 格式错误","error")}catch(ht){fn("JSON 解析失败: "+ht.message,"error")}},Ft.readAsText(kt),Ue.target.value=""},wr=()=>{const Ue=i(),kt=new Blob([JSON.stringify(Ue,null,2)],{type:"application/json"}),Ft=URL.createObjectURL(kt),pt=document.createElement("a");pt.href=Ft,pt.download=`form-${e||"export"}.json`,pt.click(),URL.revokeObjectURL(Ft)},xa=()=>{const Ue=new Date,kt=`${String(Ue.getHours()).padStart(2,"0")}:${String(Ue.getMinutes()).padStart(2,"0")}:${String(Ue.getSeconds()).padStart(2,"0")}`;j(s,a,p,`暂存 ${kt}`,"manual"),fn("已暂存到本地版本历史","success")},Sa=async Ue=>{Qe(!0);try{const kt=await L(Ue._id);if(!kt||!kt.form_snapshot){fn("无法获取备份数据","error");return}const Ft=typeof kt.form_snapshot=="string"?JSON.parse(kt.form_snapshot):kt.form_snapshot,pt=kt.flow_snapshot?typeof kt.flow_snapshot=="string"?JSON.parse(kt.flow_snapshot):kt.flow_snapshot:null,ht={...Ft,id:Ft._id||Ft.id};if(delete ht._id,await zR(ht),pt){const jn=(pt.current?.steps||[]).map(cn=>{const fa={...cn,id:cn._id||cn.id};return delete fa._id,fa.lines&&(fa.lines=fa.lines.map(Ln=>{const fr={...Ln,id:Ln._id||Ln.id};return delete fr._id,fr})),fa}),In={...pt,id:pt._id||pt.id,current:{...pt.current,steps:jn}};delete In._id,await gE(In)}z_(),an(!1),et(null),fn("还原成功,正在重新加载页面...","success"),setTimeout(()=>window.location.reload(),800)}catch(kt){fn("还原失败: "+(kt?.response?.data?.message||kt?.message||"未知错误"),"error")}finally{Qe(!1)}};if(Q)return m.jsx("div",{className:"h-screen w-full flex items-center justify-center",children:m.jsxs("div",{className:"text-center",children:[m.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600 mx-auto mb-3"}),m.jsx("p",{className:"text-sm text-gray-500",children:"加载表单数据中..."})]})});if(Z)return m.jsx("div",{className:"h-screen w-full flex items-center justify-center",children:m.jsxs("div",{className:"text-center",children:[m.jsx("p",{className:"text-sm text-red-500 mb-2",children:Z}),m.jsx("button",{onClick:()=>window.location.reload(),className:"text-sm text-indigo-600 hover:underline",children:"重试"})]})});const na=()=>{G.current?.click()},Ma=Ue=>{const kt=Ue.target.files?.[0];if(!kt)return;const Ft=new FileReader;Ft.onload=async pt=>{try{const ht=JSON.parse(pt.target?.result);ht&&Array.isArray(ht.fields)?(s&&yn&&await T({name:`导入新版表单前备份 — ${e||s}`,formId:s,flowId:_t?._id,backupType:"import",formSnapshot:yn,flowSnapshot:_t||void 0}),o(ht),s&&(O(s),j(s,ht.fields,ht.events||{},"导入新版表单","init")),re(null),fn("导入成功,已加载新版表单","success")):fn("JSON 格式错误:缺少 fields 数组","error")}catch(ht){fn("JSON 解析失败: "+ht.message,"error")}},Ft.readAsText(kt),Ue.target.value=""};return oe?m.jsxs("div",{className:"h-screen w-full flex flex-col overflow-hidden",children:[m.jsxs("header",{className:"flex-shrink-0 bg-white border-b border-gray-200",children:[m.jsx("input",{ref:G,type:"file",accept:".json",className:"hidden",onChange:Ma}),m.jsxs("div",{className:"relative flex h-12 items-center px-4",children:[m.jsxs("div",{className:"flex items-center gap-2.5",children:[m.jsx("div",{className:"w-7 h-7 rounded-lg bg-emerald-600 flex items-center justify-center flex-shrink-0",children:m.jsx(lE,{className:"w-3.5 h-3.5 text-white"})}),m.jsx("h1",{className:"text-[14px] font-semibold text-gray-800 whitespace-nowrap",children:ur||e||"未命名流程"})]}),m.jsx("div",{className:"absolute left-1/2 -translate-x-1/2",children:m.jsx(vE,{active:"form",isDirty:!1})})]})]}),m.jsx("div",{className:"flex-1 flex items-center justify-center bg-gray-50",children:m.jsxs("div",{className:"bg-white rounded-2xl shadow-xl border border-gray-200 w-[500px] p-8 space-y-6",children:[m.jsxs("div",{className:"flex items-center gap-3",children:[m.jsx("div",{className:"w-10 h-10 rounded-xl bg-amber-100 flex items-center justify-center flex-shrink-0",children:m.jsx(rw,{className:"w-5 h-5 text-amber-600"})}),m.jsxs("div",{children:[m.jsx("h2",{className:"text-[16px] font-semibold text-gray-800",children:"检测到旧版表单格式"}),m.jsx("p",{className:"text-[12px] text-gray-400 mt-0.5",children:"当前表单使用旧版格式,无法直接编辑"})]})]}),m.jsxs("div",{className:"rounded-lg bg-amber-50 border border-amber-200 px-4 py-3 space-y-1.5",children:[m.jsx("p",{className:"text-[13px] font-medium text-amber-800",children:"升级前请注意以下风险:"}),m.jsxs("ul",{className:"text-[12px] text-amber-700 space-y-1 list-disc list-inside",children:[m.jsx("li",{children:"AI 将自动转换字段名称、类型和公式,可能存在偏差,请升级后仔细核对"}),m.jsx("li",{children:"旧版公式语法可能与新版不完全兼容,需要手动确认"}),m.jsx("li",{children:"关联字段、自定义脚本等复杂配置需升级后人工检查"}),m.jsx("li",{children:'升级过程不会覆盖服务器数据,需手动点击"保存"后才会生效'}),m.jsx("li",{children:"建议升级前先在服务器备份原始表单数据"})]})]}),m.jsxs("div",{className:"flex items-center gap-2 text-[12px] text-gray-500",children:[m.jsxs("span",{className:"px-2 py-0.5 rounded bg-gray-100 text-gray-600 font-medium",children:[oe.rawFields.length," 个字段"]}),m.jsx("span",{children:"将由 AI 自动转换为新版格式"})]}),m.jsxs("div",{className:"space-y-1.5",children:[m.jsx("label",{className:"text-[12px] font-medium text-gray-600",children:"补充说明(可选)"}),m.jsx("textarea",{value:ke,onChange:Ue=>Ve(Ue.target.value),disabled:le,rows:2,placeholder:"如:金额字段使用 number 类型并开启千位分隔符;公式字段转成 RMB 大写...",className:"w-full resize-none rounded-lg border border-gray-200 px-3 py-2 text-[12px] text-gray-700 placeholder-gray-300 focus:outline-none focus:border-indigo-400 focus:ring-1 focus:ring-indigo-200 disabled:opacity-50"})]}),m.jsxs("div",{className:"flex gap-3 pt-1",children:[ne&&m.jsx("button",{onClick:Wt,disabled:le,className:"flex-1 flex items-center justify-center gap-2 rounded-lg bg-indigo-600 px-4 py-2 text-[13px] font-medium text-white hover:bg-indigo-700 disabled:opacity-50 transition-colors",children:le?m.jsxs(m.Fragment,{children:[m.jsx(Zl,{className:"w-4 h-4 animate-spin"}),xe||"AI 转换中..."]}):m.jsxs(m.Fragment,{children:[m.jsx(Do,{className:"w-4 h-4"}),"AI 升级"]})}),m.jsxs("button",{onClick:na,disabled:le,className:"flex-1 flex items-center justify-center gap-2 rounded-lg border border-gray-300 bg-white px-4 py-2 text-[13px] font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 transition-colors",children:[m.jsx(sE,{className:"w-4 h-4"}),"导入新版表单"]}),le&&m.jsx("button",{onClick:()=>pe(!je),className:`shrink-0 flex items-center justify-center w-9 h-9 rounded-lg border transition-colors ${je?"bg-gray-800 border-gray-700 text-green-400":"bg-white border-gray-300 text-gray-500 hover:bg-gray-50 hover:text-gray-700"}`,title:"查看处理日志",children:m.jsx(ip,{className:"w-4 h-4"})})]}),!ne&&m.jsxs("div",{className:"rounded-lg bg-amber-50 border border-amber-200 px-3 py-2.5 flex items-start gap-2",children:[m.jsx(cE,{className:"w-3.5 h-3.5 text-amber-500 flex-shrink-0 mt-0.5"}),m.jsxs("p",{className:"text-[11px] text-amber-700 leading-relaxed",children:["未配置环境变量 ",m.jsx("code",{className:"bg-amber-100 px-1 rounded text-[10px]",children:"WORKFLOW_AI_API_KEY"}),",AI 升级不可用。您可以在已配置的环境中将表单转换为新版格式后导出 JSON,再点击「导入新版表单」导入。"]})]}),je&&(Ae.length>0||ye)&&m.jsxs("div",{className:"rounded-lg bg-gray-900 border border-gray-700 overflow-hidden",children:[m.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5 bg-gray-800 border-b border-gray-700",children:[m.jsx("span",{className:"text-[11px] font-medium text-gray-400",children:"AI 输出"}),m.jsx("button",{onClick:()=>pe(!1),className:"text-gray-500 hover:text-gray-300",children:m.jsx(Tr,{className:"w-3 h-3"})})]}),Ae.length>0&&m.jsx("div",{className:"px-3 py-1.5 border-b border-gray-800",children:Ae.map((Ue,kt)=>m.jsxs("div",{className:"text-[10px] text-gray-500 font-mono",children:[m.jsx("span",{className:"text-gray-600 mr-1",children:"▸"}),Ue]},kt))}),ye&&m.jsxs("div",{className:"max-h-[240px] overflow-y-auto px-3 py-2",children:[m.jsx("pre",{className:"font-mono text-[11px] text-green-400 whitespace-pre-wrap break-all",children:ye}),m.jsx("div",{ref:Ne})]})]}),se&&m.jsxs("div",{className:"rounded-lg bg-red-50 border border-red-200 px-4 py-3 flex items-start gap-2.5",children:[m.jsx(op,{className:"w-4 h-4 text-red-500 flex-shrink-0 mt-0.5"}),m.jsxs("div",{className:"min-w-0",children:[m.jsx("p",{className:"text-[13px] font-medium text-red-700 mb-0.5",children:"升级失败"}),m.jsx("pre",{className:"text-[11px] text-red-600 whitespace-pre-wrap break-all font-mono",children:se})]})]})]})})]}):m.jsxs("div",{className:"h-screen w-full flex flex-col overflow-hidden",children:[m.jsxs("header",{className:"flex-shrink-0 bg-white border-b border-gray-200",children:[m.jsx("input",{ref:Y,type:"file",accept:".json",className:"hidden",onChange:Er}),m.jsxs("div",{className:"relative flex h-12 items-center px-4 gap-3",children:[m.jsxs("div",{className:"flex items-center gap-2.5",children:[m.jsx("div",{className:"w-7 h-7 rounded-lg bg-emerald-600 flex items-center justify-center flex-shrink-0",children:m.jsx(lE,{className:"w-3.5 h-3.5 text-white"})}),dr?m.jsxs("div",{className:"flex items-center gap-2",children:[m.jsx("input",{value:Dr,onChange:Ue=>Zr(Ue.target.value),className:"border border-gray-300 rounded-md px-2 py-1 text-[13px] w-48 focus:border-indigo-400 focus:ring-1 focus:ring-indigo-200 outline-none",placeholder:"表单名称",autoFocus:!0,onKeyDown:Ue=>{if(Ue.key==="Escape"&&tr(!1),Ue.key==="Enter"){const kt=Dr.trim();n(kt),Or(kt),tr(!1)}}}),m.jsx("button",{onClick:()=>{const Ue=Dr.trim();n(Ue),Or(Ue),tr(!1)},className:"text-[12px] text-indigo-600 font-medium hover:text-indigo-800 whitespace-nowrap",children:"确定"}),m.jsx("button",{onClick:()=>tr(!1),className:"text-[12px] text-gray-400 hover:text-gray-600 whitespace-nowrap",children:"取消"})]}):m.jsxs("button",{onClick:()=>{Zr(ur||e||""),tr(!0)},className:"flex items-center gap-1.5 group",title:"点击编辑名称",children:[m.jsx("h1",{className:"text-[14px] font-semibold text-gray-800 whitespace-nowrap",children:ur||e||"未命名流程"}),m.jsx(tw,{className:"w-3 h-3 text-gray-300 group-hover:text-gray-500 smooth-transition"})]})]}),m.jsx("div",{className:"absolute left-1/2 -translate-x-1/2",children:m.jsx(vE,{active:"form",isDirty:q})}),m.jsx("div",{className:"flex-1"}),m.jsxs("div",{className:"flex items-center gap-2",children:[m.jsxs("button",{onClick:rr,className:"flex items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[13px] font-medium text-gray-700 hover:bg-gray-50 smooth-transition",title:"导入 JSON",children:[m.jsx(sE,{className:"w-3.5 h-3.5"}),"导入"]}),m.jsxs("button",{onClick:wr,className:"flex items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[13px] font-medium text-gray-700 hover:bg-gray-50 smooth-transition",title:"导出 JSON",children:[m.jsx(lD,{className:"w-3.5 h-3.5"}),"导出"]}),m.jsxs("button",{onClick:xa,className:"flex items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[13px] font-medium text-gray-700 hover:bg-gray-50 smooth-transition",title:"暂存到本地版本历史",children:[m.jsx(x_,{className:"w-3.5 h-3.5"}),"暂存"]}),P.length>0&&m.jsxs("button",{onClick:()=>an(!0),className:"flex items-center gap-1.5 rounded-md border border-gray-200 bg-white px-2.5 py-1 text-[12px] text-gray-500 hover:text-gray-700 hover:bg-gray-50 smooth-transition",title:"将表单和流程恢复到 AI 升级前的状态",children:[m.jsx(Uh,{className:"w-3 h-3"}),"恢复到旧版"]}),m.jsxs("button",{onClick:qn,disabled:F,className:"flex items-center gap-1.5 rounded-md bg-indigo-600 px-3 py-1.5 text-[13px] font-medium text-white hover:bg-indigo-700 disabled:opacity-50 smooth-transition",children:[F?m.jsx(Zl,{className:"w-3.5 h-3.5 animate-spin"}):m.jsx(__,{className:"w-3.5 h-3.5"}),F?"保存中...":"保存"]}),cI]})]})]}),Fe&&m.jsxs("div",{className:"flex-shrink-0 border-b border-amber-200 bg-amber-50",children:[m.jsxs("div",{className:"flex items-center gap-2 px-4 py-1.5",children:[m.jsx(Do,{className:"w-3.5 h-3.5 shrink-0 text-amber-600"}),m.jsx("span",{className:"flex-1 text-[12px] font-medium text-amber-800",children:"表单已从旧版升级,效果不满意?可补充说明后重新转换"}),m.jsx("button",{onClick:()=>Pt(!Bt),className:"text-amber-400 hover:text-amber-600 smooth-transition",title:Bt?"收起":"展开",children:m.jsx(rl,{className:`w-4 h-4 transition-transform duration-200 ${Bt?"rotate-180":""}`})})]}),Bt&&m.jsxs(m.Fragment,{children:[m.jsxs("div",{className:"flex items-start gap-2 px-4 pb-2",children:[m.jsx("textarea",{value:Ge,onChange:Ue=>$e(Ue.target.value),disabled:Ee,rows:1,placeholder:"描述问题或补充要求,如:请假天数公式不对、金额字段需要大写...",className:"flex-1 resize-none rounded-lg border border-amber-200 bg-white px-3 py-1.5 text-[12px] text-gray-700 placeholder-gray-400 focus:outline-none focus:border-amber-400 focus:ring-1 focus:ring-amber-200 disabled:opacity-50"}),m.jsxs("button",{onClick:kn,disabled:Ee,className:"shrink-0 flex items-center gap-1.5 rounded-lg bg-amber-500 px-3 py-1.5 text-[12px] font-medium text-white hover:bg-amber-600 disabled:opacity-50 smooth-transition",children:[Ee?m.jsx(Zl,{className:"w-3.5 h-3.5 animate-spin"}):m.jsx(Do,{className:"w-3.5 h-3.5"}),Ee?tt||"转换中...":"重新转换"]}),Ee&&m.jsx("button",{onClick:()=>Lt(!gt),className:`shrink-0 flex items-center justify-center w-7 h-7 rounded-lg border transition-colors ${gt?"bg-gray-800 border-gray-700 text-green-400":"border-amber-200 text-amber-500 hover:bg-amber-100"}`,title:"查看处理日志",children:m.jsx(ip,{className:"w-3.5 h-3.5"})}),m.jsx("button",{onClick:()=>{Pe(null),Pt(!1)},className:"shrink-0 rounded-lg border border-amber-200 px-2 py-1.5 text-[12px] text-amber-600 hover:bg-amber-100 smooth-transition",title:"不再显示",children:"关闭"})]}),gt&&(Ze.length>0||xt)&&m.jsxs("div",{className:"mx-4 mb-2 rounded-lg bg-gray-900 border border-gray-700 overflow-hidden",children:[m.jsxs("div",{className:"flex items-center justify-between px-3 py-1 bg-gray-800 border-b border-gray-700",children:[m.jsx("span",{className:"text-[10px] font-medium text-gray-400",children:"AI 输出"}),m.jsx("button",{onClick:()=>Lt(!1),className:"text-gray-500 hover:text-gray-300",children:m.jsx(Tr,{className:"w-3 h-3"})})]}),Ze.length>0&&m.jsx("div",{className:"px-3 py-1 border-b border-gray-800",children:Ze.map((Ue,kt)=>m.jsxs("div",{className:"text-[10px] text-gray-500 font-mono",children:[m.jsx("span",{className:"text-gray-600 mr-1",children:"▸"}),Ue]},kt))}),xt&&m.jsxs("div",{className:"max-h-[160px] overflow-y-auto px-3 py-1.5",children:[m.jsx("pre",{className:"font-mono text-[10px] text-green-400 whitespace-pre-wrap break-all",children:xt}),m.jsx("div",{ref:Gt})]})]}),Te&&m.jsx("div",{className:"px-4 pb-2",children:m.jsx("p",{className:"rounded bg-red-50 px-2 py-1 text-[11px] text-red-600",children:Te})})]})]}),m.jsxs("div",{className:"flex-1 flex overflow-hidden min-h-0",children:[m.jsx(KD,{show:Un,defaultWidth:350,minWidth:350,maxFraction:.5,className:"bg-white",children:m.jsx(dbe,{sidebar:!0,onClose:()=>Xt(!1)})}),m.jsxs("div",{className:"flex-1 flex flex-col min-w-0 overflow-hidden",children:[m.jsxs("div",{className:"flex-shrink-0 flex items-center justify-between border-b border-gray-100 bg-white px-3 py-1.5",children:[m.jsxs("div",{className:"flex items-center gap-2 text-[11px] text-gray-400",children:[ne&&m.jsxs("button",{onClick:()=>Xt(!Un),className:`flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium smooth-transition ${Un?"bg-purple-100 text-purple-700":"text-gray-400 hover:text-purple-600 hover:bg-purple-50"}`,title:"AI 表单助手",children:[m.jsx(Do,{className:"w-3.5 h-3.5"}),"AI"]}),m.jsx("div",{className:"mx-1.5 h-4 w-px bg-gray-200"}),m.jsx("button",{onClick:D,disabled:!B,className:"rounded-md p-1.5 text-gray-500 hover:bg-gray-100 hover:text-gray-700 disabled:opacity-30 disabled:hover:bg-transparent smooth-transition",title:"撤销 (⌘Z)",children:m.jsx(mD,{className:"h-4 w-4"})}),m.jsx("button",{onClick:H,disabled:!M,className:"rounded-md p-1.5 text-gray-500 hover:bg-gray-100 hover:text-gray-700 disabled:opacity-30 disabled:hover:bg-transparent smooth-transition",title:"重做 (⌘⇧Z)",children:m.jsx(cD,{className:"h-4 w-4"})}),m.jsx("div",{className:"w-px h-4 bg-gray-200"}),m.jsxs("span",{children:[a.length," 个字段"]})]}),m.jsxs("div",{className:"flex items-center gap-2",children:[m.jsxs("button",{onClick:()=>hn(!nn),className:`flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium smooth-transition ${nn?"bg-emerald-100 text-emerald-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-100"}`,title:"预览表单",children:[m.jsx(C_,{className:"w-3.5 h-3.5"}),"预览"]}),nn&&m.jsxs(m.Fragment,{children:[m.jsx("div",{className:"w-px h-4 bg-gray-200"}),m.jsxs("div",{className:"flex items-center gap-0.5 rounded-md border border-gray-200 p-0.5",children:[m.jsx("button",{onClick:()=>Kn("desktop"),className:`flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium smooth-transition ${Qn==="desktop"?"bg-blue-100 text-blue-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-50"}`,title:"桌面模式",children:m.jsx($K,{className:"w-3.5 h-3.5"})}),m.jsx("button",{onClick:()=>Kn("tablet"),className:`flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium smooth-transition ${Qn==="tablet"?"bg-blue-100 text-blue-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-50"}`,title:"平板模式",children:m.jsx(iq,{className:"w-3.5 h-3.5"})}),m.jsx("button",{onClick:()=>Kn("mobile"),className:`flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium smooth-transition ${Qn==="mobile"?"bg-blue-100 text-blue-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-50"}`,title:"手机模式",children:m.jsx(XK,{className:"w-3.5 h-3.5"})})]})]}),m.jsx("div",{className:"w-px h-4 bg-gray-200"}),m.jsxs("button",{onClick:()=>{Dt(!Zt),Zt||At(!0)},className:`flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium smooth-transition ${Zt?"bg-amber-100 text-amber-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-100"}`,title:"表单事件",children:[m.jsx(ew,{className:"w-3.5 h-3.5"}),"事件"]}),m.jsx(hbe,{}),m.jsx("div",{className:"w-px h-4 bg-gray-200"}),m.jsxs("button",{onClick:()=>C(null),className:`flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium smooth-transition ${_?"text-gray-400 hover:text-gray-600 hover:bg-gray-100":"bg-indigo-100 text-indigo-700"}`,title:"表单属性",children:[m.jsx(O_,{className:"w-3.5 h-3.5"}),"表单属性"]})]})]}),m.jsx("div",{className:"flex-1 flex overflow-hidden min-h-0",children:nn?m.jsx("div",{className:"flex-1 min-w-0 relative",children:m.jsx(obe,{deviceMode:Qn})}):m.jsxs(m.Fragment,{children:[m.jsx(tX,{}),m.jsx("div",{className:"flex-1 min-w-0 relative",children:m.jsx(Fve,{})}),m.jsx(l0e,{})]})})]})]}),m.jsx(po,{open:Zt,onCancel:()=>{Dt(!1),mt(!1),At(!1)},title:m.jsxs("div",{className:"flex items-center justify-between pr-8",children:[m.jsxs("div",{className:"flex items-center gap-2",children:[m.jsx(ew,{className:"w-4 h-4 text-amber-600"}),m.jsx("span",{children:"表单事件"})]}),m.jsxs("div",{className:"flex items-center gap-1",children:[m.jsxs("button",{onClick:()=>At(!$t),className:`flex items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium smooth-transition ${$t?"bg-green-100 text-green-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-100"}`,title:"查看当前表单字段",children:[m.jsx(uE,{className:"w-3.5 h-3.5"}),"字段"]}),m.jsxs("button",{onClick:()=>mt(!en),className:`flex items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium smooth-transition ${en?"bg-blue-100 text-blue-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-100"}`,title:"查看帮助文档",children:[m.jsx(vR,{className:"w-3.5 h-3.5"}),"帮助"]})]})]}),footer:m.jsx("button",{onClick:()=>{Dt(!1),mt(!1),At(!1)},className:"rounded-md bg-indigo-600 px-4 py-1.5 text-[13px] font-medium text-white hover:bg-indigo-700 smooth-transition",children:"完成"}),width:en||$t?1060:640,centered:!0,destroyOnClose:!0,styles:{body:en||$t?{height:"60vh",overflow:"hidden"}:{maxHeight:"60vh",overflowY:"auto"}},children:m.jsxs("div",{className:en||$t?"flex gap-4 h-full":"",children:[m.jsxs("div",{className:`space-y-5 py-2 ${en||$t?"flex-1 min-w-0 overflow-y-auto pr-1":""}`,children:[m.jsxs("div",{children:[m.jsx("label",{className:"block text-[12px] font-medium text-gray-600 mb-1.5",children:"初始化事件 (onInit)"}),m.jsx("p",{className:"text-[10px] text-gray-400 mb-1.5",children:"表单加载后执行的 JavaScript 代码,支持 async/await。可用参数:form (表单实例), fields (字段数据)"}),m.jsxs("div",{className:"relative",children:[m.jsx("textarea",{value:p.onInit||"",onChange:Ue=>x({...p,onInit:Ue.target.value}),onFocus:Ue=>{xn.current={element:Ue.target,eventKey:"onInit"}},onSelect:Ue=>{xn.current={element:Ue.target,eventKey:"onInit"}},rows:8,className:"w-full border border-gray-200 rounded-lg px-3 py-2 text-[13px] font-mono outline-none focus:border-amber-400 focus:ring-1 focus:ring-amber-200 smooth-transition resize-none bg-gray-50",placeholder:`// 支持异步函数 (async/await)
|
|
714
|
+
\`\`\``}const xbe=["设置某个字段的默认值为当前日期","根据条件隐藏某些字段","从API获取数据并填充字段","初始化子表默认行"],ybe=["根据字段值联动显示/隐藏其他字段","当某个字段变化时自动计算另一个字段","级联下拉:选择后动态加载子选项","子表行变化时汇总到主表字段"],wbe=["校验某些字段不能为空","校验数值范围是否合法","提交前调用外部API验证","校验子表至少有一行数据"],Cbe=()=>{const{formName:e,formDescription:t,setFormName:n,setFormDescription:r,fields:a,loadForm:o,toJSON:i}=Jt(),s=Jt(Ue=>Ue.formId),u=Jt(Ue=>Ue.setFormId),f=Jt(Ue=>Ue.viewMode),h=Jt(Ue=>Ue.tableColumns),p=Jt(Ue=>Ue.formEvents),b=d.useMemo(()=>pbe(a),[a]),v=d.useMemo(()=>gbe(b),[b]),w=d.useMemo(()=>vbe(b),[b]),S=d.useMemo(()=>bbe(b),[b]),x=Jt(Ue=>Ue.setFormEvents),C=Jt(Ue=>Ue.selectField),_=Jt(Ue=>Ue.selectedFieldId),$=Jt(Ue=>Ue.setFlowSteps),j=Aw(Ue=>Ue.saveVersion),O=Aw(Ue=>Ue.loadVersions),R=$0(Ue=>Ue.saveVersion),k=$0(Ue=>Ue.loadVersions),P=Xv(Ue=>Ue.backups),A=Xv(Ue=>Ue.loadBackups),T=Xv(Ue=>Ue.createBackup),L=Xv(Ue=>Ue.fetchBackup),V=Xv(Ue=>Ue.removeBackup),q=Jt(Ue=>Ue.isDirty),I=Jt(Ue=>Ue.markClean),B=Jt(Ue=>Ue.canUndo),M=Jt(Ue=>Ue.canRedo),D=Jt(Ue=>Ue.undo),H=Jt(Ue=>Ue.redo);d.useEffect(()=>{const Ue=kt=>{(kt.metaKey||kt.ctrlKey)&&(kt.key==="z"&&!kt.shiftKey?(kt.preventDefault(),D()):(kt.key==="z"&&kt.shiftKey||kt.key==="y")&&(kt.preventDefault(),H()))};return window.addEventListener("keydown",Ue),()=>window.removeEventListener("keydown",Ue)},[D,H]);const Y=d.useRef(null),G=d.useRef(null),[F,K]=d.useState(!1),[Q,X]=d.useState(!1),[Z,te]=d.useState(""),[ne,J]=d.useState(!1),[ae,ue]=d.useState(null),[oe,re]=d.useState(null),[le,ce]=d.useState(!1),[se,fe]=d.useState(""),[xe,Ce]=d.useState(""),[Ae,Le]=d.useState([]),[ye,Me]=d.useState(""),[je,pe]=d.useState(!1),Ne=d.useRef(null),[ke,Ve]=d.useState(""),[Fe,Pe]=d.useState(null),[Ge,$e]=d.useState(""),[Ee,Ke]=d.useState(!1),[Te,He]=d.useState(""),[tt,Ye]=d.useState(""),[Ze,lt]=d.useState([]),[xt,Ot]=d.useState(""),[gt,Lt]=d.useState(!1),Gt=d.useRef(null),[Bt,Pt]=d.useState(!0),[tn,an]=d.useState(!1),[De,Qe]=d.useState(!1),[ct,et]=d.useState(null),[Je,at]=d.useState(!0),[Ct,qt]=d.useState(!1),[Ht,sn]=d.useState(""),[Et,yt]=d.useState(""),[Yt,dn]=d.useState(""),[Nn,Cn]=d.useState(""),[Zt,Dt]=d.useState(!1),[en,mt]=d.useState(!1),[$t,At]=d.useState(!1),[Nt,Tt]=d.useState(null),xn=d.useRef(null),Vn=d.useCallback(Ue=>{const kt=xn.current;if(kt&&document.activeElement===kt.element){const Ft=kt.element,pt=Ft.selectionStart??0,ht=Ft.selectionEnd??0,jn=p[kt.eventKey]||"",In=jn.substring(0,pt)+Ue+jn.substring(ht);x({...p,[kt.eventKey]:In}),requestAnimationFrame(()=>{Ft.focus(),Ft.selectionStart=Ft.selectionEnd=pt+Ue.length})}else navigator.clipboard.writeText(Ue);Tt(Ue),setTimeout(()=>Tt(null),1e3)},[p,x]),[Un,Xt]=d.useState(!1),[nn,hn]=d.useState(!1),[Qn,Kn]=d.useState("desktop"),[ur,Or]=d.useState(""),[dr,tr]=d.useState(!1),[Dr,Zr]=d.useState(""),Nr=d.useRef(void 0),[yn,Kt]=d.useState(null),[_t,wn]=d.useState(null),[Vt,Ut]=d.useState(!1);d.useEffect(()=>{Ne.current?.scrollIntoView({behavior:"smooth"})},[ye]),d.useEffect(()=>{Gt.current?.scrollIntoView({behavior:"smooth"})},[xt]);const fn=d.useCallback((Ue,kt="info")=>{Nr.current&&clearTimeout(Nr.current),ue({message:Ue,type:kt}),Nr.current=setTimeout(()=>ue(null),kt==="error"?4e3:2500)},[]);d.useEffect(()=>{ow()&&FD().then(J);const kt=new URLSearchParams(window.location.search).get("flowId");!kt||!ow()||(X(!0),te(""),LD(kt).then(Ft=>{const{form:pt,flow:ht}=Ft;if(ht&&(Or(ht.name||""),$(ht.current?.steps||[]),wn(ht)),pt&&(Kt(pt),u(pt._id),n(pt.name||""),r(pt.description||""),A(pt._id),pt.current?.fields)){const jn=pt.current.fields;if(pt.current?.version!=="v2")re({rawFields:jn});else{const cn=pt.current?.events||{};o({_id:pt._id,name:pt.name||"",description:pt.description||"",fields:jn,events:cn}),O(pt._id),j(pt._id,jn,cn,"服务器加载","init")}}}).catch(Ft=>{te(Ft?.response?.data?.message||Ft?.message||"加载失败")}).finally(()=>{X(!1)}))},[]);const qn=async()=>{if(!s||!yn){j(s,a,p,"本地保存","manual"),fn("已保存到本地版本(未连接服务器)","info");return}K(!0);try{const Ue=a.map(Ft=>{const pt=Ft,ht=pt.serverField||{};return{...ht,...Ft,fields:Ft.type==="table"?Ft.children:null,code:Ft.name,name:Ft.name,label:Ft.label,type:ht.type||Ft.type,is_required:Ft.required,is_wide:(Ft.colspan||6)>=12,is_list_display:pt.is_list_display??ht.is_list_display,is_searchable:pt.is_searchable??ht.is_searchable,is_multiselect:pt.is_multiselect??ht.is_multiselect,description:Ft.description||ht.description||""}}),kt={...yn,id:yn._id,name:e,description:t,current:{...yn.current,version:"v2",viewMode:f,tableColumns:h,fields:Ue,events:p}};if(delete kt._id,await zR(kt),Vt&&_t)try{const Ft=(_t.current?.steps||[]).map(ht=>{const jn={...ht,id:ht._id||ht.id};return delete jn._id,jn.lines&&(jn.lines=jn.lines.map(In=>{const cn={...In,id:In._id||In.id};return delete cn._id,cn})),jn}),pt={..._t,id:_t._id,current:{..._t.current,steps:Ft},upgraded:!0};delete pt._id,await gE(pt),Ut(!1)}catch(Ft){console.warn("Failed to save flow data:",Ft),fn("表单已保存,但流程数据保存失败: "+(Ft?.message||"未知错误"),"error")}j(s,a,p,"手动保存","manual"),I(),fn("保存成功","success")}catch(Ue){fn("保存失败: "+(Ue?.response?.data?.message||Ue?.response?.data||Ue?.message||"未知错误"),"error")}finally{K(!1)}},yr=(Ue,kt)=>{const Ft={},pt={},ht=In=>{for(const cn of In){const fa=cn.code||cn.name,Ln=cn.name||cn.label||cn.code||"";fa&&(pt[Ln]||(pt[Ln]=[]),pt[Ln].push(cn)),cn.type==="table"&&Array.isArray(cn.fields)&&ht(cn.fields),cn.type==="section"&&Array.isArray(cn.fields)&&ht(cn.fields)}};ht(Ue);const jn=In=>{for(const cn of In){const fa=cn.name,Ln=cn.label||cn.name||"";if(fa&&Ln&&pt[Ln])for(const fr of pt[Ln]){const Fo=fr.code||fr.name;Fo&&Fo!==fa&&(Ft[Fo]=fa)}cn.type==="table"&&Array.isArray(cn.children)&&jn(cn.children),cn.type==="section"&&Array.isArray(cn.children)&&jn(cn.children)}};return jn(kt),Ft},Wr=(Ue,kt)=>{if(!Ue||!Array.isArray(Ue))return Ue;const Ft=()=>{const ht=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return ht()+ht()+ht()},pt=Object.keys(kt).length===0;return Ue.map(ht=>{const jn=ht._id||Ft();if(pt)return ht._id?ht:{...ht,_id:jn};if(!ht.permissions||typeof ht.permissions!="object")return{...ht,_id:jn};const In={};for(const[cn,fa]of Object.entries(ht.permissions)){const Ln=kt[cn]||cn;In[Ln]=fa}return{...ht,_id:jn,permissions:In}})},or=async(Ue,kt)=>{if(!_t?.current?.steps)return _t;const Ft=yr(Ue,kt),pt=Wr(_t.current.steps,Ft),ht={..._t,current:{..._t.current,steps:pt}};return wn(ht),$(pt),Ut(!0),ht},Qr=(Ue,kt)=>{const Ft=JSON.stringify(Ue,null,2);return["请将以下旧版表单字段完整升级为新版 v2 格式,要求如下:","1. 字段名称(name)使用英文小写字母+下划线的命名规范,不要使用中文或特殊字符;","2. 字段标签(label):优先以审批单模板(instance_template)中的实际显示文本为准,若模板中未出现则保留旧版字段的中文含义;","3. 字段类型(type)根据旧版类型进行合理映射,如 text、number、date、select、checkbox、table、formula 等;","4. 公式字段需转为 formula 类型,表达式语法参考新版规范(支持 +、-、*、/、IF、SUM、CONCAT、DATEDIF、RMB 等函数);","5. 子表字段(table)的子字段同样按以上规范处理;","6. 可见性规则(visibilityRules)中的 field 引用需更新为新版对应的字段 name;","7. 下拉选项(options)保留,格式为 [{label,value}];","8. 请输出所有字段,不要遗漏,也不要添加原来没有的字段。","9. 新版已不再支持 instance_template(审批单模板)、form_script(表单脚本)、flow_events(流程事件),请分析这些旧版数据中的业务逻辑,将其功能迁移到新版的 events(onInit / onValueChange / onSubmit)、字段的 visibilityRules、requiredRules、formula 等新版机制中实现。不要在输出中返回 instance_template、form_script、flow_events 字段。","10. 字段布局是升级的核心目标,新版显示效果必须尽可能精确还原旧版审批单模板的视觉布局:"," - 首先统计模板 HTML 表格展开所有 colspan 后的实际最大总列数(包含标签列和数据列),然后选择布局方案:"," - ⭐ **优先使用【复杂表格布局】(grid 网格字段)**。只有模板表格极其简单(总列数 ≤ 6 且无任何 rowspan/colspan)时才考虑简单布局。如果你不确定用哪个,请用 grid。"," - 【简单布局】仅适用于:模板表格总列数 ≤ 6、每行最多 3 个输入字段、且无任何 rowspan 或 colspan 合并。使用 tableColumns + tableColspan 方案。如果模板中出现任何 rowspan 或 colspan,则不得使用简单布局,必须使用 grid。",' - 【复杂表格布局(grid)】模板有 rowspan/colspan、或总列数 > 6、或有多级表头:必须使用 grid 网格字段。将 HTML 表格每个 td 映射为 cellType:"label" 或 cellType:"input",rowspan/colspan 直接映射。绝大多数审批单模板都应使用此方案。'," - 若模板无法判断 colspan 则按旧版 is_wide 属性决定(is_wide=true 为 tableColumns,否则为 1)",' - 模板中的分类标题(如“工程费用”“其他费用”):简单布局时转为 section 字段并设置合适的 colorScheme;复杂表格布局时作为 grid 中的 cellType:"label" 静态文本',' - 【列数精确匹配】grid 的 gridCols 必须等于 HTML 表格展开所有 colspan 后的实际最大列数,禁止合并或删减列。如果表头"预算"或"决算"下方有多个子列,必须全部保留'," - 【单元格完整覆盖】gridData 的每行每列必须被覆盖(有 gridData 条目或被其他单元格的 rowspan/colspan 覆盖),不允许空洞。如果某列在表头有 colspan=2,数据行只需 1 列内容时也要设 colspan=2","11. 动态必填规则(requiredRules)中的 field 引用同样需更新为新版对应的字段 name;",...kt?.trim()?["",`补充要求:${kt.trim()}`]:[],"","旧版字段数据(JSON):",Ft].join(`
|
|
715
|
+
`)},$n=()=>{const Ue={},kt=_t?.instance_template_backup||_t?.instance_template;return kt&&(Ue.instance_template=kt),yn?.current?.form_script&&(Ue.form_script=yn.current.form_script),_t?.events&&(Ue.flow_events=typeof _t.events=="string"?_t.events:JSON.stringify(_t.events)),Object.keys(Ue).length>0?Ue:void 0},Mt=async(Ue,kt)=>{if(Ue.events&&typeof Ue.events=="object"){const ht={onInit:Ue.events.onInit||"",onValueChange:Ue.events.onValueChange||"",onSubmit:Ue.events.onSubmit||""};x(ht)}const Ft=kt||_t;let pt=!1;if(Ft){const ht={...Ft};ht.instance_template&&(ht.instance_template="",pt=!0),ht.events&&(ht.events="",pt=!0),pt&&(wn(ht),Ut(!0))}if(yn?.current?.form_script){const ht={...yn,current:{...yn.current,form_script:""}};Kt(ht)}},Wt=async()=>{if(oe){ce(!0),fe(""),Ce("正在准备..."),Le([]),Me(""),pe(!1);try{s&&(O(s),j(s,oe.rawFields,p||{},"AI 升级前备份(旧版表单)","auto")),_t?._id&&_t?.current?.steps&&(k(_t._id),R(_t._id,_t.current.steps,"AI 升级前备份(旧版流程)","auto")),s&&yn&&await T({name:`AI 升级前备份 — ${e||s}`,formId:s,flowId:_t?._id,backupType:"ai_upgrade",formSnapshot:yn,flowSnapshot:_t||void 0});const Ue=Qr(oe.rawFields,ke),kt=$n(),Ft=await iw([],{},Ue,void 0,kt,ht=>{Ce({prepare:"准备中...",calling:"连接 AI...",streaming:"AI 生成中...",fallback:"切换请求...",parsing:"解析中...",validating:"校验中...",complete:"完成!"}[ht.stage]||ht.stage),ht.stage!=="streaming"&&Le(In=>[...In,ht.message]),ht.accumulated&&Me(ht.accumulated)});if(Ft?.error)throw new Error(Ft.error);if(!Ft?.fields||!Array.isArray(Ft.fields)||Ft.fields.length===0)throw new Error(Ft?.message||"AI 未返回有效字段数据");o({_id:s||void 0,name:e,description:t,fields:Ft.fields,tableColumns:typeof Ft.tableColumns=="number"?Ft.tableColumns:void 0}),s&&(O(s),j(s,Ft.fields,Ft.events||{},"版本升级(AI 转换)","init"));const pt=await or(oe.rawFields,Ft.fields);await Mt(Ft,pt),Pe(oe.rawFields),$e(""),He(""),Pt(!0),re(null),fn("表单已成功升级,请检查字段后点击「保存」按钮","success")}catch(Ue){const kt=Ue?.response?.data,Ft=(typeof kt=="string"?kt:null)||kt?.error||kt?.message||(typeof kt=="object"?JSON.stringify(kt):null)||Ue?.message||"未知错误";fe(Ft)}finally{ce(!1),Ce("")}}},kn=async()=>{if(Fe){Ke(!0),He(""),Ye("正在准备..."),lt([]),Ot(""),Lt(!1);try{s&&a.length>0&&j(s,a,p||{},"重新转换前备份","auto"),_t?._id&&_t?.current?.steps&&R(_t._id,_t.current.steps,"重新转换前备份(流程)","auto");const Ue=Qr(Fe,Ge),kt=$n(),Ft=await iw([],{},Ue,void 0,kt,ht=>{Ye({prepare:"准备中...",calling:"连接 AI...",streaming:"AI 生成中...",fallback:"切换请求...",parsing:"解析中...",validating:"校验中...",complete:"完成!"}[ht.stage]||ht.stage),ht.stage!=="streaming"&<(In=>[...In,ht.message]),ht.accumulated&&Ot(ht.accumulated)});if(Ft?.error)throw new Error(Ft.error);if(!Ft?.fields||!Array.isArray(Ft.fields)||Ft.fields.length===0)throw new Error(Ft?.message||"AI 未返回有效字段数据");o({_id:s||void 0,name:e,description:t,fields:Ft.fields,tableColumns:typeof Ft.tableColumns=="number"?Ft.tableColumns:void 0}),s&&j(s,Ft.fields,Ft.events||{},"版本升级(重新转换)","ai");let pt;Fe&&(pt=await or(Fe,Ft.fields)),await Mt(Ft,pt),$e(""),fn("重新转换完成,请检查字段后点击「保存」按钮","success")}catch(Ue){const kt=Ue?.response?.data,Ft=(typeof kt=="string"?kt:null)||kt?.error||kt?.message||(typeof kt=="object"?JSON.stringify(kt):null)||Ue?.message||"未知错误";He(Ft)}finally{Ke(!1),Ye("")}}},rr=()=>{Y.current?.click()},Er=Ue=>{const kt=Ue.target.files?.[0];if(!kt)return;const Ft=new FileReader;Ft.onload=pt=>{try{const ht=JSON.parse(pt.target?.result);ht&&Array.isArray(ht.fields)?(a.length>0&&j(s,a,p,"导入前备份","auto"),o(ht),fn("导入成功","success")):fn("JSON 格式错误","error")}catch(ht){fn("JSON 解析失败: "+ht.message,"error")}},Ft.readAsText(kt),Ue.target.value=""},wr=()=>{const Ue=i(),kt=new Blob([JSON.stringify(Ue,null,2)],{type:"application/json"}),Ft=URL.createObjectURL(kt),pt=document.createElement("a");pt.href=Ft,pt.download=`form-${e||"export"}.json`,pt.click(),URL.revokeObjectURL(Ft)},xa=()=>{const Ue=new Date,kt=`${String(Ue.getHours()).padStart(2,"0")}:${String(Ue.getMinutes()).padStart(2,"0")}:${String(Ue.getSeconds()).padStart(2,"0")}`;j(s,a,p,`暂存 ${kt}`,"manual"),fn("已暂存到本地版本历史","success")},Sa=async Ue=>{Qe(!0);try{const kt=await L(Ue._id);if(!kt||!kt.form_snapshot){fn("无法获取备份数据","error");return}const Ft=typeof kt.form_snapshot=="string"?JSON.parse(kt.form_snapshot):kt.form_snapshot,pt=kt.flow_snapshot?typeof kt.flow_snapshot=="string"?JSON.parse(kt.flow_snapshot):kt.flow_snapshot:null,ht={...Ft,id:Ft._id||Ft.id};if(delete ht._id,await zR(ht),pt){const jn=(pt.current?.steps||[]).map(cn=>{const fa={...cn,id:cn._id||cn.id};return delete fa._id,fa.lines&&(fa.lines=fa.lines.map(Ln=>{const fr={...Ln,id:Ln._id||Ln.id};return delete fr._id,fr})),fa}),In={...pt,id:pt._id||pt.id,current:{...pt.current,steps:jn},upgraded:!1};delete In._id,await gE(In)}z_(),an(!1),et(null),fn("还原成功,正在重新加载页面...","success"),setTimeout(()=>window.location.reload(),800)}catch(kt){fn("还原失败: "+(kt?.response?.data?.message||kt?.message||"未知错误"),"error")}finally{Qe(!1)}};if(Q)return m.jsx("div",{className:"h-screen w-full flex items-center justify-center",children:m.jsxs("div",{className:"text-center",children:[m.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600 mx-auto mb-3"}),m.jsx("p",{className:"text-sm text-gray-500",children:"加载表单数据中..."})]})});if(Z)return m.jsx("div",{className:"h-screen w-full flex items-center justify-center",children:m.jsxs("div",{className:"text-center",children:[m.jsx("p",{className:"text-sm text-red-500 mb-2",children:Z}),m.jsx("button",{onClick:()=>window.location.reload(),className:"text-sm text-indigo-600 hover:underline",children:"重试"})]})});const na=()=>{G.current?.click()},Ma=Ue=>{const kt=Ue.target.files?.[0];if(!kt)return;const Ft=new FileReader;Ft.onload=async pt=>{try{const ht=JSON.parse(pt.target?.result);ht&&Array.isArray(ht.fields)?(s&&yn&&await T({name:`导入新版表单前备份 — ${e||s}`,formId:s,flowId:_t?._id,backupType:"import",formSnapshot:yn,flowSnapshot:_t||void 0}),o(ht),s&&(O(s),j(s,ht.fields,ht.events||{},"导入新版表单","init")),re(null),fn("导入成功,已加载新版表单","success")):fn("JSON 格式错误:缺少 fields 数组","error")}catch(ht){fn("JSON 解析失败: "+ht.message,"error")}},Ft.readAsText(kt),Ue.target.value=""};return oe?m.jsxs("div",{className:"h-screen w-full flex flex-col overflow-hidden",children:[m.jsxs("header",{className:"flex-shrink-0 bg-white border-b border-gray-200",children:[m.jsx("input",{ref:G,type:"file",accept:".json",className:"hidden",onChange:Ma}),m.jsxs("div",{className:"relative flex h-12 items-center px-4",children:[m.jsxs("div",{className:"flex items-center gap-2.5",children:[m.jsx("div",{className:"w-7 h-7 rounded-lg bg-emerald-600 flex items-center justify-center flex-shrink-0",children:m.jsx(lE,{className:"w-3.5 h-3.5 text-white"})}),m.jsx("h1",{className:"text-[14px] font-semibold text-gray-800 whitespace-nowrap",children:ur||e||"未命名流程"})]}),m.jsx("div",{className:"absolute left-1/2 -translate-x-1/2",children:m.jsx(vE,{active:"form",isDirty:!1})})]})]}),m.jsx("div",{className:"flex-1 flex items-center justify-center bg-gray-50",children:m.jsxs("div",{className:"bg-white rounded-2xl shadow-xl border border-gray-200 w-[500px] p-8 space-y-6",children:[m.jsxs("div",{className:"flex items-center gap-3",children:[m.jsx("div",{className:"w-10 h-10 rounded-xl bg-amber-100 flex items-center justify-center flex-shrink-0",children:m.jsx(rw,{className:"w-5 h-5 text-amber-600"})}),m.jsxs("div",{children:[m.jsx("h2",{className:"text-[16px] font-semibold text-gray-800",children:"检测到旧版表单格式"}),m.jsx("p",{className:"text-[12px] text-gray-400 mt-0.5",children:"当前表单使用旧版格式,无法直接编辑"})]})]}),m.jsxs("div",{className:"rounded-lg bg-amber-50 border border-amber-200 px-4 py-3 space-y-1.5",children:[m.jsx("p",{className:"text-[13px] font-medium text-amber-800",children:"升级前请注意以下风险:"}),m.jsxs("ul",{className:"text-[12px] text-amber-700 space-y-1 list-disc list-inside",children:[m.jsx("li",{children:"AI 将自动转换字段名称、类型和公式,可能存在偏差,请升级后仔细核对"}),m.jsx("li",{children:"旧版公式语法可能与新版不完全兼容,需要手动确认"}),m.jsx("li",{children:"关联字段、自定义脚本等复杂配置需升级后人工检查"}),m.jsx("li",{children:'升级过程不会覆盖服务器数据,需手动点击"保存"后才会生效'}),m.jsx("li",{children:"建议升级前先在服务器备份原始表单数据"})]})]}),m.jsxs("div",{className:"flex items-center gap-2 text-[12px] text-gray-500",children:[m.jsxs("span",{className:"px-2 py-0.5 rounded bg-gray-100 text-gray-600 font-medium",children:[oe.rawFields.length," 个字段"]}),m.jsx("span",{children:"将由 AI 自动转换为新版格式"})]}),m.jsxs("div",{className:"space-y-1.5",children:[m.jsx("label",{className:"text-[12px] font-medium text-gray-600",children:"补充说明(可选)"}),m.jsx("textarea",{value:ke,onChange:Ue=>Ve(Ue.target.value),disabled:le,rows:2,placeholder:"如:金额字段使用 number 类型并开启千位分隔符;公式字段转成 RMB 大写...",className:"w-full resize-none rounded-lg border border-gray-200 px-3 py-2 text-[12px] text-gray-700 placeholder-gray-300 focus:outline-none focus:border-indigo-400 focus:ring-1 focus:ring-indigo-200 disabled:opacity-50"})]}),m.jsxs("div",{className:"flex gap-3 pt-1",children:[ne&&m.jsx("button",{onClick:Wt,disabled:le,className:"flex-1 flex items-center justify-center gap-2 rounded-lg bg-indigo-600 px-4 py-2 text-[13px] font-medium text-white hover:bg-indigo-700 disabled:opacity-50 transition-colors",children:le?m.jsxs(m.Fragment,{children:[m.jsx(Zl,{className:"w-4 h-4 animate-spin"}),xe||"AI 转换中..."]}):m.jsxs(m.Fragment,{children:[m.jsx(Do,{className:"w-4 h-4"}),"AI 升级"]})}),m.jsxs("button",{onClick:na,disabled:le,className:"flex-1 flex items-center justify-center gap-2 rounded-lg border border-gray-300 bg-white px-4 py-2 text-[13px] font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 transition-colors",children:[m.jsx(sE,{className:"w-4 h-4"}),"导入新版表单"]}),le&&m.jsx("button",{onClick:()=>pe(!je),className:`shrink-0 flex items-center justify-center w-9 h-9 rounded-lg border transition-colors ${je?"bg-gray-800 border-gray-700 text-green-400":"bg-white border-gray-300 text-gray-500 hover:bg-gray-50 hover:text-gray-700"}`,title:"查看处理日志",children:m.jsx(ip,{className:"w-4 h-4"})})]}),!ne&&m.jsxs("div",{className:"rounded-lg bg-amber-50 border border-amber-200 px-3 py-2.5 flex items-start gap-2",children:[m.jsx(cE,{className:"w-3.5 h-3.5 text-amber-500 flex-shrink-0 mt-0.5"}),m.jsxs("p",{className:"text-[11px] text-amber-700 leading-relaxed",children:["未配置环境变量 ",m.jsx("code",{className:"bg-amber-100 px-1 rounded text-[10px]",children:"WORKFLOW_AI_API_KEY"}),",AI 升级不可用。您可以在已配置的环境中将表单转换为新版格式后导出 JSON,再点击「导入新版表单」导入。"]})]}),je&&(Ae.length>0||ye)&&m.jsxs("div",{className:"rounded-lg bg-gray-900 border border-gray-700 overflow-hidden",children:[m.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5 bg-gray-800 border-b border-gray-700",children:[m.jsx("span",{className:"text-[11px] font-medium text-gray-400",children:"AI 输出"}),m.jsx("button",{onClick:()=>pe(!1),className:"text-gray-500 hover:text-gray-300",children:m.jsx(Tr,{className:"w-3 h-3"})})]}),Ae.length>0&&m.jsx("div",{className:"px-3 py-1.5 border-b border-gray-800",children:Ae.map((Ue,kt)=>m.jsxs("div",{className:"text-[10px] text-gray-500 font-mono",children:[m.jsx("span",{className:"text-gray-600 mr-1",children:"▸"}),Ue]},kt))}),ye&&m.jsxs("div",{className:"max-h-[240px] overflow-y-auto px-3 py-2",children:[m.jsx("pre",{className:"font-mono text-[11px] text-green-400 whitespace-pre-wrap break-all",children:ye}),m.jsx("div",{ref:Ne})]})]}),se&&m.jsxs("div",{className:"rounded-lg bg-red-50 border border-red-200 px-4 py-3 flex items-start gap-2.5",children:[m.jsx(op,{className:"w-4 h-4 text-red-500 flex-shrink-0 mt-0.5"}),m.jsxs("div",{className:"min-w-0",children:[m.jsx("p",{className:"text-[13px] font-medium text-red-700 mb-0.5",children:"升级失败"}),m.jsx("pre",{className:"text-[11px] text-red-600 whitespace-pre-wrap break-all font-mono",children:se})]})]})]})})]}):m.jsxs("div",{className:"h-screen w-full flex flex-col overflow-hidden",children:[m.jsxs("header",{className:"flex-shrink-0 bg-white border-b border-gray-200",children:[m.jsx("input",{ref:Y,type:"file",accept:".json",className:"hidden",onChange:Er}),m.jsxs("div",{className:"relative flex h-12 items-center px-4 gap-3",children:[m.jsxs("div",{className:"flex items-center gap-2.5",children:[m.jsx("div",{className:"w-7 h-7 rounded-lg bg-emerald-600 flex items-center justify-center flex-shrink-0",children:m.jsx(lE,{className:"w-3.5 h-3.5 text-white"})}),dr?m.jsxs("div",{className:"flex items-center gap-2",children:[m.jsx("input",{value:Dr,onChange:Ue=>Zr(Ue.target.value),className:"border border-gray-300 rounded-md px-2 py-1 text-[13px] w-48 focus:border-indigo-400 focus:ring-1 focus:ring-indigo-200 outline-none",placeholder:"表单名称",autoFocus:!0,onKeyDown:Ue=>{if(Ue.key==="Escape"&&tr(!1),Ue.key==="Enter"){const kt=Dr.trim();n(kt),Or(kt),tr(!1)}}}),m.jsx("button",{onClick:()=>{const Ue=Dr.trim();n(Ue),Or(Ue),tr(!1)},className:"text-[12px] text-indigo-600 font-medium hover:text-indigo-800 whitespace-nowrap",children:"确定"}),m.jsx("button",{onClick:()=>tr(!1),className:"text-[12px] text-gray-400 hover:text-gray-600 whitespace-nowrap",children:"取消"})]}):m.jsxs("button",{onClick:()=>{Zr(ur||e||""),tr(!0)},className:"flex items-center gap-1.5 group",title:"点击编辑名称",children:[m.jsx("h1",{className:"text-[14px] font-semibold text-gray-800 whitespace-nowrap",children:ur||e||"未命名流程"}),m.jsx(tw,{className:"w-3 h-3 text-gray-300 group-hover:text-gray-500 smooth-transition"})]})]}),m.jsx("div",{className:"absolute left-1/2 -translate-x-1/2",children:m.jsx(vE,{active:"form",isDirty:q})}),m.jsx("div",{className:"flex-1"}),m.jsxs("div",{className:"flex items-center gap-2",children:[m.jsxs("button",{onClick:rr,className:"flex items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[13px] font-medium text-gray-700 hover:bg-gray-50 smooth-transition",title:"导入 JSON",children:[m.jsx(sE,{className:"w-3.5 h-3.5"}),"导入"]}),m.jsxs("button",{onClick:wr,className:"flex items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[13px] font-medium text-gray-700 hover:bg-gray-50 smooth-transition",title:"导出 JSON",children:[m.jsx(lD,{className:"w-3.5 h-3.5"}),"导出"]}),m.jsxs("button",{onClick:xa,className:"flex items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[13px] font-medium text-gray-700 hover:bg-gray-50 smooth-transition",title:"暂存到本地版本历史",children:[m.jsx(x_,{className:"w-3.5 h-3.5"}),"暂存"]}),P.length>0&&m.jsxs("button",{onClick:()=>an(!0),className:"flex items-center gap-1.5 rounded-md border border-gray-200 bg-white px-2.5 py-1 text-[12px] text-gray-500 hover:text-gray-700 hover:bg-gray-50 smooth-transition",title:"将表单和流程恢复到 AI 升级前的状态",children:[m.jsx(Uh,{className:"w-3 h-3"}),"恢复到旧版"]}),m.jsxs("button",{onClick:qn,disabled:F,className:"flex items-center gap-1.5 rounded-md bg-indigo-600 px-3 py-1.5 text-[13px] font-medium text-white hover:bg-indigo-700 disabled:opacity-50 smooth-transition",children:[F?m.jsx(Zl,{className:"w-3.5 h-3.5 animate-spin"}):m.jsx(__,{className:"w-3.5 h-3.5"}),F?"保存中...":"保存"]}),cI]})]})]}),Fe&&m.jsxs("div",{className:"flex-shrink-0 border-b border-amber-200 bg-amber-50",children:[m.jsxs("div",{className:"flex items-center gap-2 px-4 py-1.5",children:[m.jsx(Do,{className:"w-3.5 h-3.5 shrink-0 text-amber-600"}),m.jsx("span",{className:"flex-1 text-[12px] font-medium text-amber-800",children:"表单已从旧版升级,效果不满意?可补充说明后重新转换"}),m.jsx("button",{onClick:()=>Pt(!Bt),className:"text-amber-400 hover:text-amber-600 smooth-transition",title:Bt?"收起":"展开",children:m.jsx(rl,{className:`w-4 h-4 transition-transform duration-200 ${Bt?"rotate-180":""}`})})]}),Bt&&m.jsxs(m.Fragment,{children:[m.jsxs("div",{className:"flex items-start gap-2 px-4 pb-2",children:[m.jsx("textarea",{value:Ge,onChange:Ue=>$e(Ue.target.value),disabled:Ee,rows:1,placeholder:"描述问题或补充要求,如:请假天数公式不对、金额字段需要大写...",className:"flex-1 resize-none rounded-lg border border-amber-200 bg-white px-3 py-1.5 text-[12px] text-gray-700 placeholder-gray-400 focus:outline-none focus:border-amber-400 focus:ring-1 focus:ring-amber-200 disabled:opacity-50"}),m.jsxs("button",{onClick:kn,disabled:Ee,className:"shrink-0 flex items-center gap-1.5 rounded-lg bg-amber-500 px-3 py-1.5 text-[12px] font-medium text-white hover:bg-amber-600 disabled:opacity-50 smooth-transition",children:[Ee?m.jsx(Zl,{className:"w-3.5 h-3.5 animate-spin"}):m.jsx(Do,{className:"w-3.5 h-3.5"}),Ee?tt||"转换中...":"重新转换"]}),Ee&&m.jsx("button",{onClick:()=>Lt(!gt),className:`shrink-0 flex items-center justify-center w-7 h-7 rounded-lg border transition-colors ${gt?"bg-gray-800 border-gray-700 text-green-400":"border-amber-200 text-amber-500 hover:bg-amber-100"}`,title:"查看处理日志",children:m.jsx(ip,{className:"w-3.5 h-3.5"})}),m.jsx("button",{onClick:()=>{Pe(null),Pt(!1)},className:"shrink-0 rounded-lg border border-amber-200 px-2 py-1.5 text-[12px] text-amber-600 hover:bg-amber-100 smooth-transition",title:"不再显示",children:"关闭"})]}),gt&&(Ze.length>0||xt)&&m.jsxs("div",{className:"mx-4 mb-2 rounded-lg bg-gray-900 border border-gray-700 overflow-hidden",children:[m.jsxs("div",{className:"flex items-center justify-between px-3 py-1 bg-gray-800 border-b border-gray-700",children:[m.jsx("span",{className:"text-[10px] font-medium text-gray-400",children:"AI 输出"}),m.jsx("button",{onClick:()=>Lt(!1),className:"text-gray-500 hover:text-gray-300",children:m.jsx(Tr,{className:"w-3 h-3"})})]}),Ze.length>0&&m.jsx("div",{className:"px-3 py-1 border-b border-gray-800",children:Ze.map((Ue,kt)=>m.jsxs("div",{className:"text-[10px] text-gray-500 font-mono",children:[m.jsx("span",{className:"text-gray-600 mr-1",children:"▸"}),Ue]},kt))}),xt&&m.jsxs("div",{className:"max-h-[160px] overflow-y-auto px-3 py-1.5",children:[m.jsx("pre",{className:"font-mono text-[10px] text-green-400 whitespace-pre-wrap break-all",children:xt}),m.jsx("div",{ref:Gt})]})]}),Te&&m.jsx("div",{className:"px-4 pb-2",children:m.jsx("p",{className:"rounded bg-red-50 px-2 py-1 text-[11px] text-red-600",children:Te})})]})]}),m.jsxs("div",{className:"flex-1 flex overflow-hidden min-h-0",children:[m.jsx(KD,{show:Un,defaultWidth:350,minWidth:350,maxFraction:.5,className:"bg-white",children:m.jsx(dbe,{sidebar:!0,onClose:()=>Xt(!1)})}),m.jsxs("div",{className:"flex-1 flex flex-col min-w-0 overflow-hidden",children:[m.jsxs("div",{className:"flex-shrink-0 flex items-center justify-between border-b border-gray-100 bg-white px-3 py-1.5",children:[m.jsxs("div",{className:"flex items-center gap-2 text-[11px] text-gray-400",children:[ne&&m.jsxs("button",{onClick:()=>Xt(!Un),className:`flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium smooth-transition ${Un?"bg-purple-100 text-purple-700":"text-gray-400 hover:text-purple-600 hover:bg-purple-50"}`,title:"AI 表单助手",children:[m.jsx(Do,{className:"w-3.5 h-3.5"}),"AI"]}),m.jsx("div",{className:"mx-1.5 h-4 w-px bg-gray-200"}),m.jsx("button",{onClick:D,disabled:!B,className:"rounded-md p-1.5 text-gray-500 hover:bg-gray-100 hover:text-gray-700 disabled:opacity-30 disabled:hover:bg-transparent smooth-transition",title:"撤销 (⌘Z)",children:m.jsx(mD,{className:"h-4 w-4"})}),m.jsx("button",{onClick:H,disabled:!M,className:"rounded-md p-1.5 text-gray-500 hover:bg-gray-100 hover:text-gray-700 disabled:opacity-30 disabled:hover:bg-transparent smooth-transition",title:"重做 (⌘⇧Z)",children:m.jsx(cD,{className:"h-4 w-4"})}),m.jsx("div",{className:"w-px h-4 bg-gray-200"}),m.jsxs("span",{children:[a.length," 个字段"]})]}),m.jsxs("div",{className:"flex items-center gap-2",children:[m.jsxs("button",{onClick:()=>hn(!nn),className:`flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium smooth-transition ${nn?"bg-emerald-100 text-emerald-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-100"}`,title:"预览表单",children:[m.jsx(C_,{className:"w-3.5 h-3.5"}),"预览"]}),nn&&m.jsxs(m.Fragment,{children:[m.jsx("div",{className:"w-px h-4 bg-gray-200"}),m.jsxs("div",{className:"flex items-center gap-0.5 rounded-md border border-gray-200 p-0.5",children:[m.jsx("button",{onClick:()=>Kn("desktop"),className:`flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium smooth-transition ${Qn==="desktop"?"bg-blue-100 text-blue-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-50"}`,title:"桌面模式",children:m.jsx($K,{className:"w-3.5 h-3.5"})}),m.jsx("button",{onClick:()=>Kn("tablet"),className:`flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium smooth-transition ${Qn==="tablet"?"bg-blue-100 text-blue-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-50"}`,title:"平板模式",children:m.jsx(iq,{className:"w-3.5 h-3.5"})}),m.jsx("button",{onClick:()=>Kn("mobile"),className:`flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium smooth-transition ${Qn==="mobile"?"bg-blue-100 text-blue-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-50"}`,title:"手机模式",children:m.jsx(XK,{className:"w-3.5 h-3.5"})})]})]}),m.jsx("div",{className:"w-px h-4 bg-gray-200"}),m.jsxs("button",{onClick:()=>{Dt(!Zt),Zt||At(!0)},className:`flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium smooth-transition ${Zt?"bg-amber-100 text-amber-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-100"}`,title:"表单事件",children:[m.jsx(ew,{className:"w-3.5 h-3.5"}),"事件"]}),m.jsx(hbe,{}),m.jsx("div",{className:"w-px h-4 bg-gray-200"}),m.jsxs("button",{onClick:()=>C(null),className:`flex items-center gap-1 rounded px-2 py-1 text-[11px] font-medium smooth-transition ${_?"text-gray-400 hover:text-gray-600 hover:bg-gray-100":"bg-indigo-100 text-indigo-700"}`,title:"表单属性",children:[m.jsx(O_,{className:"w-3.5 h-3.5"}),"表单属性"]})]})]}),m.jsx("div",{className:"flex-1 flex overflow-hidden min-h-0",children:nn?m.jsx("div",{className:"flex-1 min-w-0 relative",children:m.jsx(obe,{deviceMode:Qn})}):m.jsxs(m.Fragment,{children:[m.jsx(tX,{}),m.jsx("div",{className:"flex-1 min-w-0 relative",children:m.jsx(Fve,{})}),m.jsx(l0e,{})]})})]})]}),m.jsx(po,{open:Zt,onCancel:()=>{Dt(!1),mt(!1),At(!1)},title:m.jsxs("div",{className:"flex items-center justify-between pr-8",children:[m.jsxs("div",{className:"flex items-center gap-2",children:[m.jsx(ew,{className:"w-4 h-4 text-amber-600"}),m.jsx("span",{children:"表单事件"})]}),m.jsxs("div",{className:"flex items-center gap-1",children:[m.jsxs("button",{onClick:()=>At(!$t),className:`flex items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium smooth-transition ${$t?"bg-green-100 text-green-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-100"}`,title:"查看当前表单字段",children:[m.jsx(uE,{className:"w-3.5 h-3.5"}),"字段"]}),m.jsxs("button",{onClick:()=>mt(!en),className:`flex items-center gap-1 rounded-md px-2 py-1 text-[11px] font-medium smooth-transition ${en?"bg-blue-100 text-blue-700":"text-gray-400 hover:text-gray-600 hover:bg-gray-100"}`,title:"查看帮助文档",children:[m.jsx(vR,{className:"w-3.5 h-3.5"}),"帮助"]})]})]}),footer:m.jsx("button",{onClick:()=>{Dt(!1),mt(!1),At(!1)},className:"rounded-md bg-indigo-600 px-4 py-1.5 text-[13px] font-medium text-white hover:bg-indigo-700 smooth-transition",children:"完成"}),width:en||$t?1060:640,centered:!0,destroyOnClose:!0,styles:{body:en||$t?{height:"60vh",overflow:"hidden"}:{maxHeight:"60vh",overflowY:"auto"}},children:m.jsxs("div",{className:en||$t?"flex gap-4 h-full":"",children:[m.jsxs("div",{className:`space-y-5 py-2 ${en||$t?"flex-1 min-w-0 overflow-y-auto pr-1":""}`,children:[m.jsxs("div",{children:[m.jsx("label",{className:"block text-[12px] font-medium text-gray-600 mb-1.5",children:"初始化事件 (onInit)"}),m.jsx("p",{className:"text-[10px] text-gray-400 mb-1.5",children:"表单加载后执行的 JavaScript 代码,支持 async/await。可用参数:form (表单实例), fields (字段数据)"}),m.jsxs("div",{className:"relative",children:[m.jsx("textarea",{value:p.onInit||"",onChange:Ue=>x({...p,onInit:Ue.target.value}),onFocus:Ue=>{xn.current={element:Ue.target,eventKey:"onInit"}},onSelect:Ue=>{xn.current={element:Ue.target,eventKey:"onInit"}},rows:8,className:"w-full border border-gray-200 rounded-lg px-3 py-2 text-[13px] font-mono outline-none focus:border-amber-400 focus:ring-1 focus:ring-amber-200 smooth-transition resize-none bg-gray-50",placeholder:`// 支持异步函数 (async/await)
|
|
716
716
|
// 例如:
|
|
717
717
|
// var result = await fetch('/api/data');
|
|
718
718
|
// var data = await result.json();
|
package/designer/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/api/workflow/designer-v2/vite.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>designer</title>
|
|
8
|
-
<script type="module" crossorigin src="/api/workflow/designer-v2/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/api/workflow/designer-v2/assets/index-Qp1zkbew.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/api/workflow/designer-v2/assets/index-BVsRCpLO.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
@@ -463,6 +463,7 @@ router.put('/am/flows', async function (req, res) {
|
|
|
463
463
|
let spaceId = flowCome["space"];
|
|
464
464
|
let formId = flowCome["form"];
|
|
465
465
|
let flowId = flowCome["id"];
|
|
466
|
+
let upgraded = flowCome['upgraded'];
|
|
466
467
|
let now = new Date();
|
|
467
468
|
|
|
468
469
|
await designerManager.checkBeforeFlow(spaceId, formId);
|
|
@@ -593,6 +594,9 @@ router.put('/am/flows', async function (req, res) {
|
|
|
593
594
|
if (updateObj.$push) {
|
|
594
595
|
updateData.$push = updateObj.$push;
|
|
595
596
|
}
|
|
597
|
+
|
|
598
|
+
updateData.upgraded = upgraded;
|
|
599
|
+
|
|
596
600
|
await objectql.getObject('flows').update(flowId, updateData);
|
|
597
601
|
console.log('update', flowId, 'end');
|
|
598
602
|
updatedFlows.push(await flowCollection.findOne({_id: flowId}));
|