@qfei-design/make-app-approval 0.0.0-stage → 0.1.0

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.
Files changed (41) hide show
  1. package/PUBLIC_API.md +129 -0
  2. package/README.md +65 -2
  3. package/capabilities.json +76 -0
  4. package/dist/detail/approval-task-detail.d.ts +2 -0
  5. package/dist/detail/diagnostics.d.ts +2 -0
  6. package/dist/detail/field-value.d.ts +2 -0
  7. package/dist/detail/index.d.ts +3 -0
  8. package/dist/detail/task-policy.d.ts +18 -0
  9. package/dist/detail/types.d.ts +111 -0
  10. package/dist/detail.cjs +1 -0
  11. package/dist/detail.mjs +500 -0
  12. package/dist/index.cjs +1 -0
  13. package/dist/index.d.ts +21 -0
  14. package/dist/index.mjs +30 -0
  15. package/dist/list/approval-table.d.ts +14 -0
  16. package/dist/list/diagnostics.d.ts +3 -0
  17. package/dist/list/index.d.ts +3 -0
  18. package/dist/list/my-approvals-page.d.ts +2 -0
  19. package/dist/list/page-contract.d.ts +3 -0
  20. package/dist/list/status-label.d.ts +1 -0
  21. package/dist/list/types.d.ts +71 -0
  22. package/dist/list/ui-components.d.ts +44 -0
  23. package/dist/list/use-approval-page.d.ts +12 -0
  24. package/dist/list/virtual-page-loader.d.ts +26 -0
  25. package/dist/list.cjs +1 -0
  26. package/dist/list.mjs +381 -0
  27. package/dist/react/index.d.ts +7 -0
  28. package/dist/react.cjs +1 -0
  29. package/dist/react.mjs +17 -0
  30. package/dist/styles.css +94 -0
  31. package/dist/styles.css.d.ts +1 -0
  32. package/dist/withdrawal.d.ts +14 -0
  33. package/docs/host-integration.md +217 -0
  34. package/docs/implementation-plan.md +61 -0
  35. package/docs/publishing.md +108 -0
  36. package/examples/antd-components.tsx +38 -0
  37. package/examples/detail-integration.tsx +80 -0
  38. package/examples/host-integration.tsx +36 -0
  39. package/package.ai.json +85 -0
  40. package/package.json +117 -4
  41. package/recipes.json +114 -0
@@ -0,0 +1,44 @@
1
+ import type { ComponentType, ReactNode } from "react";
2
+ import type { ApprovalListTab, ApprovalStatusOption } from "./types.js";
3
+ /** 宿主将组件库事件转换成值;包不依赖 DOM Event 或任何日期库对象。 */
4
+ export type ApprovalInputProps = Readonly<{
5
+ id: string;
6
+ ariaLabel: string;
7
+ value: string;
8
+ onChange: (value: string) => void;
9
+ placeholder?: string;
10
+ disabled?: boolean;
11
+ }>;
12
+ export type ApprovalSelectProps = ApprovalInputProps & Readonly<{
13
+ options: readonly ApprovalStatusOption[];
14
+ }>;
15
+ /** value / onChange 使用 YYYY-MM-DD;清空必须回传空字符串。 */
16
+ export type ApprovalDatePickerProps = ApprovalInputProps;
17
+ export type ApprovalButtonProps = Readonly<{
18
+ children: ReactNode;
19
+ htmlType: "button" | "submit";
20
+ variant: "primary" | "default" | "text";
21
+ onClick?: () => void;
22
+ disabled?: boolean;
23
+ loading?: boolean;
24
+ ariaLabel?: string;
25
+ }>;
26
+ export type ApprovalTabsProps = Readonly<{
27
+ items: readonly Readonly<{
28
+ value: ApprovalListTab;
29
+ label: string;
30
+ }>[];
31
+ value: ApprovalListTab;
32
+ onChange: (value: ApprovalListTab) => void;
33
+ ariaLabel: string;
34
+ /** 仅在当前激活的面板渲染一次;宿主 Tabs 负责键盘与 tab/panel 关联。 */
35
+ children: ReactNode;
36
+ }>;
37
+ /** 必须由宿主完整提供;应在模块作用域定义,避免重渲染时创建新的组件类型。 */
38
+ export type ApprovalUIComponents = Readonly<{
39
+ Input: ComponentType<ApprovalInputProps>;
40
+ Select: ComponentType<ApprovalSelectProps>;
41
+ DatePicker: ComponentType<ApprovalDatePickerProps>;
42
+ Button: ComponentType<ApprovalButtonProps>;
43
+ Tabs: ComponentType<ApprovalTabsProps>;
44
+ }>;
@@ -0,0 +1,12 @@
1
+ import type { ApprovalListQuery, ApprovalListProvider, ApprovalLogger, ApprovalPage } from "./types.js";
2
+ type LoadState = ApprovalPage & {
3
+ token: object;
4
+ status: "success" | "error";
5
+ };
6
+ export declare const useApprovalPage: (provider: ApprovalListProvider, query: ApprovalListQuery, refreshKey: string | number | undefined, logger?: ApprovalLogger) => {
7
+ initialPage: LoadState | undefined;
8
+ total: number;
9
+ status: string;
10
+ reload: () => void;
11
+ };
12
+ export {};
@@ -0,0 +1,26 @@
1
+ import type { CanvasTableComponent, IVirtualPageRequestContext } from "@qfei-design/canvas-table";
2
+ import type { ApprovalListItem, ApprovalListProvider, ApprovalListQuery, ApprovalLogger, ApprovalPage } from "./types.js";
3
+ export type VirtualListSnapshot = Readonly<{
4
+ total: number;
5
+ rows: readonly ApprovalListItem[];
6
+ failed: boolean;
7
+ loading: boolean;
8
+ }>;
9
+ type Table = Pick<CanvasTableComponent, "setVirtualPageData" | "markPageLoadFailed" | "getPagesInView" | "getTableData" | "scrollToRow">;
10
+ /** 页面交互不暴露页码;这里只负责 Canvas 的零基数据页。 */
11
+ export declare const createVirtualPageLoader: ({ table, query, initialPage, loadPage, onChange, retryViewport, onReload, logger }: {
12
+ table: Table;
13
+ query: ApprovalListQuery;
14
+ initialPage: ApprovalPage;
15
+ loadPage: ApprovalListProvider["loadPage"];
16
+ onChange: (snapshot: VirtualListSnapshot) => void;
17
+ retryViewport: () => void;
18
+ onReload: () => void;
19
+ logger?: ApprovalLogger;
20
+ }) => {
21
+ load(page: number, request: IVirtualPageRequestContext): void;
22
+ viewportChanged(): void;
23
+ retry(): void;
24
+ dispose(): void;
25
+ };
26
+ export {};
package/dist/list.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";var ne=Object.create;var Z=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var ce=Object.getPrototypeOf,pe=Object.prototype.hasOwnProperty;var de=(e,t,n,I)=>{if(t&&typeof t=="object"||typeof t=="function")for(let T of ie(t))!pe.call(e,T)&&T!==n&&Z(e,T,{get:()=>t[T],enumerable:!(I=le(t,T))||I.enumerable});return e};var ue=(e,t,n)=>(n=e!=null?ne(ce(e)):{},de(t||!e||!e.__esModule?Z(n,"default",{value:e,enumerable:!0}):n,e));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),i=require("react"),fe=require("./index.cjs"),te=e=>e==null||e==="UNSUBMITTED"?"状态未知":fe.getApprovalStatusDisplay(e).label,z=(e,t)=>{try{e?e(t):t.phase==="error"?console.warn("[make-app-approval]",t):console.info("[make-app-approval]",t)}catch{console.warn("[make-app-approval] diagnostic sink failed")}},ae=e=>typeof e=="object"&&e!==null,he=e=>ae(e)?["id","entityKey","recordId"].every(t=>typeof e[t]=="string"&&e[t].trim().length>0)&&["applicationNo","applicationType","applicantName","applicationTime"].every(t=>typeof e[t]=="string")&&["taskId","processInstanceId"].every(t=>e[t]===void 0||typeof e[t]=="string"&&e[t].trim().length>0)&&(typeof e.processStatus=="string"||e.processStatus===null):!1,Y=(e,t)=>{if(!ae(e)||!Array.isArray(e.rows)||!e.rows.every(he)||typeof e.total!="number"||!Number.isSafeInteger(e.total)||e.total<0||e.rows.length>t||e.rows.length>e.total||new Set(e.rows.map(n=>n.id)).size!==e.rows.length)throw new Error("Invalid approval page contract");return{rows:e.rows,total:e.total}},ge=({table:e,query:t,initialPage:n,loadPage:I,onChange:T,retryViewport:V,onReload:F,logger:P})=>{const g=new Map,C=new Set;let j=[];const p=new WeakMap,m=new Set;let w=n,f=n.total,d=0,k=!1,x=!1,y;const D=r=>Number.isSafeInteger(r)&&r>=0&&r*t.pageSize<f,b=(r,a,v)=>z(P,{operation:"list",phase:a,tab:t.tab,page:r+1,pageSize:t.pageSize,rowCount:v}),u=()=>{k||T({total:f,rows:j,failed:x||m.size>0,loading:g.size>0})},N=r=>{r.finished||(r.finished=!0,r.removeAbort(),g.get(r.page)===r&&g.delete(r.page),e.markPageLoadFailed(r.page,r.request),r.controller.abort(),b(r.page,"cancel"))},h=r=>{d=r;const a=e.getPagesInView()??[],v=new Set([d,...a].flatMap(l=>[l-1,l,l+1]).filter(D));for(const l of g.values())v.has(l.page)||N(l);for(const l of m)v.has(l)||m.delete(l)},E=(r,a,v)=>{const l=a.rows.map(s=>{const A={...s,statusLabel:te(s.processStatus)};return p.set(A,s),A});if(!e.setVirtualPageData(l,r,a.total,v)){b(r,"skip");return}f=a.total;try{j=Y({rows:e.getTableData()??[],total:f},Number.MAX_SAFE_INTEGER).rows.map(s=>p.get(s)??s)}catch(s){x=!0,j=[],w=void 0,y&&clearTimeout(y),y=void 0;for(const A of g.values())N(A);throw s}w&&w.total!==f&&(w=void 0),m.delete(r);for(const s of g.values())D(s.page)||N(s);!D(r)&&r>0&&e.scrollToRow(Math.max(0,f-1)),b(r,"success",a.rows.length)},M=()=>{if(k||y)return;const r=[...g.values()].filter(a=>!a.running&&!a.finished).sort((a,v)=>Math.abs(a.page-d)-Math.abs(v.page-d)||a.page-v.page);for(const a of r){if(C.size>=2)break;a.running=!0,C.add(a),b(a.page,"start"),(async()=>{try{const v=await I({...t,page:a.page+1},{signal:a.controller.signal});if(k||a.finished||a.controller.signal.aborted)return;const l=Y(v,t.pageSize);a.finished=!0,a.removeAbort(),g.delete(a.page),E(a.page,l,a.request)}catch{!k&&!a.controller.signal.aborted&&(m.add(a.page),b(a.page,"error"),e.markPageLoadFailed(a.page,a.request))}finally{a.finished||(a.finished=!0,a.removeAbort(),g.get(a.page)===a&&g.delete(a.page)),C.delete(a),u(),M()}})()}u()},O=()=>{y&&clearTimeout(y),y=setTimeout(()=>{y=void 0,M()},120)};return{load(r,a){if(a.useRequestIdentity(),k||x||a.signal.aborted||!D(r)){e.markPageLoadFailed(r,a),b(r,"skip");return}const v=g.get(r);if(v?.request===a&&!v.finished)return;if(v&&N(v),h(r),r===0&&w){const s=w;w=void 0;try{E(0,s,a)}catch{m.add(r),e.markPageLoadFailed(r,a),b(r,"error")}u();return}const l={page:r,request:a,controller:new AbortController,running:!1,finished:!1,removeAbort:()=>{}},c=()=>{N(l),u()};a.signal.addEventListener("abort",c,{once:!0}),l.removeAbort=()=>a.signal.removeEventListener("abort",c),g.set(r,l),O(),u()},viewportChanged(){if(k)return;const r=e.getPagesInView();r?.length&&(h(r[0]),g.size&&O(),u())},retry(){if(!k){if(x){F();return}m.size!==0&&(m.clear(),V(),u())}},dispose(){k=!0,y&&clearTimeout(y),y=void 0;for(const r of g.values())N(r);j=[],m.clear(),w=void 0}}},me=[{key:"applicationNo",title:"申请单编号",width:260},{key:"applicationType",title:"申请单类型",width:180},{key:"applicantName",title:"申请人",width:170},{key:"applicationTime",title:"申请时间",width:220},{key:"statusLabel",title:"流程状态",width:140}].map(e=>({...e,showEllipsis:!0,sortable:!1})),q=40,ve=e=>{const t=i.useRef(void 0);return e.initialPage?o.jsx(be,{...e,initialPage:e.initialPage,restoreScroll:t.current?.query===e.query?t.current.position:void 0,rememberScroll:n=>{t.current={query:e.query,position:n}}}):o.jsx("div",{className:"make-app-approval-canvas",role:"group","aria-label":"审批记录表格"})},be=({components:{Button:e},initialPage:t,query:n,provider:I,themeKey:T,onOpen:V,onReload:F,logger:P,restoreScroll:g,rememberScroll:C})=>{const j=i.useRef(null),p=i.useRef(null),m=i.useRef(null),[w,f]=i.useState(!1),[d,k]=i.useState(0),[x,y]=i.useState({...t,failed:!1,loading:!1}),D=i.useRef(t.rows),b=i.useRef(g),u=i.useRef({provider:I,onOpen:V,onReload:F,logger:P,rememberScroll:C});u.current={provider:I,onOpen:V,onReload:F,logger:P,rememberScroll:C};const N=i.useRef(()=>{});return i.useEffect(()=>{const h=j.current;if(!h)return;let E=!1,M,O,r,a=t.total;z(u.current.logger,{operation:"table",phase:"start"});const v=()=>{E||(f(!0),z(u.current.logger,{operation:"table",phase:"error"}))};return import("@qfei-design/canvas-table").then(l=>{if(E)return;const c=()=>{const A=p.current,$=A?.getScrollState();A&&$&&l.globalEventBus.emitWithNamespace("scroll:change",A.tableId,$)},s=()=>{if(!E)try{const{width:A,height:$}=h.getBoundingClientRect();if(A<=0||$<=0)return;const L=getComputedStyle(h),G={rowHeight:q,headerHeight:40,fontSize:14,fontFamily:L.fontFamily||"Arial, sans-serif",...L.color?{textColor:L.color}:{},...L.getPropertyValue("--make-approval-bg").trim()?{rowBgColor:L.getPropertyValue("--make-approval-bg").trim()}:{},...L.getPropertyValue("--make-approval-header").trim()?{headerBgColor:L.getPropertyValue("--make-approval-header").trim()}:{},...L.getPropertyValue("--make-approval-border").trim()?{borderColor:L.getPropertyValue("--make-approval-border").trim()}:{}},re=Math.max(Math.ceil(300/n.pageSize),Math.ceil($*3/q/n.pageSize)+2)*n.pageSize,J={enabled:!0,totalRowCount:a,pageSize:n.pageSize,maxCachedRows:re};if(p.current){p.current.updateProps({canvasWidth:A,canvasHeight:$,style:G,virtualOptions:J}),p.current.updateCanvasSize(A,$,!0),c();return}p.current=new l.CanvasTableComponent(h,{columns:me,canvasWidth:A,canvasHeight:$,style:G,rowKey:"id",showSN:{enabled:!0,width:64,formatter:(S,R)=>R+1},virtualOptions:J,selectable:{enabled:!1},rowSortable:{enabled:!1},editApplyMode:"controlled",customEdit:S=>{S.cancel()},emptyStateOptions:{text:"暂无审批记录"},bodyRowHeadSuffixOptions:{enabled:!0,width:20,render:({group:S,x:R,height:_,rowData:U})=>{const oe=U?.id,W=new l.RectShape({name:"approval-open",x:R,y:_/2-10,cursor:"pointer",tooltip:"查看审批详情",attrs:{width:20,height:20,fill:"transparent",stroke:"transparent"}});W.addChild(new l.ImgShape({name:"approval-open-icon",x:3,y:3,attrs:{width:14,height:14,img:"data:image/svg+xml;charset=utf-8,"+encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="${L.color||"#64748b"}" stroke-width="1.8"><path d="M8 3H3v5m13-5h5v5M3 16v5h5m13-5v5h-5"/></svg>`)}})),W.on("mousedown",X=>X.stopPropagation?.()),W.on("click",X=>{X.stopPropagation?.();const Q=D.current.find(se=>se.id===oe);Q&&u.current.onOpen(Q)}),S.addChild(W)}}});const B=p.current,K=ge({table:B,query:n,initialPage:t,retryViewport:c,onReload:()=>u.current.onReload(),loadPage:(S,R)=>u.current.provider.loadPage(S,R),logger:S=>z(u.current.logger,S),onChange:S=>{E||(a=S.total,D.current=S.rows,y(R=>R.total===S.total&&R.failed===S.failed&&R.loading===S.loading&&R.rows.length===S.rows.length&&R.rows.every((_,U)=>_===S.rows[U])?R:S))}});m.current=K,O=l.globalEventBus.onWithNamespace("data:load",B.tableId,(S,R)=>K.load(S,R)),r=l.globalEventBus.onWithNamespace("scroll:change",B.tableId,()=>K.viewportChanged()),b.current&&B.scrollTo(b.current.scrollX,b.current.scrollY),f(!1),z(u.current.logger,{operation:"table",phase:"success"})}catch{v()}};N.current=s,M=new ResizeObserver(s),M.observe(h),s()}).catch(v),()=>{E=!0,M?.disconnect(),N.current=()=>{},p.current&&(b.current=p.current.getScrollState(),b.current&&u.current.rememberScroll(b.current)),O?.(),r?.(),m.current?.dispose(),m.current=null,p.current?.destroy(),p.current=null,z(u.current.logger,{operation:"table",phase:"destroy"})}},[t,n,d]),i.useEffect(()=>{N.current()},[T]),o.jsxs("div",{className:"make-app-approval-table-frame","aria-busy":x.loading,children:[o.jsx("div",{ref:j,className:"make-app-approval-canvas",role:"group","aria-label":"审批记录表格"}),w&&o.jsxs("div",{className:"make-app-approval-overlay",role:"alert",children:["表格加载失败 ",o.jsx(e,{htmlType:"button",variant:"default",onClick:()=>{f(!1),k(h=>h+1)},children:"重新加载表格"})]}),!w&&x.failed&&o.jsxs("div",{className:"make-app-approval-table-feedback",role:"alert",children:["部分审批记录加载失败 ",o.jsx(e,{htmlType:"button",variant:"default",onClick:()=>m.current?.retry(),children:"重试加载"})]}),!w&&!x.failed&&x.loading&&o.jsxs("div",{className:"make-app-approval-table-loading",role:"status","aria-label":"正在加载审批记录","aria-live":"polite",children:[o.jsx("span",{className:"make-app-approval-loading-spinner","aria-hidden":"true"}),o.jsx("span",{children:"加载中"})]}),o.jsxs("ul",{className:"make-app-approval-accessible-rows","aria-label":"审批记录文字视图",children:[x.total===0&&o.jsx("li",{children:"暂无审批记录"}),x.rows.map(h=>o.jsxs("li",{children:[o.jsxs("span",{children:[h.applicationNo,",",h.applicationType,",",h.applicantName,",",h.applicationTime,",",te(h.processStatus),"。"]}),o.jsxs(e,{htmlType:"button",variant:"text",onClick:()=>V(h),children:["打开 ",h.applicationNo||h.applicationType," 的审批详情"]})]},h.id))]})]})},we=[],ye=(e,t,n,I)=>{const[T,V]=i.useState(0),[F,P]=i.useState(),g=i.useRef({provider:e,logger:I});g.current={provider:e,logger:I};const C=i.useMemo(()=>({}),[t,n,T]);i.useEffect(()=>{const p=new AbortController,{provider:m,logger:w}=g.current,f={operation:"list",tab:t.tab,page:t.page,pageSize:t.pageSize};z(w,{...f,phase:"start"});let d=!1;return(async()=>{try{const k=await m.loadPage(t,{signal:p.signal});if(p.signal.aborted)return;const x=Y(k,t.pageSize);d=!0,P({...x,token:C,status:"success"}),z(w,{...f,phase:"success",rowCount:x.rows.length})}catch{if(p.signal.aborted)return;d=!0,P({token:C,status:"error",rows:we,total:0}),z(w,{...f,phase:"error"})}})(),()=>{p.abort(),d||z(w,{...f,phase:"cancel"})}},[t,C]);const j=F?.token===C?F:void 0;return{initialPage:j?.status==="success"?j:void 0,total:j?.total??0,status:j?.status??"loading",reload:()=>V(p=>p+1)}},H={keyword:"",processStatus:"",startDate:"",endDate:""},Se=[{value:"pending",label:"待我处理"},{value:"approved",label:"已审批"}],ee=e=>{if(e==="")return!0;if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;const t=new Date(`${e}T00:00:00Z`);return Number.isFinite(t.getTime())&&t.toISOString().slice(0,10)===e},ke=({components:e,provider:t,onOpenApproval:n,statusOptions:I=[],pageSize:T=20,refreshKey:V,themeKey:F,logger:P,className:g})=>{const{Input:C,Select:j,DatePicker:p,Button:m,Tabs:w}=e,f=i.useId(),[d,k]=i.useState(H),[x,y]=i.useState(""),[D,b]=i.useState(""),[u,N]=i.useState({...H,tab:"pending",page:1,pageSize:T}),{initialPage:h,status:E,reload:M}=ye(t,u,V,P),O=i.useRef(!1),r=i.useRef(!0);i.useEffect(()=>(r.current=!0,()=>{r.current=!1}),[]);const a=E==="loading",v=async c=>{if(!O.current){O.current=!0,b(""),z(P,{operation:"open",phase:"start"});try{await n(c),z(P,{operation:"open",phase:"success"})}catch{r.current&&b("审批详情打开失败,请重试"),z(P,{operation:"open",phase:"error"})}finally{O.current=!1}}},l=c=>{c!==u.tab&&(y(""),b(""),N(s=>({...s,tab:c,page:1})))};return o.jsx("section",{className:["make-app-approval",g].filter(Boolean).join(" "),"aria-label":"我的审批",children:o.jsxs(w,{items:Se,value:u.tab,onChange:l,ariaLabel:"审批分类",children:[o.jsxs("form",{className:"make-app-approval-filters",onSubmit:c=>{if(c.preventDefault(),!ee(d.startDate)||!ee(d.endDate)){y("请选择有效日期");return}if(d.startDate&&d.endDate&&d.startDate>d.endDate){y("开始日期不能晚于结束日期");return}y(""),b(""),N(s=>({...s,...d,keyword:d.keyword.trim(),page:1}))},children:[o.jsxs("div",{className:"make-app-approval-filter-field",children:[o.jsx("label",{htmlFor:`${f}-keyword`,children:"申请单号或申请人"}),o.jsx(C,{id:`${f}-keyword`,ariaLabel:"申请单号或申请人",placeholder:"搜索申请单号、申请人",value:d.keyword,onChange:c=>k(s=>({...s,keyword:c}))})]}),o.jsxs("div",{className:"make-app-approval-filter-field",children:[o.jsx("label",{htmlFor:`${f}-status`,children:"流程状态"}),o.jsx(j,{id:`${f}-status`,ariaLabel:"流程状态",value:d.processStatus,options:[{value:"",label:"全部流程状态"},...I],onChange:c=>k(s=>({...s,processStatus:c}))})]}),o.jsxs("fieldset",{className:"make-app-approval-date-field",children:[o.jsx("legend",{children:"申请时间"}),o.jsxs("div",{className:"make-app-approval-date-range",children:[o.jsx("div",{className:"make-app-approval-date-control",children:o.jsx(p,{id:`${f}-start`,ariaLabel:"申请开始日期",placeholder:"开始日期",value:d.startDate,onChange:c=>k(s=>({...s,startDate:c}))})}),o.jsx("span",{children:"至"}),o.jsx("div",{className:"make-app-approval-date-control",children:o.jsx(p,{id:`${f}-end`,ariaLabel:"申请结束日期",placeholder:"结束日期",value:d.endDate,onChange:c=>k(s=>({...s,endDate:c}))})})]})]}),o.jsxs("div",{className:"make-app-approval-filter-actions",children:[o.jsx(m,{htmlType:"submit",variant:"primary",children:"查询"}),o.jsx(m,{htmlType:"button",variant:"default",onClick:()=>{k(H),y(""),b(""),N(c=>({...c,...H,page:1}))},children:"重置"}),o.jsx(m,{htmlType:"button",variant:"default",disabled:a,loading:a,onClick:M,children:"刷新"})]})]}),x&&o.jsx("p",{role:"alert",className:"make-app-approval-error",children:x}),D&&o.jsx("p",{role:"alert",className:"make-app-approval-error",children:D}),o.jsxs("div",{className:"make-app-approval-results","aria-busy":a,children:[o.jsx(ve,{components:e,initialPage:h,query:u,provider:t,onOpen:c=>{v(c)},onReload:M,themeKey:F,logger:P}),a&&o.jsx("div",{className:"make-app-approval-overlay",role:"status",children:"正在加载审批记录…"}),E==="error"&&o.jsxs("div",{className:"make-app-approval-overlay",role:"alert",children:[o.jsx("span",{children:"审批列表加载失败,请重试"}),o.jsx(m,{htmlType:"button",variant:"default",onClick:M,children:"重试"})]})]})]})})},xe=e=>{const t=e.pageSize??20;if(!e.scopeKey.trim())throw new Error("MyApprovalsPage requires scopeKey");for(const n of["Input","Select","DatePicker","Button","Tabs"])if(!e.components?.[n])throw new Error(`MyApprovalsPage requires components.${n}`);if(!Number.isSafeInteger(t)||t<1||t>200)throw new Error("pageSize must be an integer from 1 to 200");return o.jsx(ke,{...e,pageSize:t},JSON.stringify([e.scopeKey,t]))};exports.MyApprovalsPage=xe;
package/dist/list.mjs ADDED
@@ -0,0 +1,381 @@
1
+ import { jsx as n, jsxs as N } from "react/jsx-runtime";
2
+ import { useRef as E, useState as x, useEffect as j, useMemo as ie, useId as ce } from "react";
3
+ import { getApprovalStatusDisplay as pe } from "./index.mjs";
4
+ const re = (e) => e == null || e === "UNSUBMITTED" ? "状态未知" : pe(e).label, I = (e, a) => {
5
+ try {
6
+ e ? e(a) : a.phase === "error" ? console.warn("[make-app-approval]", a) : console.info("[make-app-approval]", a);
7
+ } catch {
8
+ console.warn("[make-app-approval] diagnostic sink failed");
9
+ }
10
+ }, oe = (e) => typeof e == "object" && e !== null, de = (e) => oe(e) ? ["id", "entityKey", "recordId"].every((a) => typeof e[a] == "string" && e[a].trim().length > 0) && ["applicationNo", "applicationType", "applicantName", "applicationTime"].every((a) => typeof e[a] == "string") && ["taskId", "processInstanceId"].every((a) => e[a] === void 0 || typeof e[a] == "string" && e[a].trim().length > 0) && (typeof e.processStatus == "string" || e.processStatus === null) : !1, Q = (e, a) => {
11
+ if (!oe(e) || !Array.isArray(e.rows) || !e.rows.every(de) || typeof e.total != "number" || !Number.isSafeInteger(e.total) || e.total < 0 || e.rows.length > a || e.rows.length > e.total || new Set(e.rows.map((m) => m.id)).size !== e.rows.length)
12
+ throw new Error("Invalid approval page contract");
13
+ return { rows: e.rows, total: e.total };
14
+ }, ue = ({ table: e, query: a, initialPage: m, loadPage: F, onChange: H, retryViewport: $, onReload: B, logger: R }) => {
15
+ const f = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Set();
16
+ let T = [];
17
+ const i = /* @__PURE__ */ new WeakMap(), h = /* @__PURE__ */ new Set();
18
+ let b = m, d = m.total, c = 0, k = !1, S = !1, w;
19
+ const M = (r) => Number.isSafeInteger(r) && r >= 0 && r * a.pageSize < d, v = (r, t, g) => I(R, { operation: "list", phase: t, tab: a.tab, page: r + 1, pageSize: a.pageSize, rowCount: g }), p = () => {
20
+ k || H({ total: d, rows: T, failed: S || h.size > 0, loading: f.size > 0 });
21
+ }, C = (r) => {
22
+ r.finished || (r.finished = !0, r.removeAbort(), f.get(r.page) === r && f.delete(r.page), e.markPageLoadFailed(r.page, r.request), r.controller.abort(), v(r.page, "cancel"));
23
+ }, u = (r) => {
24
+ c = r;
25
+ const t = e.getPagesInView() ?? [], g = new Set([c, ...t].flatMap((s) => [s - 1, s, s + 1]).filter(M));
26
+ for (const s of f.values()) g.has(s.page) || C(s);
27
+ for (const s of h) g.has(s) || h.delete(s);
28
+ }, D = (r, t, g) => {
29
+ const s = t.rows.map((o) => {
30
+ const A = { ...o, statusLabel: re(o.processStatus) };
31
+ return i.set(A, o), A;
32
+ });
33
+ if (!e.setVirtualPageData(s, r, t.total, g)) {
34
+ v(r, "skip");
35
+ return;
36
+ }
37
+ d = t.total;
38
+ try {
39
+ T = Q({ rows: e.getTableData() ?? [], total: d }, Number.MAX_SAFE_INTEGER).rows.map((o) => i.get(o) ?? o);
40
+ } catch (o) {
41
+ S = !0, T = [], b = void 0, w && clearTimeout(w), w = void 0;
42
+ for (const A of f.values()) C(A);
43
+ throw o;
44
+ }
45
+ b && b.total !== d && (b = void 0), h.delete(r);
46
+ for (const o of f.values()) M(o.page) || C(o);
47
+ !M(r) && r > 0 && e.scrollToRow(Math.max(0, d - 1)), v(r, "success", t.rows.length);
48
+ }, L = () => {
49
+ if (k || w) return;
50
+ const r = [...f.values()].filter((t) => !t.running && !t.finished).sort((t, g) => Math.abs(t.page - c) - Math.abs(g.page - c) || t.page - g.page);
51
+ for (const t of r) {
52
+ if (z.size >= 2) break;
53
+ t.running = !0, z.add(t), v(t.page, "start"), (async () => {
54
+ try {
55
+ const g = await F({ ...a, page: t.page + 1 }, { signal: t.controller.signal });
56
+ if (k || t.finished || t.controller.signal.aborted) return;
57
+ const s = Q(g, a.pageSize);
58
+ t.finished = !0, t.removeAbort(), f.delete(t.page), D(t.page, s, t.request);
59
+ } catch {
60
+ !k && !t.controller.signal.aborted && (h.add(t.page), v(t.page, "error"), e.markPageLoadFailed(t.page, t.request));
61
+ } finally {
62
+ t.finished || (t.finished = !0, t.removeAbort(), f.get(t.page) === t && f.delete(t.page)), z.delete(t), p(), L();
63
+ }
64
+ })();
65
+ }
66
+ p();
67
+ }, O = () => {
68
+ w && clearTimeout(w), w = setTimeout(() => {
69
+ w = void 0, L();
70
+ }, 120);
71
+ };
72
+ return {
73
+ load(r, t) {
74
+ if (t.useRequestIdentity(), k || S || t.signal.aborted || !M(r)) {
75
+ e.markPageLoadFailed(r, t), v(r, "skip");
76
+ return;
77
+ }
78
+ const g = f.get(r);
79
+ if (g?.request === t && !g.finished) return;
80
+ if (g && C(g), u(r), r === 0 && b) {
81
+ const o = b;
82
+ b = void 0;
83
+ try {
84
+ D(0, o, t);
85
+ } catch {
86
+ h.add(r), e.markPageLoadFailed(r, t), v(r, "error");
87
+ }
88
+ p();
89
+ return;
90
+ }
91
+ const s = { page: r, request: t, controller: new AbortController(), running: !1, finished: !1, removeAbort: () => {
92
+ } }, l = () => {
93
+ C(s), p();
94
+ };
95
+ t.signal.addEventListener("abort", l, { once: !0 }), s.removeAbort = () => t.signal.removeEventListener("abort", l), f.set(r, s), O(), p();
96
+ },
97
+ viewportChanged() {
98
+ if (k) return;
99
+ const r = e.getPagesInView();
100
+ r?.length && (u(r[0]), f.size && O(), p());
101
+ },
102
+ retry() {
103
+ if (!k) {
104
+ if (S) {
105
+ B();
106
+ return;
107
+ }
108
+ h.size !== 0 && (h.clear(), $(), p());
109
+ }
110
+ },
111
+ dispose() {
112
+ k = !0, w && clearTimeout(w), w = void 0;
113
+ for (const r of f.values()) C(r);
114
+ T = [], h.clear(), b = void 0;
115
+ }
116
+ };
117
+ }, fe = [
118
+ { key: "applicationNo", title: "申请单编号", width: 260 },
119
+ { key: "applicationType", title: "申请单类型", width: 180 },
120
+ { key: "applicantName", title: "申请人", width: 170 },
121
+ { key: "applicationTime", title: "申请时间", width: 220 },
122
+ { key: "statusLabel", title: "流程状态", width: 140 }
123
+ ].map((e) => ({ ...e, showEllipsis: !0, sortable: !1 })), te = 40, he = (e) => {
124
+ const a = E(void 0);
125
+ return e.initialPage ? /* @__PURE__ */ n(
126
+ ge,
127
+ {
128
+ ...e,
129
+ initialPage: e.initialPage,
130
+ restoreScroll: a.current?.query === e.query ? a.current.position : void 0,
131
+ rememberScroll: (m) => {
132
+ a.current = { query: e.query, position: m };
133
+ }
134
+ }
135
+ ) : /* @__PURE__ */ n("div", { className: "make-app-approval-canvas", role: "group", "aria-label": "审批记录表格" });
136
+ }, ge = ({ components: { Button: e }, initialPage: a, query: m, provider: F, themeKey: H, onOpen: $, onReload: B, logger: R, restoreScroll: f, rememberScroll: z }) => {
137
+ const T = E(null), i = E(null), h = E(null), [b, d] = x(!1), [c, k] = x(0), [S, w] = x({ ...a, failed: !1, loading: !1 }), M = E(a.rows), v = E(f), p = E({ provider: F, onOpen: $, onReload: B, logger: R, rememberScroll: z });
138
+ p.current = { provider: F, onOpen: $, onReload: B, logger: R, rememberScroll: z };
139
+ const C = E(() => {
140
+ });
141
+ return j(() => {
142
+ const u = T.current;
143
+ if (!u) return;
144
+ let D = !1, L, O, r, t = a.total;
145
+ I(p.current.logger, { operation: "table", phase: "start" });
146
+ const g = () => {
147
+ D || (d(!0), I(p.current.logger, { operation: "table", phase: "error" }));
148
+ };
149
+ return import("@qfei-design/canvas-table").then((s) => {
150
+ if (D) return;
151
+ const l = () => {
152
+ const A = i.current, W = A?.getScrollState();
153
+ A && W && s.globalEventBus.emitWithNamespace("scroll:change", A.tableId, W);
154
+ }, o = () => {
155
+ if (!D)
156
+ try {
157
+ const { width: A, height: W } = u.getBoundingClientRect();
158
+ if (A <= 0 || W <= 0) return;
159
+ const V = getComputedStyle(u), Z = {
160
+ rowHeight: te,
161
+ headerHeight: 40,
162
+ fontSize: 14,
163
+ fontFamily: V.fontFamily || "Arial, sans-serif",
164
+ ...V.color ? { textColor: V.color } : {},
165
+ ...V.getPropertyValue("--make-approval-bg").trim() ? { rowBgColor: V.getPropertyValue("--make-approval-bg").trim() } : {},
166
+ ...V.getPropertyValue("--make-approval-header").trim() ? { headerBgColor: V.getPropertyValue("--make-approval-header").trim() } : {},
167
+ ...V.getPropertyValue("--make-approval-border").trim() ? { borderColor: V.getPropertyValue("--make-approval-border").trim() } : {}
168
+ }, ne = Math.max(Math.ceil(300 / m.pageSize), Math.ceil(W * 3 / te / m.pageSize) + 2) * m.pageSize, q = { enabled: !0, totalRowCount: t, pageSize: m.pageSize, maxCachedRows: ne };
169
+ if (i.current) {
170
+ i.current.updateProps({ canvasWidth: A, canvasHeight: W, style: Z, virtualOptions: q }), i.current.updateCanvasSize(A, W, !0), l();
171
+ return;
172
+ }
173
+ i.current = new s.CanvasTableComponent(u, {
174
+ columns: fe,
175
+ canvasWidth: A,
176
+ canvasHeight: W,
177
+ style: Z,
178
+ rowKey: "id",
179
+ showSN: { enabled: !0, width: 64, formatter: (y, P) => P + 1 },
180
+ virtualOptions: q,
181
+ selectable: { enabled: !1 },
182
+ rowSortable: { enabled: !1 },
183
+ editApplyMode: "controlled",
184
+ customEdit: (y) => {
185
+ y.cancel();
186
+ },
187
+ emptyStateOptions: { text: "暂无审批记录" },
188
+ bodyRowHeadSuffixOptions: {
189
+ enabled: !0,
190
+ width: 20,
191
+ render: ({ group: y, x: P, height: Y, rowData: G }) => {
192
+ const se = G?.id, _ = new s.RectShape({ name: "approval-open", x: P, y: Y / 2 - 10, cursor: "pointer", tooltip: "查看审批详情", attrs: { width: 20, height: 20, fill: "transparent", stroke: "transparent" } });
193
+ _.addChild(new s.ImgShape({ name: "approval-open-icon", x: 3, y: 3, attrs: {
194
+ width: 14,
195
+ height: 14,
196
+ img: "data:image/svg+xml;charset=utf-8," + encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="${V.color || "#64748b"}" stroke-width="1.8"><path d="M8 3H3v5m13-5h5v5M3 16v5h5m13-5v5h-5"/></svg>`)
197
+ } })), _.on("mousedown", (J) => J.stopPropagation?.()), _.on("click", (J) => {
198
+ J.stopPropagation?.();
199
+ const ee = M.current.find((le) => le.id === se);
200
+ ee && p.current.onOpen(ee);
201
+ }), y.addChild(_);
202
+ }
203
+ }
204
+ });
205
+ const K = i.current, X = ue({
206
+ table: K,
207
+ query: m,
208
+ initialPage: a,
209
+ // 公开滚动同步事件会重新检测缺页,不移动视口,也不复用失败身份。
210
+ retryViewport: l,
211
+ onReload: () => p.current.onReload(),
212
+ loadPage: (y, P) => p.current.provider.loadPage(y, P),
213
+ logger: (y) => I(p.current.logger, y),
214
+ onChange: (y) => {
215
+ D || (t = y.total, M.current = y.rows, w((P) => P.total === y.total && P.failed === y.failed && P.loading === y.loading && P.rows.length === y.rows.length && P.rows.every((Y, G) => Y === y.rows[G]) ? P : y));
216
+ }
217
+ });
218
+ h.current = X, O = s.globalEventBus.onWithNamespace("data:load", K.tableId, (y, P) => X.load(y, P)), r = s.globalEventBus.onWithNamespace("scroll:change", K.tableId, () => X.viewportChanged()), v.current && K.scrollTo(v.current.scrollX, v.current.scrollY), d(!1), I(p.current.logger, { operation: "table", phase: "success" });
219
+ } catch {
220
+ g();
221
+ }
222
+ };
223
+ C.current = o, L = new ResizeObserver(o), L.observe(u), o();
224
+ }).catch(g), () => {
225
+ D = !0, L?.disconnect(), C.current = () => {
226
+ }, i.current && (v.current = i.current.getScrollState(), v.current && p.current.rememberScroll(v.current)), O?.(), r?.(), h.current?.dispose(), h.current = null, i.current?.destroy(), i.current = null, I(p.current.logger, { operation: "table", phase: "destroy" });
227
+ };
228
+ }, [a, m, c]), j(() => {
229
+ C.current();
230
+ }, [H]), /* @__PURE__ */ N("div", { className: "make-app-approval-table-frame", "aria-busy": S.loading, children: [
231
+ /* @__PURE__ */ n("div", { ref: T, className: "make-app-approval-canvas", role: "group", "aria-label": "审批记录表格" }),
232
+ b && /* @__PURE__ */ N("div", { className: "make-app-approval-overlay", role: "alert", children: [
233
+ "表格加载失败 ",
234
+ /* @__PURE__ */ n(e, { htmlType: "button", variant: "default", onClick: () => {
235
+ d(!1), k((u) => u + 1);
236
+ }, children: "重新加载表格" })
237
+ ] }),
238
+ !b && S.failed && /* @__PURE__ */ N("div", { className: "make-app-approval-table-feedback", role: "alert", children: [
239
+ "部分审批记录加载失败 ",
240
+ /* @__PURE__ */ n(e, { htmlType: "button", variant: "default", onClick: () => h.current?.retry(), children: "重试加载" })
241
+ ] }),
242
+ !b && !S.failed && S.loading && /* @__PURE__ */ N("div", { className: "make-app-approval-table-loading", role: "status", "aria-label": "正在加载审批记录", "aria-live": "polite", children: [
243
+ /* @__PURE__ */ n("span", { className: "make-app-approval-loading-spinner", "aria-hidden": "true" }),
244
+ /* @__PURE__ */ n("span", { children: "加载中" })
245
+ ] }),
246
+ /* @__PURE__ */ N("ul", { className: "make-app-approval-accessible-rows", "aria-label": "审批记录文字视图", children: [
247
+ S.total === 0 && /* @__PURE__ */ n("li", { children: "暂无审批记录" }),
248
+ S.rows.map((u) => /* @__PURE__ */ N("li", { children: [
249
+ /* @__PURE__ */ N("span", { children: [
250
+ u.applicationNo,
251
+ ",",
252
+ u.applicationType,
253
+ ",",
254
+ u.applicantName,
255
+ ",",
256
+ u.applicationTime,
257
+ ",",
258
+ re(u.processStatus),
259
+ "。"
260
+ ] }),
261
+ /* @__PURE__ */ N(e, { htmlType: "button", variant: "text", onClick: () => $(u), children: [
262
+ "打开 ",
263
+ u.applicationNo || u.applicationType,
264
+ " 的审批详情"
265
+ ] })
266
+ ] }, u.id))
267
+ ] })
268
+ ] });
269
+ }, me = [], ve = (e, a, m, F) => {
270
+ const [H, $] = x(0), [B, R] = x(), f = E({ provider: e, logger: F });
271
+ f.current = { provider: e, logger: F };
272
+ const z = ie(() => ({}), [a, m, H]);
273
+ j(() => {
274
+ const i = new AbortController(), { provider: h, logger: b } = f.current, d = { operation: "list", tab: a.tab, page: a.page, pageSize: a.pageSize };
275
+ I(b, { ...d, phase: "start" });
276
+ let c = !1;
277
+ return (async () => {
278
+ try {
279
+ const k = await h.loadPage(a, { signal: i.signal });
280
+ if (i.signal.aborted) return;
281
+ const S = Q(k, a.pageSize);
282
+ c = !0, R({ ...S, token: z, status: "success" }), I(b, { ...d, phase: "success", rowCount: S.rows.length });
283
+ } catch {
284
+ if (i.signal.aborted) return;
285
+ c = !0, R({ token: z, status: "error", rows: me, total: 0 }), I(b, { ...d, phase: "error" });
286
+ }
287
+ })(), () => {
288
+ i.abort(), c || I(b, { ...d, phase: "cancel" });
289
+ };
290
+ }, [a, z]);
291
+ const T = B?.token === z ? B : void 0;
292
+ return {
293
+ initialPage: T?.status === "success" ? T : void 0,
294
+ total: T?.total ?? 0,
295
+ status: T?.status ?? "loading",
296
+ reload: () => $((i) => i + 1)
297
+ };
298
+ }, U = { keyword: "", processStatus: "", startDate: "", endDate: "" }, be = [{ value: "pending", label: "待我处理" }, { value: "approved", label: "已审批" }], ae = (e) => {
299
+ if (e === "") return !0;
300
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(e)) return !1;
301
+ const a = /* @__PURE__ */ new Date(`${e}T00:00:00Z`);
302
+ return Number.isFinite(a.getTime()) && a.toISOString().slice(0, 10) === e;
303
+ }, we = ({ components: e, provider: a, onOpenApproval: m, statusOptions: F = [], pageSize: H = 20, refreshKey: $, themeKey: B, logger: R, className: f }) => {
304
+ const { Input: z, Select: T, DatePicker: i, Button: h, Tabs: b } = e, d = ce(), [c, k] = x(U), [S, w] = x(""), [M, v] = x(""), [p, C] = x({ ...U, tab: "pending", page: 1, pageSize: H }), { initialPage: u, status: D, reload: L } = ve(a, p, $, R), O = E(!1), r = E(!0);
305
+ j(() => (r.current = !0, () => {
306
+ r.current = !1;
307
+ }), []);
308
+ const t = D === "loading", g = async (l) => {
309
+ if (!O.current) {
310
+ O.current = !0, v(""), I(R, { operation: "open", phase: "start" });
311
+ try {
312
+ await m(l), I(R, { operation: "open", phase: "success" });
313
+ } catch {
314
+ r.current && v("审批详情打开失败,请重试"), I(R, { operation: "open", phase: "error" });
315
+ } finally {
316
+ O.current = !1;
317
+ }
318
+ }
319
+ }, s = (l) => {
320
+ l !== p.tab && (w(""), v(""), C((o) => ({ ...o, tab: l, page: 1 })));
321
+ };
322
+ return /* @__PURE__ */ n("section", { className: ["make-app-approval", f].filter(Boolean).join(" "), "aria-label": "我的审批", children: /* @__PURE__ */ N(b, { items: be, value: p.tab, onChange: s, ariaLabel: "审批分类", children: [
323
+ /* @__PURE__ */ N("form", { className: "make-app-approval-filters", onSubmit: (l) => {
324
+ if (l.preventDefault(), !ae(c.startDate) || !ae(c.endDate)) {
325
+ w("请选择有效日期");
326
+ return;
327
+ }
328
+ if (c.startDate && c.endDate && c.startDate > c.endDate) {
329
+ w("开始日期不能晚于结束日期");
330
+ return;
331
+ }
332
+ w(""), v(""), C((o) => ({ ...o, ...c, keyword: c.keyword.trim(), page: 1 }));
333
+ }, children: [
334
+ /* @__PURE__ */ N("div", { className: "make-app-approval-filter-field", children: [
335
+ /* @__PURE__ */ n("label", { htmlFor: `${d}-keyword`, children: "申请单号或申请人" }),
336
+ /* @__PURE__ */ n(z, { id: `${d}-keyword`, ariaLabel: "申请单号或申请人", placeholder: "搜索申请单号、申请人", value: c.keyword, onChange: (l) => k((o) => ({ ...o, keyword: l })) })
337
+ ] }),
338
+ /* @__PURE__ */ N("div", { className: "make-app-approval-filter-field", children: [
339
+ /* @__PURE__ */ n("label", { htmlFor: `${d}-status`, children: "流程状态" }),
340
+ /* @__PURE__ */ n(T, { id: `${d}-status`, ariaLabel: "流程状态", value: c.processStatus, options: [{ value: "", label: "全部流程状态" }, ...F], onChange: (l) => k((o) => ({ ...o, processStatus: l })) })
341
+ ] }),
342
+ /* @__PURE__ */ N("fieldset", { className: "make-app-approval-date-field", children: [
343
+ /* @__PURE__ */ n("legend", { children: "申请时间" }),
344
+ /* @__PURE__ */ N("div", { className: "make-app-approval-date-range", children: [
345
+ /* @__PURE__ */ n("div", { className: "make-app-approval-date-control", children: /* @__PURE__ */ n(i, { id: `${d}-start`, ariaLabel: "申请开始日期", placeholder: "开始日期", value: c.startDate, onChange: (l) => k((o) => ({ ...o, startDate: l })) }) }),
346
+ /* @__PURE__ */ n("span", { children: "至" }),
347
+ /* @__PURE__ */ n("div", { className: "make-app-approval-date-control", children: /* @__PURE__ */ n(i, { id: `${d}-end`, ariaLabel: "申请结束日期", placeholder: "结束日期", value: c.endDate, onChange: (l) => k((o) => ({ ...o, endDate: l })) }) })
348
+ ] })
349
+ ] }),
350
+ /* @__PURE__ */ N("div", { className: "make-app-approval-filter-actions", children: [
351
+ /* @__PURE__ */ n(h, { htmlType: "submit", variant: "primary", children: "查询" }),
352
+ /* @__PURE__ */ n(h, { htmlType: "button", variant: "default", onClick: () => {
353
+ k(U), w(""), v(""), C((l) => ({ ...l, ...U, page: 1 }));
354
+ }, children: "重置" }),
355
+ /* @__PURE__ */ n(h, { htmlType: "button", variant: "default", disabled: t, loading: t, onClick: L, children: "刷新" })
356
+ ] })
357
+ ] }),
358
+ S && /* @__PURE__ */ n("p", { role: "alert", className: "make-app-approval-error", children: S }),
359
+ M && /* @__PURE__ */ n("p", { role: "alert", className: "make-app-approval-error", children: M }),
360
+ /* @__PURE__ */ N("div", { className: "make-app-approval-results", "aria-busy": t, children: [
361
+ /* @__PURE__ */ n(he, { components: e, initialPage: u, query: p, provider: a, onOpen: (l) => {
362
+ g(l);
363
+ }, onReload: L, themeKey: B, logger: R }),
364
+ t && /* @__PURE__ */ n("div", { className: "make-app-approval-overlay", role: "status", children: "正在加载审批记录…" }),
365
+ D === "error" && /* @__PURE__ */ N("div", { className: "make-app-approval-overlay", role: "alert", children: [
366
+ /* @__PURE__ */ n("span", { children: "审批列表加载失败,请重试" }),
367
+ /* @__PURE__ */ n(h, { htmlType: "button", variant: "default", onClick: L, children: "重试" })
368
+ ] })
369
+ ] })
370
+ ] }) });
371
+ }, Ne = (e) => {
372
+ const a = e.pageSize ?? 20;
373
+ if (!e.scopeKey.trim()) throw new Error("MyApprovalsPage requires scopeKey");
374
+ for (const m of ["Input", "Select", "DatePicker", "Button", "Tabs"])
375
+ if (!e.components?.[m]) throw new Error(`MyApprovalsPage requires components.${m}`);
376
+ if (!Number.isSafeInteger(a) || a < 1 || a > 200) throw new Error("pageSize must be an integer from 1 to 200");
377
+ return /* @__PURE__ */ n(we, { ...e, pageSize: a }, JSON.stringify([e.scopeKey, a]));
378
+ };
379
+ export {
380
+ Ne as MyApprovalsPage
381
+ };
@@ -0,0 +1,7 @@
1
+ import type { CSSProperties } from "react";
2
+ export type ApprovalStatusProps = {
3
+ value: unknown;
4
+ className?: string;
5
+ style?: CSSProperties;
6
+ };
7
+ export declare const ApprovalStatus: ({ value, className, style }: ApprovalStatusProps) => import("react").JSX.Element;
package/dist/react.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),r=require("./index.cjs"),n=({value:e,className:a,style:s})=>{const t=r.getApprovalStatusDisplay(e);return o.jsx("span",{className:["make-app-approval-status",a].filter(Boolean).join(" "),"data-tone":t.tone,style:s,children:t.label})};exports.ApprovalStatus=n;
package/dist/react.mjs ADDED
@@ -0,0 +1,17 @@
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ import { getApprovalStatusDisplay as r } from "./index.mjs";
3
+ const n = ({ value: a, className: o, style: p }) => {
4
+ const t = r(a);
5
+ return /* @__PURE__ */ s(
6
+ "span",
7
+ {
8
+ className: ["make-app-approval-status", o].filter(Boolean).join(" "),
9
+ "data-tone": t.tone,
10
+ style: p,
11
+ children: t.label
12
+ }
13
+ );
14
+ };
15
+ export {
16
+ n as ApprovalStatus
17
+ };
@@ -0,0 +1,94 @@
1
+ .make-app-approval-status {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ padding: 2px 8px;
5
+ border-radius: 4px;
6
+ font-size: 12px;
7
+ line-height: 20px;
8
+ white-space: nowrap;
9
+ color: var(--make-approval-text, hsl(var(--muted-foreground, 160 8% 42%)));
10
+ background: var(--make-approval-surface, hsl(var(--muted, 150 22% 94%)));
11
+ }
12
+
13
+ .make-app-approval-status[data-tone="processing"],
14
+ .make-app-approval-status[data-tone="success"] {
15
+ color: var(--make-approval-primary, hsl(var(--primary, 176 77% 26%)));
16
+ }
17
+
18
+ .make-app-approval-status[data-tone="danger"],
19
+ .make-app-approval-status[data-tone="unknown"] {
20
+ color: var(--make-approval-error, var(--make-mobile-error, #dc2626));
21
+ }
22
+
23
+ .make-app-approval {
24
+ --make-approval-bg: hsl(var(--background, 0 0% 100%));
25
+ --make-approval-header: hsl(var(--muted, 210 20% 97%));
26
+ --make-approval-border: hsl(var(--border, 214 25% 89%));
27
+ --make-approval-foreground: hsl(var(--foreground, 222 30% 16%));
28
+ --make-approval-primary: hsl(var(--primary, 176 77% 26%));
29
+ --make-approval-primary-foreground: hsl(var(--primary-foreground, 0 0% 100%));
30
+ --make-approval-muted: hsl(var(--muted-foreground, 215 16% 47%));
31
+ --make-approval-radius: var(--radius, 6px);
32
+ color: var(--make-approval-foreground);
33
+ background: var(--make-approval-bg);
34
+ border: 1px solid var(--make-approval-border);
35
+ border-radius: var(--make-approval-radius);
36
+ font-family: inherit;
37
+ font-size: 14px;
38
+ line-height: 1.5;
39
+ width: 100%;
40
+ min-width: 0;
41
+ box-sizing: border-box;
42
+ }
43
+ .make-app-approval-filters { display: flex; align-items: end; flex-wrap: wrap; gap: 14px; padding: 20px; }
44
+ .make-app-approval-filter-field { display: flex; flex-direction: column; gap: 6px; width: 200px; min-width: 0; }
45
+ .make-app-approval-filter-field > label { color: var(--make-approval-muted); font-size: 12px; }
46
+ .make-app-approval-date-field { border: 0; padding: 0; margin: 0; min-width: 0; }
47
+ .make-app-approval-date-field > legend { padding: 0; margin-bottom: 6px; color: var(--make-approval-muted); font-size: 12px; }
48
+ .make-app-approval-date-range, .make-app-approval-filter-actions { display: flex; align-items: center; gap: 8px; }
49
+ .make-app-approval-date-control { min-width: 0; width: 145px; }
50
+ .make-app-approval-results, .make-app-approval-table-frame { position: relative; }
51
+ .make-app-approval-canvas { width: 100%; height: var(--make-approval-table-height, 440px); min-height: 200px; overflow: hidden; color: var(--make-approval-foreground); }
52
+ .make-app-approval-overlay { position: absolute; inset: 40px 0 0; display: flex; align-items: center; justify-content: center; gap: 12px; background: var(--make-approval-bg); color: var(--make-approval-muted); }
53
+ .make-app-approval-table-feedback { position: absolute; top: 48px; right: 12px; left: 12px; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; padding: 8px 12px; color: var(--make-approval-muted); background: var(--make-approval-bg); border: 1px solid var(--make-approval-border); border-radius: var(--make-approval-radius); }
54
+ .make-app-approval-table-loading { position: absolute; right: 16px; bottom: 16px; display: inline-flex; align-items: center; gap: 8px; padding: 6px 10px; color: var(--make-approval-muted); background: var(--make-approval-bg); border: 1px solid var(--make-approval-border); border-radius: var(--make-approval-radius); font-size: 12px; line-height: 20px; white-space: nowrap; pointer-events: none; }
55
+ .make-app-approval-loading-spinner { width: 14px; height: 14px; flex: none; box-sizing: border-box; border: 2px solid var(--make-approval-border); border-top-color: var(--make-approval-primary); border-radius: 50%; animation: make-app-approval-spin 900ms linear infinite; }
56
+ @keyframes make-app-approval-spin { to { transform: rotate(360deg); } }
57
+ @media (prefers-reduced-motion: reduce) {
58
+ .make-app-approval-loading-spinner { animation: none; }
59
+ }
60
+ .make-app-approval-error { margin: 0; padding: 0 20px 12px; color: var(--make-approval-error, var(--make-mobile-error, #dc2626)); }
61
+ .make-app-approval-accessible-rows { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
62
+ .make-app-approval-accessible-rows:focus-within { position: relative; width: auto; height: auto; margin: 0; padding: 12px 20px; clip-path: none; white-space: normal; background: var(--make-approval-bg); list-style: none; }
63
+ .make-app-approval-accessible-rows li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
64
+ @media (max-width: 680px) {
65
+ .make-app-approval-filters { padding: 12px; }
66
+ }
67
+
68
+ .make-app-approval-detail { color: var(--make-approval-foreground, inherit); font-family: inherit; min-width: 0; display: flex; flex-direction: column; min-height: 100%; }
69
+ .make-app-approval-detail-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 16px; padding: 24px 28px; border-bottom: 1px solid var(--make-approval-border, #e2e8f0); }
70
+ .make-app-approval-detail-title, .make-app-approval-detail-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
71
+ .make-app-approval-detail-title h2 { font-size: 18px; font-weight: 600; margin: 0; }
72
+ .make-app-approval-detail-content { flex: 1; min-width: 0; color: var(--make-approval-foreground, inherit); }
73
+ .make-app-approval-detail-section { padding: 28px; }
74
+ .make-app-approval-detail-section h3 { font-size: 14px; font-weight: 600; margin: 0 0 16px; }
75
+ .make-app-approval-detail-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 24px; }
76
+ .make-app-approval-detail-field { min-width: 0; display: grid; grid-template-columns: minmax(80px, 24%) minmax(0, 1fr); align-items: center; gap: 12px; padding-block: 16px; border-bottom: 1px solid var(--make-approval-border, #e2e8f0); }
77
+ .make-app-approval-detail-field > label { color: var(--make-approval-muted, inherit); font-size: 12px; overflow-wrap: anywhere; }
78
+ .make-app-approval-required { color: var(--make-approval-error, var(--make-mobile-error, #dc2626)); }
79
+ .make-app-approval-detail-value { min-width: 0; font-size: 14px; overflow-wrap: anywhere; }
80
+ .make-app-approval-detail-field[data-invalid="true"] > label, .make-app-approval-detail-error { color: var(--make-approval-error, var(--make-mobile-error, #dc2626)); }
81
+ .make-app-approval-detail-error { margin-block: 8px; }
82
+ .make-app-approval-detail-history { border-top: 8px solid var(--make-approval-header, #f6f7f9); }
83
+ .make-app-approval-detail-message { margin-inline: 28px; }
84
+ .make-app-approval-detail-footer { padding: 20px 28px; border-top: 1px solid var(--make-approval-border, #e2e8f0); }
85
+ .make-app-approval-detail-opinion { display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--make-approval-border, #e2e8f0); }
86
+ .make-app-approval-detail-opinion > label { font-size: 14px; font-weight: 600; }
87
+ .make-app-approval-action-confirm { display: flex; flex-direction: column; gap: 12px; padding-top: 12px; }
88
+ .make-app-approval-action-confirm h3 { font-size: 14px; margin: 0; }
89
+ .make-app-approval-action-confirm > .make-app-approval-detail-actions { justify-content: flex-end; }
90
+ .make-app-approval-detail-target { display: flex; flex-direction: column; gap: 8px; max-width: 320px; }
91
+ @media (max-width: 680px) {
92
+ .make-app-approval-detail-fields { grid-template-columns: minmax(0, 1fr); }
93
+ .make-app-approval-detail-section, .make-app-approval-detail-header, .make-app-approval-detail-footer { padding: 16px; }
94
+ }
@@ -0,0 +1 @@
1
+ export {};