@liexx/form 0.0.1
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/README.md +0 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +174 -0
- package/dist/index.js +301 -0
- package/dist/style.css +1 -0
- package/interface/client.d.ts +79 -0
- package/interface/form.d.ts +11 -0
- package/package.json +77 -0
package/README.md
ADDED
|
File without changes
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const t=require("vue"),n=require("element-plus"),d=(e,{model:o,setField:a})=>({modelValue:o[e.prop],"onUpdate:modelValue":c=>a(e.prop,c)}),B=(e,{model:o,setField:a})=>({fileList:o[e.prop],"onUpdate:fileList":c=>a(e.prop,c)}),b=e=>({disabled:e.disabled,...e.extends}),h=(e,o="输入")=>({placeholder:e.placeholder??`请${o}${e.label}`,...b(e)}),_=e=>e.options??[],C={input:(e,o)=>t.h(n.ElInput,{...d(e,o),...h(e)}),textarea:(e,o)=>t.h(n.ElInput,{...d(e,o),...h(e),type:"textarea"}),number:(e,o)=>t.h(n.ElInputNumber,{...d(e,o),...h(e)}),select:(e,o)=>t.h(n.ElSelect,{...d(e,o),clearable:!0,...h(e,"选择"),options:_(e)}),radio:(e,o)=>t.h(n.ElRadioGroup,{...d(e,o),...h(e),options:_(e)}),checkbox:(e,o)=>t.h(n.ElCheckboxGroup,{...d(e,o),...h(e),options:_(e)}),date:(e,o)=>t.h(n.ElDatePicker,{...d(e,o),...h(e,"选择日期"),type:"date"}),daterange:(e,o)=>t.h(n.ElDatePicker,{...d(e,o),...b(e),type:"daterange",startPlaceholder:"开始日期",endPlaceholder:"结束日期"}),time:(e,o)=>t.h(n.ElTimePicker,{...d(e,o),...h(e,"选择时间")}),cascader:(e,o)=>t.h(n.ElCascader,{...d(e,o),...h(e,"选择"),options:_(e)}),tree:(e,o)=>t.h(n.ElTreeSelect,{...d(e,o),...h(e,"选择"),data:_(e)}),rate:(e,o)=>t.h(n.ElRate,{...d(e,o),...b(e)}),switch:(e,o)=>t.h(n.ElSwitch,{...d(e,o),...b(e)}),file:(e,o)=>t.h(n.ElUpload,{...b(e),...B(e,o)},()=>t.h(n.ElButton,null,()=>"上传文件")),image:(e,o)=>t.h(n.ElUpload,{listType:"picture-card",...b(e),...B(e,o)})},j=t.defineComponent({props:{item:{type:Object,required:!0},model:{type:Object,required:!0},setField:{type:Function,required:!0}},setup(e){return()=>{var o;return((o=C[e.item.type])==null?void 0:o.call(C,e.item,e))??null}}}),L=e=>{const o=t.reactive(structuredClone(e??{}));return{model:o,setField:(l,r)=>{o[l]=r},getValue:()=>({...o}),setValue:l=>{Object.assign(o,l)}}},U=new Set(["select","date","daterange","time","cascader","tree","radio","checkbox"]),D={checkbox:"array",daterange:"array",file:"array",image:"array",number:"number",rate:"number",switch:"boolean"},I=e=>{const o=l=>l.map(r=>{var u;return JSON.stringify([r.prop,r.label,r.type,r.required??!1,(u=r.rules)==null?void 0:u.map(({regExp:i,message:m})=>[String(i),m])])}).join("|");let a="",c={};return{rules:t.computed(()=>{const l=e(),r=o(l);if(r===a)return c;const u={};return l.forEach(i=>{var E;const m=[],k=U.has(i.type)?"选择":"输入";i.required&&m.push({required:!0,type:D[i.type],message:`请${k}${i.label}`,trigger:["blur","change"]}),(E=i.rules)==null||E.forEach(({regExp:g,message:P})=>{m.push({validator:(V,v,y)=>g(v)?y():y(new Error(P)),trigger:["blur","change"]})}),m.length&&(u[i.prop]=m)}),a=r,c=u,u})}},$=e=>{const o=t.reactive({});return{items:t.computed(()=>e().map(s=>{const l=o[s.prop];if(!l)return s;const{extends:r,...u}=l;return{...s,...u,...r?{extends:{...s.extends,...r}}:{}}})),setProps:(s,l)=>{const r=o[s],{extends:u,...i}=l;o[s]={...r,...i,...u?{extends:{...r==null?void 0:r.extends,...u}}:{}}}}},G={key:0,class:"pro-form__required"},M={class:"form-item-tip"},W=t.defineComponent({__name:"index",props:{template:{default:()=>[]},gutter:{default:20},labelWidth:{default:"auto"},labelPosition:{default:"right"},scrollToError:{type:Boolean,default:!1},defaultValue:{default:()=>({})},tipPosition:{default:"bottom"}},emits:["change","init"],setup(e,{expose:o,emit:a}){const c=a,s=e,{model:l,setField:r,getValue:u,setValue:i}=L(s.defaultValue),{items:m,setProps:k}=$(()=>s.template),{rules:E}=I(()=>m.value),g=t.ref(),P=async()=>{var f;try{return await((f=g.value)==null?void 0:f.validate()),!0}catch{return!1}},V=()=>{var f;return(f=g.value)==null?void 0:f.resetFields()},v=()=>{var f;return(f=g.value)==null?void 0:f.clearValidate()},y=(f,x)=>{c("change",f,x)};return t.onMounted(()=>{c("init")}),o({model:l,getValue:u,setValue:i,setProps:k,validate:P,reset:V,clearValidate:v}),(f,x)=>{const w=t.resolveComponent("el-tooltip"),q=t.resolveComponent("el-form-item"),N=t.resolveComponent("el-col"),T=t.resolveComponent("el-row"),O=t.resolveComponent("el-form");return t.openBlock(),t.createBlock(O,{ref_key:"formRef",ref:g,class:"form","label-width":e.labelWidth,"label-position":e.labelPosition,model:t.unref(l),rules:t.unref(E),"scroll-to-error":e.scrollToError},{default:t.withCtx(()=>[t.createVNode(T,{gutter:e.gutter},{default:t.withCtx(()=>[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(t.unref(m),p=>(t.openBlock(),t.createBlock(N,{key:p.prop,span:p.span||24},{default:t.withCtx(()=>[t.createVNode(q,{"hide-required-asterisk":!0,prop:p.prop},{label:t.withCtx(()=>[p.required?(t.openBlock(),t.createElementBlock("span",G,"*")):t.createCommentVNode("",!0),t.createElementVNode("span",null,t.toDisplayString(p.label),1),p.tip&&e.tipPosition==="left"?(t.openBlock(),t.createBlock(w,{key:1,content:p.tip,placement:"top"},{default:t.withCtx(()=>[...x[0]||(x[0]=[t.createElementVNode("i",{class:"ri-question-fill",style:{"font-size":"16px",color:"#f56c6c"}},null,-1)])]),_:1},8,["content"])):t.createCommentVNode("",!0)]),default:t.withCtx(()=>[t.createVNode(t.unref(j),{item:p,model:t.unref(l),"set-field":t.unref(r),onChange:R=>y(R,p)},null,8,["item","model","set-field","onChange"]),p.tip&&e.tipPosition==="bottom"?(t.openBlock(),t.createBlock(w,{key:0,class:"box-item",effect:"dark",content:p.tip,placement:"top-start"},{default:t.withCtx(()=>[t.createElementVNode("div",M,t.toDisplayString(p.tip),1)]),_:2},1032,["content"])):t.createCommentVNode("",!0)]),_:2},1032,["prop"])]),_:2},1032,["span"]))),128))]),_:1},8,["gutter"])]),_:1},8,["label-width","label-position","model","rules","scroll-to-error"])}}}),Y=(e,o)=>{const a=e.__vccOpts||e;for(const[c,s]of o)a[c]=s;return a},F=Y(W,[["__scopeId","data-v-121a6606"]]);function z(e){e.component("ProForm",F)}const S=Object.assign(F,{install:z});exports.ProForm=S;exports.default=S;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { AllowedComponentProps } from 'vue';
|
|
2
|
+
import { App } from 'vue';
|
|
3
|
+
import { ComponentCustomProps } from 'vue';
|
|
4
|
+
import { ComponentOptionsBase } from 'vue';
|
|
5
|
+
import { ComponentOptionsMixin } from 'vue';
|
|
6
|
+
import { ComponentProvideOptions } from 'vue';
|
|
7
|
+
import { CreateComponentPublicInstanceWithMixins } from 'vue';
|
|
8
|
+
import { GlobalComponents } from 'vue';
|
|
9
|
+
import { GlobalDirectives } from 'vue';
|
|
10
|
+
import { PublicProps } from 'vue';
|
|
11
|
+
import { VNodeProps } from 'vue';
|
|
12
|
+
|
|
13
|
+
declare type FormModel_2 = Record<string, any>;
|
|
14
|
+
|
|
15
|
+
declare type FormProps_2 = {
|
|
16
|
+
template: FromItems_2; // 表单配置
|
|
17
|
+
gutter?: number; // 表单间距
|
|
18
|
+
labelWidth?: number | string; // 表单label宽度
|
|
19
|
+
labelPosition?: "left" | "right" | "top"; // 表单label位置
|
|
20
|
+
scrollToError?: boolean; // 校验不通过时滚动到第一个错误字段
|
|
21
|
+
defaultValue?: FormModel_2; // 表单默认值
|
|
22
|
+
tipPosition?: "left" | "bottom"; // 表单提示位置
|
|
23
|
+
};
|
|
24
|
+
export { FormProps_2 as FormProps }
|
|
25
|
+
|
|
26
|
+
declare type FormRule_2 = {
|
|
27
|
+
regExp: (value: any) => boolean;
|
|
28
|
+
message: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
declare type FromItem_2 = {
|
|
32
|
+
label: string;
|
|
33
|
+
prop: string;
|
|
34
|
+
type:
|
|
35
|
+
| "input"
|
|
36
|
+
| "select"
|
|
37
|
+
| "date"
|
|
38
|
+
| "daterange"
|
|
39
|
+
| "cascader"
|
|
40
|
+
| "tree"
|
|
41
|
+
| "switch"
|
|
42
|
+
| "radio"
|
|
43
|
+
| "file"
|
|
44
|
+
| "image"
|
|
45
|
+
| "number"
|
|
46
|
+
| "textarea"
|
|
47
|
+
| "checkbox"
|
|
48
|
+
| "rate"
|
|
49
|
+
| "time"
|
|
50
|
+
| "file";
|
|
51
|
+
// 占位
|
|
52
|
+
span?: number;
|
|
53
|
+
// 输入框占位文本
|
|
54
|
+
placeholder?: string;
|
|
55
|
+
// 提示
|
|
56
|
+
tip?: string;
|
|
57
|
+
//是否必填
|
|
58
|
+
required?: boolean;
|
|
59
|
+
//自定义校验规则
|
|
60
|
+
rules?: FormRule_2[];
|
|
61
|
+
//是否禁用
|
|
62
|
+
disabled?: boolean;
|
|
63
|
+
//是否显示到表单
|
|
64
|
+
isForm?: boolean;
|
|
65
|
+
// 透传给组件的额外 props(如 select 的 options、daterange 的 type 等)
|
|
66
|
+
extends?: Record<string, any>;
|
|
67
|
+
// 字典值
|
|
68
|
+
dict?: string;
|
|
69
|
+
// 选项内容
|
|
70
|
+
options?: OptionItem_2[];
|
|
71
|
+
//通过api方式获取选择内容
|
|
72
|
+
optionsApi?: (params?: Record<string, any>) => Promise<Record<string, any>[]>;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
declare type FromItems_2 = FromItem_2[];
|
|
76
|
+
export { FromItems_2 as FromItems }
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 全局注册 ProForm 组件。
|
|
80
|
+
* 用法:app.use(ProForm)
|
|
81
|
+
*/
|
|
82
|
+
declare function install(app: App): void;
|
|
83
|
+
|
|
84
|
+
declare type OptionItem_2 = {
|
|
85
|
+
label?: string;
|
|
86
|
+
value?: any;
|
|
87
|
+
children?: OptionItem_2[];
|
|
88
|
+
[key: string]: any; // 允许自定义字段,如 cascader 的 deptName/deptId
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
declare const ProForm: {
|
|
92
|
+
new (...args: any[]): CreateComponentPublicInstanceWithMixins<Readonly<FormProps_2> & Readonly<{
|
|
93
|
+
onChange?: ((...args: any[]) => any) | undefined;
|
|
94
|
+
onInit?: ((...args: any[]) => any) | undefined;
|
|
95
|
+
}>, {
|
|
96
|
+
model: FormModel_2;
|
|
97
|
+
getValue: () => FormModel_2;
|
|
98
|
+
setValue: (data: FormModel_2) => void;
|
|
99
|
+
setProps: (prop: string, partial: Partial<FromItem_2>) => void;
|
|
100
|
+
validate: () => Promise<boolean>;
|
|
101
|
+
reset: () => void | undefined;
|
|
102
|
+
clearValidate: () => void | undefined;
|
|
103
|
+
}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
|
|
104
|
+
change: (...args: any[]) => void;
|
|
105
|
+
init: (...args: any[]) => void;
|
|
106
|
+
}, PublicProps, {
|
|
107
|
+
template: FromItems_2;
|
|
108
|
+
defaultValue: FormModel_2;
|
|
109
|
+
gutter: number;
|
|
110
|
+
labelWidth: number | string;
|
|
111
|
+
labelPosition: "left" | "right" | "top";
|
|
112
|
+
scrollToError: boolean;
|
|
113
|
+
tipPosition: "left" | "bottom";
|
|
114
|
+
}, false, {}, {}, GlobalComponents, GlobalDirectives, string, {
|
|
115
|
+
formRef: unknown;
|
|
116
|
+
}, any, ComponentProvideOptions, {
|
|
117
|
+
P: {};
|
|
118
|
+
B: {};
|
|
119
|
+
D: {};
|
|
120
|
+
C: {};
|
|
121
|
+
M: {};
|
|
122
|
+
Defaults: {};
|
|
123
|
+
}, Readonly<FormProps_2> & Readonly<{
|
|
124
|
+
onChange?: ((...args: any[]) => any) | undefined;
|
|
125
|
+
onInit?: ((...args: any[]) => any) | undefined;
|
|
126
|
+
}>, {
|
|
127
|
+
model: FormModel_2;
|
|
128
|
+
getValue: () => FormModel_2;
|
|
129
|
+
setValue: (data: FormModel_2) => void;
|
|
130
|
+
setProps: (prop: string, partial: Partial<FromItem_2>) => void;
|
|
131
|
+
validate: () => Promise<boolean>;
|
|
132
|
+
reset: () => void | undefined;
|
|
133
|
+
clearValidate: () => void | undefined;
|
|
134
|
+
}, {}, {}, {}, {
|
|
135
|
+
template: FromItems_2;
|
|
136
|
+
defaultValue: FormModel_2;
|
|
137
|
+
gutter: number;
|
|
138
|
+
labelWidth: number | string;
|
|
139
|
+
labelPosition: "left" | "right" | "top";
|
|
140
|
+
scrollToError: boolean;
|
|
141
|
+
tipPosition: "left" | "bottom";
|
|
142
|
+
}>;
|
|
143
|
+
__isFragment?: never;
|
|
144
|
+
__isTeleport?: never;
|
|
145
|
+
__isSuspense?: never;
|
|
146
|
+
} & ComponentOptionsBase<Readonly<FormProps_2> & Readonly<{
|
|
147
|
+
onChange?: ((...args: any[]) => any) | undefined;
|
|
148
|
+
onInit?: ((...args: any[]) => any) | undefined;
|
|
149
|
+
}>, {
|
|
150
|
+
model: FormModel_2;
|
|
151
|
+
getValue: () => FormModel_2;
|
|
152
|
+
setValue: (data: FormModel_2) => void;
|
|
153
|
+
setProps: (prop: string, partial: Partial<FromItem_2>) => void;
|
|
154
|
+
validate: () => Promise<boolean>;
|
|
155
|
+
reset: () => void | undefined;
|
|
156
|
+
clearValidate: () => void | undefined;
|
|
157
|
+
}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
|
|
158
|
+
change: (...args: any[]) => void;
|
|
159
|
+
init: (...args: any[]) => void;
|
|
160
|
+
}, string, {
|
|
161
|
+
template: FromItems_2;
|
|
162
|
+
defaultValue: FormModel_2;
|
|
163
|
+
gutter: number;
|
|
164
|
+
labelWidth: number | string;
|
|
165
|
+
labelPosition: "left" | "right" | "top";
|
|
166
|
+
scrollToError: boolean;
|
|
167
|
+
tipPosition: "left" | "bottom";
|
|
168
|
+
}, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & VNodeProps & AllowedComponentProps & ComponentCustomProps & {
|
|
169
|
+
install: typeof install;
|
|
170
|
+
};
|
|
171
|
+
export { ProForm }
|
|
172
|
+
export default ProForm;
|
|
173
|
+
|
|
174
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { defineComponent as D, h as l, reactive as G, computed as W, ref as M, onMounted as Q, resolveComponent as E, openBlock as m, createBlock as V, unref as _, withCtx as h, createVNode as S, createElementBlock as j, Fragment as X, renderList as Z, createElementVNode as q, toDisplayString as B, createCommentVNode as T } from "vue";
|
|
2
|
+
import { ElUpload as N, ElButton as ee, ElSwitch as te, ElRate as oe, ElTreeSelect as re, ElCascader as le, ElTimePicker as ne, ElDatePicker as U, ElCheckboxGroup as se, ElRadioGroup as ae, ElSelect as ce, ElInputNumber as ue, ElInput as $ } from "element-plus";
|
|
3
|
+
const u = (e, { model: t, setField: s }) => ({
|
|
4
|
+
modelValue: t[e.prop],
|
|
5
|
+
"onUpdate:modelValue": (a) => s(e.prop, a)
|
|
6
|
+
}), I = (e, { model: t, setField: s }) => ({
|
|
7
|
+
fileList: t[e.prop],
|
|
8
|
+
"onUpdate:fileList": (a) => s(e.prop, a)
|
|
9
|
+
}), y = (e) => ({
|
|
10
|
+
disabled: e.disabled,
|
|
11
|
+
...e.extends
|
|
12
|
+
}), f = (e, t = "输入") => ({
|
|
13
|
+
placeholder: e.placeholder ?? `请${t}${e.label}`,
|
|
14
|
+
...y(e)
|
|
15
|
+
}), x = (e) => e.options ?? [], O = {
|
|
16
|
+
input: (e, t) => l($, { ...u(e, t), ...f(e) }),
|
|
17
|
+
textarea: (e, t) => l($, {
|
|
18
|
+
...u(e, t),
|
|
19
|
+
...f(e),
|
|
20
|
+
type: "textarea"
|
|
21
|
+
}),
|
|
22
|
+
number: (e, t) => l(ue, { ...u(e, t), ...f(e) }),
|
|
23
|
+
select: (e, t) => l(ce, {
|
|
24
|
+
...u(e, t),
|
|
25
|
+
clearable: !0,
|
|
26
|
+
...f(e, "选择"),
|
|
27
|
+
options: x(e)
|
|
28
|
+
}),
|
|
29
|
+
radio: (e, t) => l(ae, {
|
|
30
|
+
...u(e, t),
|
|
31
|
+
...f(e),
|
|
32
|
+
options: x(e)
|
|
33
|
+
}),
|
|
34
|
+
checkbox: (e, t) => l(se, {
|
|
35
|
+
...u(e, t),
|
|
36
|
+
...f(e),
|
|
37
|
+
options: x(e)
|
|
38
|
+
}),
|
|
39
|
+
date: (e, t) => l(U, {
|
|
40
|
+
...u(e, t),
|
|
41
|
+
...f(e, "选择日期"),
|
|
42
|
+
type: "date"
|
|
43
|
+
}),
|
|
44
|
+
daterange: (e, t) => l(U, {
|
|
45
|
+
...u(e, t),
|
|
46
|
+
...y(e),
|
|
47
|
+
type: "daterange",
|
|
48
|
+
startPlaceholder: "开始日期",
|
|
49
|
+
endPlaceholder: "结束日期"
|
|
50
|
+
}),
|
|
51
|
+
time: (e, t) => l(ne, {
|
|
52
|
+
...u(e, t),
|
|
53
|
+
...f(e, "选择时间")
|
|
54
|
+
}),
|
|
55
|
+
cascader: (e, t) => l(le, {
|
|
56
|
+
...u(e, t),
|
|
57
|
+
...f(e, "选择"),
|
|
58
|
+
options: x(e)
|
|
59
|
+
}),
|
|
60
|
+
tree: (e, t) => l(re, {
|
|
61
|
+
...u(e, t),
|
|
62
|
+
...f(e, "选择"),
|
|
63
|
+
data: x(e)
|
|
64
|
+
}),
|
|
65
|
+
rate: (e, t) => l(oe, { ...u(e, t), ...y(e) }),
|
|
66
|
+
switch: (e, t) => l(te, { ...u(e, t), ...y(e) }),
|
|
67
|
+
file: (e, t) => l(
|
|
68
|
+
N,
|
|
69
|
+
{ ...y(e), ...I(e, t) },
|
|
70
|
+
() => l(ee, null, () => "上传文件")
|
|
71
|
+
),
|
|
72
|
+
image: (e, t) => l(N, {
|
|
73
|
+
listType: "picture-card",
|
|
74
|
+
...y(e),
|
|
75
|
+
...I(e, t)
|
|
76
|
+
})
|
|
77
|
+
}, de = D({
|
|
78
|
+
props: {
|
|
79
|
+
item: { type: Object, required: !0 },
|
|
80
|
+
model: { type: Object, required: !0 },
|
|
81
|
+
setField: {
|
|
82
|
+
type: Function,
|
|
83
|
+
required: !0
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
setup(e) {
|
|
87
|
+
return () => {
|
|
88
|
+
var t;
|
|
89
|
+
return ((t = O[e.item.type]) == null ? void 0 : t.call(O, e.item, e)) ?? null;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}), ie = (e) => {
|
|
93
|
+
const t = G(structuredClone(e ?? {}));
|
|
94
|
+
return { model: t, setField: (r, o) => {
|
|
95
|
+
t[r] = o;
|
|
96
|
+
}, getValue: () => ({ ...t }), setValue: (r) => {
|
|
97
|
+
Object.assign(t, r);
|
|
98
|
+
} };
|
|
99
|
+
}, pe = /* @__PURE__ */ new Set([
|
|
100
|
+
"select",
|
|
101
|
+
"date",
|
|
102
|
+
"daterange",
|
|
103
|
+
"time",
|
|
104
|
+
"cascader",
|
|
105
|
+
"tree",
|
|
106
|
+
"radio",
|
|
107
|
+
"checkbox"
|
|
108
|
+
]), fe = {
|
|
109
|
+
checkbox: "array",
|
|
110
|
+
daterange: "array",
|
|
111
|
+
file: "array",
|
|
112
|
+
image: "array",
|
|
113
|
+
number: "number",
|
|
114
|
+
rate: "number",
|
|
115
|
+
switch: "boolean"
|
|
116
|
+
}, ge = (e) => {
|
|
117
|
+
const t = (r) => r.map(
|
|
118
|
+
(o) => {
|
|
119
|
+
var c;
|
|
120
|
+
return JSON.stringify([
|
|
121
|
+
o.prop,
|
|
122
|
+
o.label,
|
|
123
|
+
o.type,
|
|
124
|
+
o.required ?? !1,
|
|
125
|
+
(c = o.rules) == null ? void 0 : c.map(({ regExp: d, message: g }) => [String(d), g])
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
).join("|");
|
|
129
|
+
let s = "", a = {};
|
|
130
|
+
return { rules: W(() => {
|
|
131
|
+
const r = e(), o = t(r);
|
|
132
|
+
if (o === s) return a;
|
|
133
|
+
const c = {};
|
|
134
|
+
return r.forEach((d) => {
|
|
135
|
+
var P;
|
|
136
|
+
const g = [], F = pe.has(d.type) ? "选择" : "输入";
|
|
137
|
+
d.required && g.push({
|
|
138
|
+
required: !0,
|
|
139
|
+
type: fe[d.type],
|
|
140
|
+
message: `请${F}${d.label}`,
|
|
141
|
+
trigger: ["blur", "change"]
|
|
142
|
+
}), (P = d.rules) == null || P.forEach(({ regExp: b, message: w }) => {
|
|
143
|
+
g.push({
|
|
144
|
+
validator: (R, C, k) => b(C) ? k() : k(new Error(w)),
|
|
145
|
+
trigger: ["blur", "change"]
|
|
146
|
+
});
|
|
147
|
+
}), g.length && (c[d.prop] = g);
|
|
148
|
+
}), s = o, a = c, c;
|
|
149
|
+
}) };
|
|
150
|
+
}, he = (e) => {
|
|
151
|
+
const t = G({});
|
|
152
|
+
return { items: W(
|
|
153
|
+
() => e().map((n) => {
|
|
154
|
+
const r = t[n.prop];
|
|
155
|
+
if (!r) return n;
|
|
156
|
+
const { extends: o, ...c } = r;
|
|
157
|
+
return {
|
|
158
|
+
...n,
|
|
159
|
+
...c,
|
|
160
|
+
// extends 单独浅合并,避免整体替换丢掉原有透传 props
|
|
161
|
+
...o ? { extends: { ...n.extends, ...o } } : {}
|
|
162
|
+
};
|
|
163
|
+
})
|
|
164
|
+
), setProps: (n, r) => {
|
|
165
|
+
const o = t[n], { extends: c, ...d } = r;
|
|
166
|
+
t[n] = {
|
|
167
|
+
...o,
|
|
168
|
+
...d,
|
|
169
|
+
...c ? { extends: { ...o == null ? void 0 : o.extends, ...c } } : {}
|
|
170
|
+
};
|
|
171
|
+
} };
|
|
172
|
+
}, be = {
|
|
173
|
+
key: 0,
|
|
174
|
+
class: "pro-form__required"
|
|
175
|
+
}, me = { class: "form-item-tip" }, _e = /* @__PURE__ */ D({
|
|
176
|
+
__name: "index",
|
|
177
|
+
props: {
|
|
178
|
+
template: { default: () => [] },
|
|
179
|
+
gutter: { default: 20 },
|
|
180
|
+
labelWidth: { default: "auto" },
|
|
181
|
+
labelPosition: { default: "right" },
|
|
182
|
+
scrollToError: { type: Boolean, default: !1 },
|
|
183
|
+
defaultValue: { default: () => ({}) },
|
|
184
|
+
tipPosition: { default: "bottom" }
|
|
185
|
+
},
|
|
186
|
+
emits: ["change", "init"],
|
|
187
|
+
setup(e, { expose: t, emit: s }) {
|
|
188
|
+
const a = s, n = e, { model: r, setField: o, getValue: c, setValue: d } = ie(n.defaultValue), { items: g, setProps: F } = he(() => n.template), { rules: P } = ge(() => g.value), b = M(), w = async () => {
|
|
189
|
+
var p;
|
|
190
|
+
try {
|
|
191
|
+
return await ((p = b.value) == null ? void 0 : p.validate()), !0;
|
|
192
|
+
} catch {
|
|
193
|
+
return !1;
|
|
194
|
+
}
|
|
195
|
+
}, R = () => {
|
|
196
|
+
var p;
|
|
197
|
+
return (p = b.value) == null ? void 0 : p.resetFields();
|
|
198
|
+
}, C = () => {
|
|
199
|
+
var p;
|
|
200
|
+
return (p = b.value) == null ? void 0 : p.clearValidate();
|
|
201
|
+
}, k = (p, v) => {
|
|
202
|
+
a("change", p, v);
|
|
203
|
+
};
|
|
204
|
+
return Q(() => {
|
|
205
|
+
a("init");
|
|
206
|
+
}), t({
|
|
207
|
+
model: r,
|
|
208
|
+
getValue: c,
|
|
209
|
+
setValue: d,
|
|
210
|
+
setProps: F,
|
|
211
|
+
validate: w,
|
|
212
|
+
reset: R,
|
|
213
|
+
clearValidate: C
|
|
214
|
+
}), (p, v) => {
|
|
215
|
+
const L = E("el-tooltip"), z = E("el-form-item"), A = E("el-col"), J = E("el-row"), H = E("el-form");
|
|
216
|
+
return m(), V(H, {
|
|
217
|
+
ref_key: "formRef",
|
|
218
|
+
ref: b,
|
|
219
|
+
class: "form",
|
|
220
|
+
"label-width": e.labelWidth,
|
|
221
|
+
"label-position": e.labelPosition,
|
|
222
|
+
model: _(r),
|
|
223
|
+
rules: _(P),
|
|
224
|
+
"scroll-to-error": e.scrollToError
|
|
225
|
+
}, {
|
|
226
|
+
default: h(() => [
|
|
227
|
+
S(J, { gutter: e.gutter }, {
|
|
228
|
+
default: h(() => [
|
|
229
|
+
(m(!0), j(X, null, Z(_(g), (i) => (m(), V(A, {
|
|
230
|
+
key: i.prop,
|
|
231
|
+
span: i.span || 24
|
|
232
|
+
}, {
|
|
233
|
+
default: h(() => [
|
|
234
|
+
S(z, {
|
|
235
|
+
"hide-required-asterisk": !0,
|
|
236
|
+
prop: i.prop
|
|
237
|
+
}, {
|
|
238
|
+
label: h(() => [
|
|
239
|
+
i.required ? (m(), j("span", be, "*")) : T("", !0),
|
|
240
|
+
q("span", null, B(i.label), 1),
|
|
241
|
+
i.tip && e.tipPosition === "left" ? (m(), V(L, {
|
|
242
|
+
key: 1,
|
|
243
|
+
content: i.tip,
|
|
244
|
+
placement: "top"
|
|
245
|
+
}, {
|
|
246
|
+
default: h(() => [...v[0] || (v[0] = [
|
|
247
|
+
q("i", {
|
|
248
|
+
class: "ri-question-fill",
|
|
249
|
+
style: { "font-size": "16px", color: "#f56c6c" }
|
|
250
|
+
}, null, -1)
|
|
251
|
+
])]),
|
|
252
|
+
_: 1
|
|
253
|
+
}, 8, ["content"])) : T("", !0)
|
|
254
|
+
]),
|
|
255
|
+
default: h(() => [
|
|
256
|
+
S(_(de), {
|
|
257
|
+
item: i,
|
|
258
|
+
model: _(r),
|
|
259
|
+
"set-field": _(o),
|
|
260
|
+
onChange: (K) => k(K, i)
|
|
261
|
+
}, null, 8, ["item", "model", "set-field", "onChange"]),
|
|
262
|
+
i.tip && e.tipPosition === "bottom" ? (m(), V(L, {
|
|
263
|
+
key: 0,
|
|
264
|
+
class: "box-item",
|
|
265
|
+
effect: "dark",
|
|
266
|
+
content: i.tip,
|
|
267
|
+
placement: "top-start"
|
|
268
|
+
}, {
|
|
269
|
+
default: h(() => [
|
|
270
|
+
q("div", me, B(i.tip), 1)
|
|
271
|
+
]),
|
|
272
|
+
_: 2
|
|
273
|
+
}, 1032, ["content"])) : T("", !0)
|
|
274
|
+
]),
|
|
275
|
+
_: 2
|
|
276
|
+
}, 1032, ["prop"])
|
|
277
|
+
]),
|
|
278
|
+
_: 2
|
|
279
|
+
}, 1032, ["span"]))), 128))
|
|
280
|
+
]),
|
|
281
|
+
_: 1
|
|
282
|
+
}, 8, ["gutter"])
|
|
283
|
+
]),
|
|
284
|
+
_: 1
|
|
285
|
+
}, 8, ["label-width", "label-position", "model", "rules", "scroll-to-error"]);
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
}), ye = (e, t) => {
|
|
289
|
+
const s = e.__vccOpts || e;
|
|
290
|
+
for (const [a, n] of t)
|
|
291
|
+
s[a] = n;
|
|
292
|
+
return s;
|
|
293
|
+
}, Y = /* @__PURE__ */ ye(_e, [["__scopeId", "data-v-121a6606"]]);
|
|
294
|
+
function Ee(e) {
|
|
295
|
+
e.component("ProForm", Y);
|
|
296
|
+
}
|
|
297
|
+
const ke = Object.assign(Y, { install: Ee });
|
|
298
|
+
export {
|
|
299
|
+
ke as ProForm,
|
|
300
|
+
ke as default
|
|
301
|
+
};
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.form-item-tip[data-v-121a6606]{width:100%;margin-top:4px;font-size:12px;line-height:1.5;color:#f56c6c;font-weight:500;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}[data-v-121a6606] .el-form-item__label:before{display:none!important}.pro-form__required[data-v-121a6606]{color:#f56c6c;margin-left:4px;font-size:18px}.pro-form__tip-icon[data-v-121a6606]{margin-left:4px;font-size:14px;color:#909399;cursor:help;vertical-align:middle}[data-v-121a6606] .box-item{color:#f56c6c}[data-v-121a6606] .el-input-number,[data-v-121a6606] .el-cascader{width:100%!important}[data-v-121a6606] .el-select,[data-v-121a6606] .el-cascader,[data-v-121a6606] .el-tree-select,[data-v-121a6606] .el-date-picker,[data-v-121a6606] .el-input{width:100%}[data-v-121a6606] .el-upload{--el-upload-picture-card-size: 100px}[data-v-121a6606] .el-upload .el-upload--picture-card,[data-v-121a6606] .el-upload .el-upload-list--picture-card .el-upload-list__item{border-radius:8px}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @liexx/table/interface/client
|
|
3
|
+
*
|
|
4
|
+
* 表格类型全局声明。(由 scripts/sync-interface.mjs 从 types/pro-form.ts 自动生成,请勿手工修改)
|
|
5
|
+
* 在 tsconfig.app.json 的 compilerOptions.types 中添加 "@liexx/table/interface/client",
|
|
6
|
+
* 即可无需 import 直接使用这些类型。
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
declare type FromItems = FromItem[];
|
|
10
|
+
|
|
11
|
+
declare type OptionItem = {
|
|
12
|
+
label?: string;
|
|
13
|
+
value?: any;
|
|
14
|
+
children?: OptionItem[];
|
|
15
|
+
[key: string]: any; // 允许自定义字段,如 cascader 的 deptName/deptId
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
declare type FormModel = Record<string, any>;
|
|
19
|
+
|
|
20
|
+
declare type FormRule = {
|
|
21
|
+
regExp: (value: any) => boolean;
|
|
22
|
+
message: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
declare type FormProps = {
|
|
26
|
+
template: FromItems; // 表单配置
|
|
27
|
+
gutter?: number; // 表单间距
|
|
28
|
+
labelWidth?: number | string; // 表单label宽度
|
|
29
|
+
labelPosition?: "left" | "right" | "top"; // 表单label位置
|
|
30
|
+
scrollToError?: boolean; // 校验不通过时滚动到第一个错误字段
|
|
31
|
+
defaultValue?: FormModel; // 表单默认值
|
|
32
|
+
tipPosition?: "left" | "bottom"; // 表单提示位置
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
declare type FromItem = {
|
|
36
|
+
label: string;
|
|
37
|
+
prop: string;
|
|
38
|
+
type:
|
|
39
|
+
| "input"
|
|
40
|
+
| "select"
|
|
41
|
+
| "date"
|
|
42
|
+
| "daterange"
|
|
43
|
+
| "cascader"
|
|
44
|
+
| "tree"
|
|
45
|
+
| "switch"
|
|
46
|
+
| "radio"
|
|
47
|
+
| "file"
|
|
48
|
+
| "image"
|
|
49
|
+
| "number"
|
|
50
|
+
| "textarea"
|
|
51
|
+
| "checkbox"
|
|
52
|
+
| "rate"
|
|
53
|
+
| "time"
|
|
54
|
+
| "file";
|
|
55
|
+
// 占位
|
|
56
|
+
span?: number;
|
|
57
|
+
// 输入框占位文本
|
|
58
|
+
placeholder?: string;
|
|
59
|
+
// 提示
|
|
60
|
+
tip?: string;
|
|
61
|
+
//是否必填
|
|
62
|
+
required?: boolean;
|
|
63
|
+
//自定义校验规则
|
|
64
|
+
rules?: FormRule[];
|
|
65
|
+
//是否禁用
|
|
66
|
+
disabled?: boolean;
|
|
67
|
+
//是否显示到表单
|
|
68
|
+
isForm?: boolean;
|
|
69
|
+
// 透传给组件的额外 props(如 select 的 options、daterange 的 type 等)
|
|
70
|
+
extends?: Record<string, any>;
|
|
71
|
+
// 字典值
|
|
72
|
+
dict?: string;
|
|
73
|
+
// 选项内容
|
|
74
|
+
options?: OptionItem[];
|
|
75
|
+
//通过api方式获取选择内容
|
|
76
|
+
optionsApi?: (params?: Record<string, any>) => Promise<Record<string, any>[]>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
declare type ProTableProps<T = any> = TableProps
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @liexx/table/interface/form
|
|
3
|
+
*
|
|
4
|
+
* 表格类型全局声明。(由 scripts/sync-interface.mjs 从 types/pro-form.ts 自动生成,请勿手工修改)
|
|
5
|
+
* 在 tsconfig.app.json 的 compilerOptions.types 中添加 "@liexx/table/interface/form",
|
|
6
|
+
* 即可无需 import 直接使用这些类型。
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
declare type FormItems = TableFilter[]
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@liexx/form",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Enhanced form component for Vue 3 based on Element Plus",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "ljc",
|
|
8
|
+
"packageManager": "pnpm@10.26.0",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"vue",
|
|
11
|
+
"vue3",
|
|
12
|
+
"form",
|
|
13
|
+
"pro-form",
|
|
14
|
+
"element-plus"
|
|
15
|
+
],
|
|
16
|
+
"main": "./dist/index.cjs",
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"interface"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": [
|
|
24
|
+
"**/*.css"
|
|
25
|
+
],
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js",
|
|
30
|
+
"require": "./dist/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./interface/client": {
|
|
33
|
+
"types": "./interface/client.d.ts"
|
|
34
|
+
},
|
|
35
|
+
"./interface/form": {
|
|
36
|
+
"types": "./interface/form.d.ts"
|
|
37
|
+
},
|
|
38
|
+
"./style.css": "./dist/style.css",
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"dev": "vite",
|
|
43
|
+
"sync:interface": "node scripts/sync-interface.mjs",
|
|
44
|
+
"build": "npm run sync:interface && vue-tsc --noEmit && vite build",
|
|
45
|
+
"preview": "vite preview",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:watch": "vitest",
|
|
48
|
+
"lint": "vue-tsc --noEmit",
|
|
49
|
+
"prepublishOnly": "npm run build"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"element-plus": "^2.13.7",
|
|
53
|
+
"vue": "^3.5.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@microsoft/api-extractor": "^7.59.1",
|
|
57
|
+
"@vitejs/plugin-vue": "^5.2.0",
|
|
58
|
+
"@vue/test-utils": "^2.4.6",
|
|
59
|
+
"@vue/tsconfig": "^0.7.0",
|
|
60
|
+
"element-plus": "^2.14.3",
|
|
61
|
+
"jsdom": "^25.0.0",
|
|
62
|
+
"sass-embedded": "^1.100.0",
|
|
63
|
+
"typescript": "~5.7.0",
|
|
64
|
+
"vite": "^6.0.0",
|
|
65
|
+
"vite-plugin-dts": "^4.5.0",
|
|
66
|
+
"vitest": "^2.1.0",
|
|
67
|
+
"vue": "^3.5.13",
|
|
68
|
+
"vue-tsc": "^2.2.0"
|
|
69
|
+
},
|
|
70
|
+
"publishConfig": {
|
|
71
|
+
"registry": "https://registry.npmjs.org",
|
|
72
|
+
"access": "public"
|
|
73
|
+
},
|
|
74
|
+
"dependencies": {
|
|
75
|
+
"remixicon": "^4.9.1"
|
|
76
|
+
}
|
|
77
|
+
}
|