zy-react-library 1.2.2 → 1.2.4
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/components/DragTableBuilder/DragTableBuilder.js +1 -0
- package/components/DragTableBuilder/DragTableBuilder.less +8 -0
- package/components/DragTableBuilder/DropZone.js +1 -0
- package/components/DragTableBuilder/DropZone.less +80 -0
- package/components/DragTableBuilder/FieldConfigEditor.js +1 -0
- package/components/DragTableBuilder/FieldConfigEditor.less +5 -0
- package/components/DragTableBuilder/FieldLibrary.js +1 -0
- package/components/DragTableBuilder/FieldLibrary.less +37 -0
- package/components/DragTableBuilder/TablePreview.js +1 -0
- package/components/DragTableBuilder/TablePreview.less +69 -0
- package/components/DragTableBuilder/index.d.ts +71 -0
- package/components/DragTableBuilder/index.js +1 -0
- package/components/FormBuilder/FormBuilder.d.ts +2 -3
- package/components/FormBuilder/FormItemsRenderer.d.ts +45 -12
- package/components/Search/index.d.ts +2 -3
- package/package.json +1 -1
- package/utils/index.d.ts +4 -0
- package/utils/index.js +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useState as e,useCallback as t}from"react";import{message as i,Modal as l,Space as n,Button as o,Row as d,Col as r}from"antd";import{CopyOutlined as a,ExportOutlined as s,Html5Outlined as c,ClearOutlined as p}from"@ant-design/icons";import{DndContext as b}from"../../node_modules/@dnd-kit/core/dist/core.esm";import{arrayMove as h}from"../../node_modules/@dnd-kit/sortable/dist/sortable.esm";import m from"./FieldLibrary.js";import f from"./DropZone.js";import g from"./FieldConfigEditor.js";import u from"./TablePreview.js";import"../../src/components/DragTableBuilder/DragTableBuilder.less";import{jsxs as x,jsx as y}from"react/jsx-runtime";const w=[{type:"text",label:"文本",icon:"T"},{type:"number",label:"数字",icon:"#"},{type:"date",label:"日期",icon:"📅"},{type:"datetime",label:"日期时间",icon:"🕐"},{type:"select",label:"下拉选择",icon:"▼"},{type:"boolean",label:"布尔值",icon:"☑"},{type:"email",label:"邮箱",icon:"✉"},{type:"url",label:"链接",icon:"🔗"},{type:"image",label:"图片",icon:"🖼"},{type:"tag",label:"标签",icon:"🏷"},{type:"progress",label:"进度条",icon:"▓"},{type:"rate",label:"评分",icon:"★"}],v=v=>{const{fieldTypes:k=w,initialFields:C=[],onChange:T,onExport:L,showPreview:$=!0,showLibrary:E=!0,showConfigEditor:j=!0}=v,[I,D]=e(C),[M,R]=e(null),[_,F]=e(!1),H=t(()=>`field_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,[]),O=t(e=>{const{active:t,over:i}=e;if(i&&t.id!==i.id){const e=I.findIndex(e=>e.id===t.id),l=I.findIndex(e=>e.id===i.id),n=h(I,e,l);D(n),T&&T(n)}},[I,T]),U=t(e=>{const t=I.filter(t=>t.id!==e);D(t),T&&T(t)},[I,T]),B=t(e=>{R(e),F(!0)},[]),N=t(e=>{const t=I.map(t=>t.id===e.id?e:t);D(t),F(!1),R(null),T&&T(t),i.success("字段配置已保存")},[I,T]),S=t(()=>{F(!1),R(null)},[]),P=t(()=>{l.confirm({title:"确认清空",content:"确定要清空所有字段吗?",onOk:()=>{D([]),T&&T([]),i.success("已清空所有字段")}})},[T]),z=t(()=>{const e=I.map(e=>({title:e.title,dataIndex:e.dataIndex,width:e.width,align:e.align,fixed:e.fixed,ellipsis:e.ellipsis,sorter:!1!==e.sortable})),t=JSON.stringify(e,null,2);navigator.clipboard.writeText(t).then(()=>{i.success("配置已复制到剪贴板")}).catch(()=>{i.error("复制失败")})},[I]),J=t(()=>{const e=I.map(e=>({title:e.title,dataIndex:e.dataIndex,width:e.width,align:e.align,fixed:e.fixed,ellipsis:e.ellipsis,sorter:!1!==e.sortable}));L?L(e):(console.log("导出的表格配置:",e),i.success("配置已导出到控制台"))},[I,L]),Z=t(()=>{let e=`<table style="width: ${I.reduce((e,t)=>e+(t.width||150),0)}px; border-collapse: collapse; font-size: 13px;">\n`;return e+=" <thead>\n",e+=" <tr>\n",I.forEach(t=>{const i=t.align||"center";e+=` <th style="width: ${t.width||150}px; text-align: ${i}; padding: 8px 12px; border: 1px solid #f0f0f0; background: #fafafa; font-weight: 600;">${t.title||t.label}</th>\n`}),e+=" </tr>\n",e+=" </thead>\n",e+=" <tbody>\n",e+=" <tr>\n",I.forEach(t=>{const i=t.align||"center";e+=` <td style="width: ${t.width||150}px; text-align: ${i}; padding: 8px 12px; border: 1px solid #f0f0f0;">数据示例</td>\n`}),e+=" </tr>\n",e+=" </tbody>\n",e+="</table>",e},[I]),q=t(()=>{const e=Z();navigator.clipboard.writeText(e).then(()=>{i.success("HTML代码已复制到剪贴板")}).catch(()=>{i.error("复制失败")})},[Z]),A=t(()=>{const e=Z(),t=new Blob([e],{type:"text/html"}),l=URL.createObjectURL(t),n=document.createElement("a");n.href=l,n.download="table.html",document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(l),i.success("HTML文件已导出")},[Z]),G=t(e=>{const t={id:H(),type:e.type,label:e.label,title:e.label,dataIndex:`field_${I.length+1}`,width:150,align:"center",ellipsis:!0,sortable:!0},l=[...I,t];D(l),T&&T(l),i.success(`已添加${e.label}字段`)},[I,H,T]);return x("div",{className:"drag-table-builder",children:[y("div",{className:"builder-header",children:x(n,{wrap:!0,children:[y(o,{icon:y(a,{}),onClick:z,disabled:0===I.length,children:"复制配置"}),y(o,{icon:y(s,{}),onClick:J,disabled:0===I.length,children:"导出配置"}),y(o,{icon:y(c,{}),onClick:q,disabled:0===I.length,children:"复制HTML"}),y(o,{icon:y(c,{}),onClick:A,disabled:0===I.length,children:"导出HTML"}),y(o,{icon:y(p,{}),onClick:P,disabled:0===I.length,danger:!0,children:"清空"})]})}),y(b,{onDragEnd:O,children:x(d,{gutter:16,children:[E&&y(r,{span:6,children:y(m,{fields:k,onFieldClick:G})}),x(r,{span:E?18:24,children:[y(f,{fields:I,onRemove:U,onEdit:B}),$&&y("div",{style:{marginTop:16},children:y(u,{fields:I})})]})]})}),j&&y(g,{visible:_,field:M,onSave:N,onCancel:S})]})};export{v as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DeleteOutlined as e}from"@ant-design/icons";import{SortableContext as i,verticalListSortingStrategy as t,useSortable as n}from"../../node_modules/@dnd-kit/sortable/dist/sortable.esm";import{CSS as s}from"../../node_modules/@dnd-kit/utilities/dist/utilities.esm";import{Card as a,Empty as d}from"antd";import"../../src/components/DragTableBuilder/DropZone.less";import{jsx as o,jsxs as l}from"react/jsx-runtime";const r=({field:i,onRemove:t,onEdit:a})=>{const{attributes:d,listeners:r,setNodeRef:c,transform:m,transition:p,isDragging:f}=n({id:i.id}),h={transform:s.Transform.toString(m),transition:p,opacity:f?.5:1};return o("div",{ref:c,style:h,...d,...r,className:"sortable-field",children:l("div",{className:"field-content",children:[o("span",{className:"drag-handle",children:"⋮⋮"}),o("span",{className:"field-title",children:i.title||i.label}),o("span",{className:"field-dataindex",children:i.dataIndex||"未设置"}),l("div",{className:"field-actions",children:[o("span",{className:"action-btn edit-btn",onClick:e=>{e.stopPropagation(),a(i)},children:"编辑"}),o("span",{className:"action-btn delete-btn",onClick:e=>{e.stopPropagation(),t(i.id)},children:o(e,{})})]})]})})},c=({fields:e,onRemove:n,onEdit:s,children:l})=>o("div",{className:"drop-zone",children:o(a,{title:"表格字段",size:"small",className:"drop-zone-card",children:0===e.length?o(d,{description:"从左侧点击字段添加到此处",image:d.PRESENTED_IMAGE_SIMPLE}):o(i,{items:e.map(e=>e.id),strategy:t,children:o("div",{className:"field-list",children:e.map(e=>o(r,{field:e,onRemove:n,onEdit:s},e.id))})})})});export{c as default};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
.drop-zone {
|
|
2
|
+
.drop-zone-card {
|
|
3
|
+
min-height: 400px;
|
|
4
|
+
|
|
5
|
+
.field-list {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
gap: 8px;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.sortable-field {
|
|
13
|
+
cursor: move;
|
|
14
|
+
transition: all 0.3s;
|
|
15
|
+
border: 1px solid #d9d9d9;
|
|
16
|
+
border-radius: 4px;
|
|
17
|
+
padding: 8px 12px;
|
|
18
|
+
background: #fff;
|
|
19
|
+
|
|
20
|
+
&:hover {
|
|
21
|
+
border-color: #1890ff;
|
|
22
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.field-content {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
gap: 12px;
|
|
29
|
+
|
|
30
|
+
.drag-handle {
|
|
31
|
+
cursor: move;
|
|
32
|
+
color: #999;
|
|
33
|
+
font-size: 12px;
|
|
34
|
+
letter-spacing: -2px;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.field-title {
|
|
38
|
+
flex: 1;
|
|
39
|
+
font-weight: 500;
|
|
40
|
+
color: #333;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.field-dataindex {
|
|
44
|
+
color: #999;
|
|
45
|
+
font-size: 12px;
|
|
46
|
+
font-family: monospace;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.field-actions {
|
|
50
|
+
display: flex;
|
|
51
|
+
gap: 8px;
|
|
52
|
+
margin-left: auto;
|
|
53
|
+
|
|
54
|
+
.action-btn {
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
font-size: 12px;
|
|
57
|
+
padding: 2px 8px;
|
|
58
|
+
border-radius: 3px;
|
|
59
|
+
transition: all 0.3s;
|
|
60
|
+
|
|
61
|
+
&.edit-btn {
|
|
62
|
+
color: #1890ff;
|
|
63
|
+
|
|
64
|
+
&:hover {
|
|
65
|
+
background: #e6f7ff;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&.delete-btn {
|
|
70
|
+
color: #ff4d4f;
|
|
71
|
+
|
|
72
|
+
&:hover {
|
|
73
|
+
background: #fff1f0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Select as e,Input as l,Form as i,Modal as a,Space as t,InputNumber as r,Switch as d}from"antd";import{useEffect as n}from"react";import"../../src/components/DragTableBuilder/FieldConfigEditor.less";import{jsx as s,jsxs as o}from"react/jsx-runtime";const{Option:c}=e,{TextArea:h}=l,m=({visible:m,field:u,onSave:p,onCancel:x})=>{const[b]=i.useForm();return n(()=>{m&&u&&b.setFieldsValue({title:u.title||u.label||"",dataIndex:u.dataIndex||"",width:u.width||150,align:u.align||"center",fixed:u.fixed||void 0,ellipsis:void 0===u.ellipsis||u.ellipsis,sortable:void 0===u.sortable||u.sortable,render:u.render||""})},[m,u,b]),s(a,{title:"编辑字段配置",open:m,onOk:()=>{b.validateFields().then(e=>{const l={...u,title:e.title,dataIndex:e.dataIndex,width:e.width,align:e.align,fixed:e.fixed||void 0,ellipsis:e.ellipsis,sortable:e.sortable,render:e.render};p(l)})},onCancel:x,width:600,okText:"保存",cancelText:"取消",children:o(i,{form:b,layout:"vertical",className:"field-config-form",children:[s(i.Item,{label:"列标题",name:"title",rules:[{required:!0,message:"请输入列标题"}],children:s(l,{placeholder:"请输入列标题"})}),s(i.Item,{label:"数据字段名",name:"dataIndex",rules:[{required:!0,message:"请输入数据字段名"}],children:s(l,{placeholder:"请输入数据字段名(如:name, age等)"})}),o(t,{style:{width:"100%"},size:"large",children:[s(i.Item,{label:"列宽度",name:"width",initialValue:150,children:s(r,{min:50,max:1e3,style:{width:120}})}),s(i.Item,{label:"对齐方式",name:"align",initialValue:"center",children:o(e,{style:{width:120},children:[s(c,{value:"left",children:"左对齐"}),s(c,{value:"center",children:"居中"}),s(c,{value:"right",children:"右对齐"})]})})]}),o(t,{style:{width:"100%"},size:"large",children:[s(i.Item,{label:"固定列",name:"fixed",children:o(e,{placeholder:"不固定",style:{width:120},allowClear:!0,children:[s(c,{value:"left",children:"左侧固定"}),s(c,{value:"right",children:"右侧固定"})]})}),s(i.Item,{label:"超长省略",name:"ellipsis",valuePropName:"checked",initialValue:!0,children:s(d,{})}),s(i.Item,{label:"可排序",name:"sortable",valuePropName:"checked",initialValue:!0,children:s(d,{})})]}),s(i.Item,{label:"自定义渲染函数(可选)",name:"render",extra:"请输入函数体,如:return text + '元'",children:s(h,{rows:3,placeholder:"可选:输入自定义渲染函数的函数体"})})]})})};export{m as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Card as l,Tag as e}from"antd";import"../../src/components/DragTableBuilder/FieldLibrary.less";import{jsx as i,jsxs as a}from"react/jsx-runtime";const c=({field:l,onClick:c})=>i("div",{className:"clickable-field",onClick:()=>c(l),children:a(e,{color:"blue",className:"field-tag",children:[l.icon&&i("span",{className:"field-icon",children:l.icon}),i("span",{className:"field-label",children:l.label})]})}),s=({fields:e,onFieldClick:a})=>i("div",{className:"field-library",children:i(l,{title:"字段库",size:"small",className:"field-library-card",children:i("div",{className:"field-list",children:e.map(l=>i(c,{field:l,onClick:a},l.type))})})});export{s as default};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
.field-library {
|
|
2
|
+
.field-library-card {
|
|
3
|
+
min-height: 400px;
|
|
4
|
+
|
|
5
|
+
.field-list {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-wrap: wrap;
|
|
8
|
+
gap: 8px;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.clickable-field {
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
transition: all 0.3s;
|
|
15
|
+
|
|
16
|
+
&:hover {
|
|
17
|
+
transform: translateY(-2px);
|
|
18
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.field-tag {
|
|
22
|
+
margin: 0;
|
|
23
|
+
padding: 4px 12px;
|
|
24
|
+
font-size: 14px;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
user-select: none;
|
|
27
|
+
|
|
28
|
+
.field-icon {
|
|
29
|
+
margin-right: 4px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.field-label {
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Card as e,Empty as t}from"antd";import"../../src/components/DragTableBuilder/TablePreview.less";import{jsx as r,jsxs as i}from"react/jsx-runtime";const a=({fields:a,dataSource:l})=>{const n=l||(0===a.length?[]:Array.from({length:3},(e,t)=>{const r={};return a.forEach(e=>{const i=e.dataIndex;if(i)switch(e.type){case"text":r[i]=`示例文本${t+1}`;break;case"number":r[i]=Math.floor(1e3*Math.random());break;case"date":r[i]="2024-01-01";break;case"datetime":r[i]="2024-01-01 12:00:00";break;case"select":r[i]=t%2==0?"选项1":"选项2";break;case"boolean":r[i]=t%2==0?"是":"否";break;case"email":r[i]=`example${t}@test.com`;break;case"url":r[i]=`https://example.com/${t}`;break;default:r[i]=`数据${t+1}`}}),r})),s=a.reduce((e,t)=>e+(t.width||150),0);return r("div",{className:"table-preview",children:r(e,{title:"表格预览",size:"small",className:"preview-card",children:0===a.length?r(t,{description:"暂无数据,请先添加字段",image:t.PRESENTED_IMAGE_SIMPLE}):r("div",{className:"native-table-container",children:i("table",{className:"native-table",style:{width:s},children:[r("thead",{children:r("tr",{children:a.map(e=>r("th",{style:{width:e.width||150,textAlign:e.align||"center",position:e.fixed?"sticky":"static",left:"left"===e.fixed?0:"auto",right:"right"===e.fixed?0:"auto",zIndex:e.fixed?2:1},children:e.title||e.label},e.id))})}),r("tbody",{children:n.map((e,t)=>r("tr",{children:a.map(i=>{const a=e[i.dataIndex],l=((e,t,r,i)=>{if(e.render)try{return new Function("text","record","index",e.render)(t,r,i)}catch(e){return console.error("渲染函数执行错误:",e),t}return t})(i,a,e,t);return r("td",{style:{width:i.width||150,textAlign:i.align||"center",overflow:!1!==i.ellipsis?"hidden":"visible",textOverflow:!1!==i.ellipsis?"ellipsis":"clip",whiteSpace:!1!==i.ellipsis?"nowrap":"normal"},title:!1!==i.ellipsis?a:void 0,children:l},i.id)})},t))})]})})})})};export{a as default};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
.table-preview {
|
|
2
|
+
.preview-card {
|
|
3
|
+
.native-table-container {
|
|
4
|
+
overflow-x: auto;
|
|
5
|
+
overflow-y: auto;
|
|
6
|
+
max-height: 300px;
|
|
7
|
+
border: 1px solid #f0f0f0;
|
|
8
|
+
border-radius: 4px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.native-table {
|
|
12
|
+
width: 100%;
|
|
13
|
+
border-collapse: collapse;
|
|
14
|
+
font-size: 13px;
|
|
15
|
+
background: #fff;
|
|
16
|
+
|
|
17
|
+
thead {
|
|
18
|
+
position: sticky;
|
|
19
|
+
top: 0;
|
|
20
|
+
z-index: 10;
|
|
21
|
+
background: #fafafa;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
th {
|
|
25
|
+
padding: 8px 12px;
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
color: rgba(0, 0, 0, 0.88);
|
|
28
|
+
background: #fafafa;
|
|
29
|
+
border: 1px solid #f0f0f0;
|
|
30
|
+
white-space: nowrap;
|
|
31
|
+
|
|
32
|
+
&[style*="position: sticky"] {
|
|
33
|
+
background: #fafafa;
|
|
34
|
+
z-index: 2;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
tbody {
|
|
39
|
+
tr {
|
|
40
|
+
transition: background 0.3s;
|
|
41
|
+
|
|
42
|
+
&:hover {
|
|
43
|
+
background: #fafafa;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&:nth-child(even) {
|
|
47
|
+
background: #fafafa;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&:hover:nth-child(even) {
|
|
51
|
+
background: #f0f0f0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
td {
|
|
57
|
+
padding: 8px 12px;
|
|
58
|
+
color: rgba(0, 0, 0, 0.88);
|
|
59
|
+
border: 1px solid #f0f0f0;
|
|
60
|
+
background: #fff;
|
|
61
|
+
|
|
62
|
+
&[style*="position: sticky"] {
|
|
63
|
+
background: #fff;
|
|
64
|
+
z-index: 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { FC, ReactNode } from "react";
|
|
2
|
+
import type { ColumnsType } from "antd/es/table";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 字段类型定义
|
|
6
|
+
*/
|
|
7
|
+
export interface FieldType {
|
|
8
|
+
/** 字段类型标识 */
|
|
9
|
+
type: string;
|
|
10
|
+
/** 字段显示名称 */
|
|
11
|
+
label: string;
|
|
12
|
+
/** 字段图标 */
|
|
13
|
+
icon?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 表格字段配置
|
|
18
|
+
*/
|
|
19
|
+
export interface TableField {
|
|
20
|
+
/** 字段唯一标识 */
|
|
21
|
+
id: string;
|
|
22
|
+
/** 字段类型 */
|
|
23
|
+
type: string;
|
|
24
|
+
/** 字段标签 */
|
|
25
|
+
label: string;
|
|
26
|
+
/** 列标题 */
|
|
27
|
+
title: string;
|
|
28
|
+
/** 数据字段名 */
|
|
29
|
+
dataIndex: string;
|
|
30
|
+
/** 列宽度 */
|
|
31
|
+
width?: number;
|
|
32
|
+
/** 对齐方式 */
|
|
33
|
+
align?: "left" | "center" | "right";
|
|
34
|
+
/** 固定列 */
|
|
35
|
+
fixed?: "left" | "right";
|
|
36
|
+
/** 超长省略 */
|
|
37
|
+
ellipsis?: boolean;
|
|
38
|
+
/** 可排序 */
|
|
39
|
+
sortable?: boolean;
|
|
40
|
+
/** 自定义渲染函数 */
|
|
41
|
+
render?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* DragTableBuilder 组件属性
|
|
46
|
+
*/
|
|
47
|
+
export interface DragTableBuilderProps {
|
|
48
|
+
/** 可用字段类型列表 */
|
|
49
|
+
fieldTypes?: FieldType[];
|
|
50
|
+
/** 初始字段列表 */
|
|
51
|
+
initialFields?: TableField[];
|
|
52
|
+
/** 字段列表变化回调 */
|
|
53
|
+
onChange?: (fields: TableField[]) => void;
|
|
54
|
+
/** 导出配置回调 */
|
|
55
|
+
onExport?: (config: ColumnsType<any>) => void;
|
|
56
|
+
/** 是否显示预览区域 */
|
|
57
|
+
showPreview?: boolean;
|
|
58
|
+
/** 是否显示字段库 */
|
|
59
|
+
showLibrary?: boolean;
|
|
60
|
+
/** 是否显示配置编辑器 */
|
|
61
|
+
showConfigEditor?: boolean;
|
|
62
|
+
/** 自定义预览数据 */
|
|
63
|
+
dataSource?: any[];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 拖拽式表格构建器组件
|
|
68
|
+
*/
|
|
69
|
+
declare const DragTableBuilder: FC<DragTableBuilderProps>;
|
|
70
|
+
|
|
71
|
+
export default DragTableBuilder;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import r from"./DragTableBuilder.js";export{r as default};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { FormInstance, FormProps } from "antd/es/form";
|
|
2
|
-
import type { useForm, useWatch } from "antd/es/form/Form";
|
|
3
2
|
import type { Gutter } from "antd/es/grid/row";
|
|
4
3
|
import type { FC, ReactNode } from "react";
|
|
5
4
|
import type { FormOption, FormValues } from "./FormItemsRenderer";
|
|
@@ -42,8 +41,8 @@ export interface FormBuilderProps extends Omit<FormProps, "form"> {
|
|
|
42
41
|
* 表单构建器组件
|
|
43
42
|
*/
|
|
44
43
|
declare const FormBuilder: FC<FormBuilderProps> & {
|
|
45
|
-
useForm: typeof useForm;
|
|
46
|
-
useWatch: typeof useWatch;
|
|
44
|
+
useForm: typeof import("antd").Form.useForm;
|
|
45
|
+
useWatch: typeof import("antd").Form.useWatch;
|
|
47
46
|
};
|
|
48
47
|
|
|
49
48
|
export default FormBuilder;
|
|
@@ -2,12 +2,14 @@ import type { ColProps } from "antd/es/col";
|
|
|
2
2
|
import type { FormItemProps, Rule } from "antd/es/form";
|
|
3
3
|
import type { FormListFieldData } from "antd/es/form/FormList";
|
|
4
4
|
import type { Gutter } from "antd/es/grid/row";
|
|
5
|
-
import type { NamePath } from "rc-field-form/lib/interface";
|
|
6
5
|
import type { FC, ReactNode } from "react";
|
|
7
6
|
import type { FORM_ITEM_RENDER_TYPE_MAP } from "../../enum/formItemRender";
|
|
8
7
|
|
|
8
|
+
/** 表单项 name */
|
|
9
|
+
export type FormFieldName = string | number | (string | number)[];
|
|
10
|
+
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
12
|
+
* 选择项数据类型
|
|
11
13
|
*/
|
|
12
14
|
export interface OptionItem {
|
|
13
15
|
/** ID字段 */
|
|
@@ -22,7 +24,7 @@ export interface OptionItem {
|
|
|
22
24
|
/**
|
|
23
25
|
* 字段键配置
|
|
24
26
|
*/
|
|
25
|
-
export interface
|
|
27
|
+
export interface ItemsFieldConfig {
|
|
26
28
|
/** 值字段的键名,默认 'bianma' */
|
|
27
29
|
valueKey?: string;
|
|
28
30
|
/** 标签字段的键名,默认 'name' */
|
|
@@ -71,17 +73,15 @@ export interface FormListUniqueProps {
|
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
/**
|
|
74
|
-
*
|
|
76
|
+
* 表单配置项公共字段
|
|
75
77
|
*/
|
|
76
|
-
export interface
|
|
78
|
+
export interface FormOptionBase {
|
|
77
79
|
/** React 需要的 key,如果传递了唯一的 name,则不需要 */
|
|
78
80
|
key?: string;
|
|
79
81
|
/** 表单项字段名 */
|
|
80
|
-
name?:
|
|
82
|
+
name?: FormFieldName;
|
|
81
83
|
/** 表单项标签 */
|
|
82
84
|
label?: ReactNode;
|
|
83
|
-
/** 渲染类型 */
|
|
84
|
-
render?: T | ReactNode;
|
|
85
85
|
/** 占据栅格列数,默认 12 */
|
|
86
86
|
span?: number | string;
|
|
87
87
|
/** 是否必填,默认 true,支持函数动态计算 */
|
|
@@ -101,11 +101,9 @@ export interface FormOption<T extends keyof FORM_ITEM_RENDER_TYPE_MAP = keyof FO
|
|
|
101
101
|
/** 选项数据(用于 select、radio、checkbox) */
|
|
102
102
|
items?: OptionItem[];
|
|
103
103
|
/** 字段键配置 */
|
|
104
|
-
itemsField?:
|
|
104
|
+
itemsField?: ItemsFieldConfig;
|
|
105
105
|
/** checkbox 的栅格数量,如果不传入不使用栅格,传入才使用 */
|
|
106
106
|
checkboxCol?: number;
|
|
107
|
-
/** 传递给表单控件的属性,支持函数动态计算 */
|
|
108
|
-
componentProps?: FORM_ITEM_RENDER_TYPE_MAP[T] | ((formValues: FormValues) => FORM_ITEM_RENDER_TYPE_MAP[T]);
|
|
109
107
|
/** 传递给 Form.Item 的属性,支持函数动态计算 */
|
|
110
108
|
formItemProps?: FormItemProps | ((formValues: FormValues) => FormItemProps);
|
|
111
109
|
/** label 栅格配置,默认直接使用外层的 labelCol,如果 span 等于 24,是外层的 labelCol.span 一半 */
|
|
@@ -115,13 +113,48 @@ export interface FormOption<T extends keyof FORM_ITEM_RENDER_TYPE_MAP = keyof FO
|
|
|
115
113
|
/** 是否应该更新(用于表单联动) */
|
|
116
114
|
shouldUpdate?: boolean | ((prevValues: FormValues, nextValues: FormValues, info: { source?: string }) => boolean);
|
|
117
115
|
/** 依赖字段(用于表单联动) */
|
|
118
|
-
dependencies?:
|
|
116
|
+
dependencies?: FormFieldName[];
|
|
119
117
|
/** 是否仅用于保存标签,不渲染到页面上,只在表单中保存数据,默认 false */
|
|
120
118
|
onlyForLabel?: boolean;
|
|
121
119
|
/** Form.List 独有的属性 */
|
|
122
120
|
formListUniqueProps?: FormListUniqueProps | ((formValues: FormValues) => FormListUniqueProps);
|
|
123
121
|
}
|
|
124
122
|
|
|
123
|
+
/**
|
|
124
|
+
* 按 render 类型区分的表单项
|
|
125
|
+
*/
|
|
126
|
+
export type FormOptionByRender<K extends keyof FORM_ITEM_RENDER_TYPE_MAP> = FormOptionBase & {
|
|
127
|
+
/** 渲染类型(写字面量时 componentProps 会按该类型推导) */
|
|
128
|
+
render: K;
|
|
129
|
+
/** 传递给表单控件的属性,类型由 render 决定 */
|
|
130
|
+
componentProps?: FORM_ITEM_RENDER_TYPE_MAP[K] | ((formValues: FormValues) => FORM_ITEM_RENDER_TYPE_MAP[K]);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 不写 render 或 render 为 input 时的表单项(默认按输入框)
|
|
135
|
+
*/
|
|
136
|
+
export type FormOptionDefault = FormOptionBase & {
|
|
137
|
+
render?: "input" | undefined;
|
|
138
|
+
/** 传递给 Input 的属性 */
|
|
139
|
+
componentProps?: FORM_ITEM_RENDER_TYPE_MAP["input"] | ((formValues: FormValues) => FORM_ITEM_RENDER_TYPE_MAP["input"]);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* 自定义渲染时的表单项(render 为 ReactNode 时使用)
|
|
144
|
+
*/
|
|
145
|
+
export type FormOptionCustomRender = FormOptionBase & {
|
|
146
|
+
render?: ReactNode;
|
|
147
|
+
componentProps?: Record<string, any> | ((formValues: FormValues) => Record<string, any>);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 表单配置项
|
|
152
|
+
*/
|
|
153
|
+
export type FormOption
|
|
154
|
+
= | FormOptionDefault
|
|
155
|
+
| { [K in keyof FORM_ITEM_RENDER_TYPE_MAP]: FormOptionByRender<K> }[keyof FORM_ITEM_RENDER_TYPE_MAP]
|
|
156
|
+
| FormOptionCustomRender;
|
|
157
|
+
|
|
125
158
|
/**
|
|
126
159
|
* FormItemsRenderer 组件属性
|
|
127
160
|
*/
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { FormInstance, FormProps } from "antd/es/form";
|
|
2
|
-
import type { useForm, useWatch } from "antd/es/form/Form";
|
|
3
2
|
import type { FC, ReactNode } from "react";
|
|
4
3
|
import type { FormOption } from "../FormBuilder/FormItemsRenderer";
|
|
5
4
|
|
|
@@ -38,8 +37,8 @@ export interface SearchProps extends Omit<FormProps, "form" | "onFinish"> {
|
|
|
38
37
|
* 支持自动展开/收起功能,当表单项超过4个时显示展开/收起按钮
|
|
39
38
|
*/
|
|
40
39
|
declare const Search: FC<SearchProps> & {
|
|
41
|
-
useForm: typeof useForm;
|
|
42
|
-
useWatch: typeof useWatch;
|
|
40
|
+
useForm: typeof import("antd").Form.useForm;
|
|
41
|
+
useWatch: typeof import("antd").Form.useWatch;
|
|
43
42
|
};
|
|
44
43
|
|
|
45
44
|
export default Search;
|
package/package.json
CHANGED
package/utils/index.d.ts
CHANGED
|
@@ -272,6 +272,10 @@ export function getIndexColumn(pagination: false | BasePaginationConfig): {
|
|
|
272
272
|
* 获取文件url
|
|
273
273
|
*/
|
|
274
274
|
export function getFileUrl(): string;
|
|
275
|
+
/**
|
|
276
|
+
* 从服务器获取文件url
|
|
277
|
+
*/
|
|
278
|
+
export function getFileUrlFromServer(): Promise<void>;
|
|
275
279
|
|
|
276
280
|
/**
|
|
277
281
|
* base64转File对象
|
package/utils/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import dayjs from"dayjs";import{ID_NUMBER}from"../regular/index.js";function serialNumber(e,t){return(e.current-1)*e.pageSize+(t+1)}function toArrayString(value){return value?eval(value).map(String):[]}function interceptTheSuffix(e,t){return e.substring(e.lastIndexOf("."),e.length).toLowerCase()===t.toLowerCase()}function image2Base64(e){return new Promise(t=>{const n=new Image;n.src=e,n.crossOrigin="Anonymous",n.onload=function(){const e=document.createElement("canvas");e.width=n.width,e.height=n.height,e.getContext("2d").drawImage(n,0,0,n.width,n.height);const r=n.src.substring(n.src.lastIndexOf(".")+1).toLowerCase();t(e.toDataURL(`image/${r}`))}})}function image2Base642(e){return new Promise((t,n)=>{const r=new FileReader;r.readAsDataURL(e),r.onload=e=>{t(e.target.result)},r.onerror=e=>{n(e)}})}function base642File(e,t="file"){const n=e.split(","),r=n[0].match(/:(.*?);/)[1],i=r.split("/")[1],
|
|
1
|
+
import{request}from"@cqsjjb/jjb-common-lib/http.js";import dayjs from"dayjs";import{ID_NUMBER}from"../regular/index.js";function serialNumber(e,t){return(e.current-1)*e.pageSize+(t+1)}function toArrayString(value){return value?eval(value).map(String):[]}function interceptTheSuffix(e,t){return e.substring(e.lastIndexOf("."),e.length).toLowerCase()===t.toLowerCase()}function image2Base64(e){return new Promise(t=>{const n=new Image;n.src=e,n.crossOrigin="Anonymous",n.onload=function(){const e=document.createElement("canvas");e.width=n.width,e.height=n.height,e.getContext("2d").drawImage(n,0,0,n.width,n.height);const r=n.src.substring(n.src.lastIndexOf(".")+1).toLowerCase();t(e.toDataURL(`image/${r}`))}})}function image2Base642(e){return new Promise((t,n)=>{const r=new FileReader;r.readAsDataURL(e),r.onload=e=>{t(e.target.result)},r.onerror=e=>{n(e)}})}function base642File(e,t="file"){const n=e.split(","),r=n[0].match(/:(.*?);/)[1],i=r.split("/")[1],o=atob(n[1]);let a=o.length;const s=new Uint8Array(a);for(;a--;)s[a]=o.charCodeAt(a);return new File([s],`${t}.${i}`,{type:r})}function checkImgExists(e){return new Promise((t,n)=>{const r=new Image;r.src=e,r.onload=function(e){t(e)},r.onerror=function(e){n(e)}})}function getDataType(e){return Object.prototype.toString.call(e).slice(8,-1)}function ArrayDeduplication(e){return[...new Set(e)]}function arrayObjectDeduplication(e,t){const n={};return e.reduce((e,r)=>(n[r[t]]||(n[r[t]]=!0,e.push(r)),e),[])}function findCharIndex(e){const{str:t,char:n,num:r}=e;let i=t.indexOf(n);if(-1===i)return-1;for(let e=0;e<r-1;e++)if(i=t.indexOf(n,i+1),-1===i)return-1;return i}function randoms(e,t){return Math.random()*(t-e+1)+e}function numFormat(e){if(e){const t=e.toString().split("."),n=t[0].split("").reverse();let r=[];for(let e=0;e<n.length;e++)e%3==0&&0!==e&&r.push(","),r.push(n[e]);return r.reverse(),r=t[1]?r.join("").concat(`.${t[1]}`):r.join(""),r}}function isEmpty(e){return null==e||"object"==typeof e&&0===Object.keys(e).length||"string"==typeof e&&0===e.trim().length}function getUrlParam(e){const t=new RegExp(`(^|&)${e}=([^&]*)(&|$)`),n=window.location.search.substr(1).match(t);return null!=n?decodeURI(n[2]):""}function paging(e){const{list:t,currentPage:n,pageSize:r}=e;return t.filter((e,t)=>t<+n*+r&&t>=(+n-1)*+r)}function getFileSuffix(e){return e.substring(e.lastIndexOf(".")+1)}function getFileName(e){return e?e.substring(e.lastIndexOf("/")+1):""}function readTxtDocument(e){return new Promise(t=>{const n=getFileUrl()+e,r=new XMLHttpRequest;r.open("get",n,!0),r.responseType="blob",r.onload=function(e){const n=new FileReader;n.readAsText(e.target.response,"GB2312"),n.onload=function(){t(n.result)}},r.send()})}function secondConversion(e){if(!e)return 0;const t=Number.parseInt((e/60/60).toString(),10),n=Number.parseInt((e/60%60).toString(),10),r=Number.parseInt((e%60).toString(),10);return t?`${t}小时${n}分钟${r}秒`:n?`${n}分钟${r}秒`:`${r}秒`}function addingPrefixToFile(e,t={}){if(!e)return[];const{pathKey:n="filePath",nameKey:r="fileName",idKey:i="id"}=t,o=getFileUrl();for(let t=0;t<e.length;t++)e[t].url=o+e[t][n],e[t].name=e[t][r]||getFileName(e[t][n]),e[t].id=e[t][i];return e}function getLabelName(e){const{status:t,list:n,idKey:r="bianma",nameKey:i="name"}=e;for(let e=0;e<n.length;e++)if(t?.toString()===n[e][r]?.toString())return n[e][i]}function calculateFileSize(e){return e>1024?`${(""+e/1024).substring(0,(""+e/1024).lastIndexOf(".")+3)}MB`:`${e}KB`}function idCardGetDateAndGender(e){let t="",n="";if(ID_NUMBER.test(e)){const r=e.substring(6,14),i=e.substring(16,17),o=`${r.substring(0,4)}-${r.substring(4,6)}-${r.substring(6,8)}`,a=new Date(o.replace(/-/g,"/")),s=a.getMonth()+1;let l;const c=a.getDate();let u;l=s<10?`0${s}`:s,u=c<10?`0${c}`:c,t=i%2==1?"1":"0",n=`${a.getFullYear()}-${l}-${u}`}return{sex:t,date:n}}function getMatchedItems(e){const{list:t,value:n,idKey:r="bianma"}=e;return t.filter(e=>n.includes(e[r]))}function getUnmatchedItems(e){const{list:t,value:n,idKey:r="bianma"}=e;return t.filter(e=>!n.includes(e[r]))}function listTransTree(e){const{json:t,idKey:n,parentIdKey:r,childrenKey:i}=e,o=[],a={};let s=0,l=0;const c=t.length;for(;s<c;s++)a[t[s][n]]=t[s];for(;l<c;l++){const e=t[l],n=a[e[r]];n?(!n[i]&&(n[i]=[]),n[i].push(e)):o.push(e)}return o}function isEmptyToWhether(e,t={}){const{yesText:n="是",noText:r="否",yesValue:i="1"}=t;return isEmpty(e)?"":e.toString()===i.toString()?n:r}function createGuid(e=32){let t="";for(let n=0;n<e;n++)t+="abcdefghijklmnopqrstuvwxyz0123456789".charAt(Math.floor(36*Math.random()));return t}function getIndexColumn(e){return{title:"序号",key:"index",width:70,render:(t,n,r)=>!1===e?r+1:serialNumber(e,r)}}function getTreeNodePaths(e){const{data:t,targetId:n,idKey:r,childrenKey:i,path:o=[],isIncludeOneself:a}=e;for(let e=0;e<t.length;e++){const s=t[e],l=[...o,s];if(s[r]===n)return a?l:o;if(s[i]&&s[i].length>0){const e=getTreeNodePaths({data:s[i],targetId:n,idKey:r,childrenKey:i,path:l,isIncludeOneself:a});if(e)return e}}return null}const processTreeDataByLevel=e=>{const{data:t,level:n,childrenKey:r,currentLevel:i=1}=e;return t.map(e=>{const t={...e};return n&&i>=n?(t.isLeaf=!0,delete t[r]):e[r]&&e[r].length>0?t[r]=processTreeDataByLevel({data:e[r],currentLevel:i+1,level:n,childrenKey:r}):t.isLeaf=!0,t})},processTreeDataForOnlyLastLevel=e=>{const{data:t,childrenKey:n,onlyLastLevel:r=!1}=e;return r?t.map(e=>{const t=e[n]&&e[n].length>0,i={...e,selectable:!t};return t&&(i[n]=processTreeDataForOnlyLastLevel({data:e[n],childrenKey:n,onlyLastLevel:r})),i}):t},validatorEndTime=(e,t="结束时间不能早于开始时间")=>({validator:(n,r)=>r&&e&&r<e?Promise.reject(t):Promise.resolve()}),validatorTimeGTCurrentDay=(e="需要大于当前时间")=>({validator:(t,n)=>n&&n<=dayjs().format("YYYY-MM-DD HH:mm:ss")?Promise.reject(e):Promise.resolve()});function dynamicLoadJs(e){return new Promise((t,n)=>{const r=document.createElement("script");r.type="text/javascript",r.src=e,r.onload=t,r.onerror=n,document.body.appendChild(r)})}function dynamicLoadCss(e){return new Promise((t,n)=>{const r=document.createElement("link");r.rel="stylesheet",r.type="text/css",r.href=e,r.onload=t,r.onerror=n,document.head.appendChild(r)})}function normalizeEmptyHtml(e){if(!e)return"";const t=e.replace(/\s+/g,"").toLowerCase();return"<p><br></p>"===t||"<p></p>"===t||""===t?"":e}function getFileUrl(){return window.fileUrl||process.env.app.fileUrl}async function getFileUrlFromServer(){if(window.fileUrl)return;const{data:e}=await request("/basicInfo/imgFiles/getImagePath","get");window.fileUrl=e}export{ArrayDeduplication,addingPrefixToFile,arrayObjectDeduplication,base642File,calculateFileSize,checkImgExists,createGuid,dynamicLoadCss,dynamicLoadJs,findCharIndex,getDataType,getFileName,getFileSuffix,getFileUrl,getFileUrlFromServer,getIndexColumn,getLabelName,getMatchedItems,getTreeNodePaths,getUnmatchedItems,getUrlParam,idCardGetDateAndGender,image2Base64,image2Base642,interceptTheSuffix,isEmpty,isEmptyToWhether,listTransTree,normalizeEmptyHtml,numFormat,paging,processTreeDataByLevel,processTreeDataForOnlyLastLevel,randoms,readTxtDocument,secondConversion,serialNumber,toArrayString,validatorEndTime,validatorTimeGTCurrentDay};
|