@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.
- package/PUBLIC_API.md +129 -0
- package/README.md +65 -2
- package/capabilities.json +76 -0
- package/dist/detail/approval-task-detail.d.ts +2 -0
- package/dist/detail/diagnostics.d.ts +2 -0
- package/dist/detail/field-value.d.ts +2 -0
- package/dist/detail/index.d.ts +3 -0
- package/dist/detail/task-policy.d.ts +18 -0
- package/dist/detail/types.d.ts +111 -0
- package/dist/detail.cjs +1 -0
- package/dist/detail.mjs +500 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.mjs +30 -0
- package/dist/list/approval-table.d.ts +14 -0
- package/dist/list/diagnostics.d.ts +3 -0
- package/dist/list/index.d.ts +3 -0
- package/dist/list/my-approvals-page.d.ts +2 -0
- package/dist/list/page-contract.d.ts +3 -0
- package/dist/list/status-label.d.ts +1 -0
- package/dist/list/types.d.ts +71 -0
- package/dist/list/ui-components.d.ts +44 -0
- package/dist/list/use-approval-page.d.ts +12 -0
- package/dist/list/virtual-page-loader.d.ts +26 -0
- package/dist/list.cjs +1 -0
- package/dist/list.mjs +381 -0
- package/dist/react/index.d.ts +7 -0
- package/dist/react.cjs +1 -0
- package/dist/react.mjs +17 -0
- package/dist/styles.css +94 -0
- package/dist/styles.css.d.ts +1 -0
- package/dist/withdrawal.d.ts +14 -0
- package/docs/host-integration.md +217 -0
- package/docs/implementation-plan.md +61 -0
- package/docs/publishing.md +108 -0
- package/examples/antd-components.tsx +38 -0
- package/examples/detail-integration.tsx +80 -0
- package/examples/host-integration.tsx +36 -0
- package/package.ai.json +85 -0
- package/package.json +117 -4
- 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
|
+
};
|
package/dist/styles.css
ADDED
|
@@ -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 {};
|