@jari-ace/element-plus-component 0.1.9 → 0.1.10

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jari-ace/element-plus-component",
3
3
  "private": false,
4
- "version": "0.1.9",
4
+ "version": "0.1.10",
5
5
  "main": "lib/index.umd.cjs",
6
6
  "module": "lib/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "animate.css": "^4.1.1"
25
25
  },
26
26
  "devDependencies": {
27
- "@jari-ace/app-bolts": "0.3.6",
27
+ "@jari-ace/app-bolts": "catalog:",
28
28
  "@types/lodash-es": "^4.17.12",
29
29
  "@vitejs/plugin-vue": "^5.2.1",
30
30
  "@vitejs/plugin-vue-jsx": "^4.1.1",
@@ -3,7 +3,7 @@ import {type PropType, provide, ref, computed, watch} from "vue";
3
3
  import {ElForm, type FormInstance, type FormRules} from "element-plus";
4
4
  import {type ValidationInstance} from "../../hooks/useBackendValidations";
5
5
  import type {JaFormModel} from "./types";
6
-
6
+ import {mergeRules} from '../../utils/formUtils'
7
7
  interface Props {
8
8
  model: JaFormModel,
9
9
  inline?:boolean,
@@ -20,6 +20,7 @@ interface Props {
20
20
  disabled?: boolean,
21
21
  scrollToError?: boolean,
22
22
  validator: ValidationInstance,
23
+ requiredPosition?: 'left' | 'right'
23
24
  }
24
25
 
25
26
  const formRef = ref<FormInstance | undefined>(undefined);
@@ -35,82 +36,26 @@ const props = withDefaults(defineProps<Props>(),{
35
36
  validateOnRuleChange:true,
36
37
  size:'small',
37
38
  scrollToError:true,
38
-
39
+ requiredPosition:'right',
39
40
  })
40
41
 
41
- // const props = defineProps({
42
- // model: {
43
- // type: Object as PropType<JaFormModel>,
44
- // required: true,
45
- // },
46
- // inline: {
47
- // type: Boolean,
48
- // default: false,
49
- // },
50
- // labelPosition: {
51
- // type: String as PropType<"left" | "top" | "right">,
52
- // default: "top",
53
- // },
54
- // labelWidth: {
55
- // type: [String, Number],
56
- // },
57
- // labelSuffix: {
58
- // type: String,
59
- // },
60
- // hideRequiredAsterisk: {
61
- // type: Boolean,
62
- // default: false,
63
- // },
64
- // showMessage: {
65
- // type: Boolean,
66
- // default: true,
67
- // },
68
- // inlineMessage: {
69
- // type: Boolean,
70
- // default: true,
71
- // },
72
- // statusIcon: {
73
- // type: Boolean,
74
- // default: false,
75
- // },
76
- // validateOnRuleChange: {
77
- // type: Boolean,
78
- // default: true,
79
- // },
80
- // rules: {
81
- // type: Object as PropType<FormRules>,
82
- // default: {},
83
- // },
84
- // size: {
85
- // type: String as PropType<"small" | "default" | "large">,
86
- // default: "small",
87
- // },
88
- // disabled: {
89
- // type: Boolean,
90
- // default: false,
91
- // },
92
- // scrollToError: {
93
- // type: Boolean,
94
- // default: true,
95
- // },
96
- // validator: {
97
- // type: Object as PropType<ValidationInstance>,
98
- // required: true,
99
- // },
100
- // });
42
+
43
+
44
+
101
45
 
102
46
  defineEmits(["validate", "click"]);
103
47
  provide("aceFormValidator", props.validator);
104
48
  provide("aceFormModel", props.model);
105
49
  provide("aceFormSize", props.size);
50
+ provide("aceFormRequiredPosition", props.requiredPosition);
51
+ const rules = ref<FormRules>({})
106
52
 
107
- const rules = computed<FormRules>(() => {
108
- return {
109
- ...props.rules,
110
- ...props.validator.rules,
111
- };
53
+ const model = computed(() => {
54
+ return props.model.formData?props.model.formData:props.model;
112
55
  });
113
56
 
57
+
58
+
114
59
  defineExpose({
115
60
  elForm: formRef,
116
61
  getElForm:():FormInstance|undefined=>formRef.value,
@@ -119,18 +64,21 @@ defineExpose({
119
64
  //先清空之前的校验
120
65
  formRef.value.clearValidate();
121
66
  //判断是否有传入rules如果有则先执行 formRef.value!.validate()
122
- if(props.rules){
67
+ if(props.rules && Object.keys(props.rules).length>0){
123
68
  await formRef.value.validate((valid,fields)=>{
124
69
  //判断校验是否成功
125
70
  if(valid){
126
71
  //前端校验已成功,执行异步submit
127
72
  submit()
128
73
  .then(() => {
74
+ //成功
129
75
  //校验通过清楚所有的错误校验信息
130
76
  props.validator?.clearFiledErrors();
131
77
  })
132
78
  .catch(() => {
133
79
  //失败
80
+ //合并rules
81
+ rules.value = mergeRules(props.rules, props.validator.rules);
134
82
  formRef.value.validate();
135
83
  if (onFail) onFail();
136
84
  });
@@ -144,6 +92,9 @@ defineExpose({
144
92
  props.validator?.clearFiledErrors();
145
93
  })
146
94
  .catch(async () => {
95
+ //失败
96
+ //合并rules
97
+ rules.value = mergeRules(props.rules, props.validator.rules);
147
98
  await formRef.value.validate();
148
99
  if (onFail) onFail();
149
100
  });
@@ -152,17 +103,26 @@ defineExpose({
152
103
 
153
104
 
154
105
  },
106
+ getRules: () => rules.value,
155
107
  });
156
108
 
109
+
157
110
  watch(() => props.model.formData, () => {
158
111
  props.validator?.clearFiledErrors();
159
112
  })
113
+
114
+ watch(() => props.rules, () => {
115
+ //合并rules
116
+ rules.value = mergeRules(props.rules, props.validator.rules);
117
+ }, { immediate: true })
118
+
119
+
160
120
  </script>
161
121
 
162
122
  <template>
163
123
  <el-form
164
124
  ref="formRef"
165
- :model="model.formData"
125
+ :model="model"
166
126
  :rules="rules"
167
127
  :inline="inline"
168
128
  :label-position="labelPosition"
@@ -1,8 +1,13 @@
1
1
  <script setup lang="ts">
2
- import {provide, ref, withDefaults, defineProps, defineExpose} from 'vue'
2
+ import { provide, ref, withDefaults, defineProps, defineExpose, inject, computed } from "vue";
3
3
  import {ElFormItem, ElIcon, ElText, type FormItemRule, ElTooltip} from 'element-plus'
4
4
  import {QuestionFilled} from "@element-plus/icons-vue";
5
5
 
6
+ type RequiredPosition = 'left' | 'right'
7
+
8
+
9
+
10
+ const aceFormRequiredPosition = inject('aceFormRequiredPosition')
6
11
  const props = withDefaults(defineProps<{
7
12
  prop?: string | string[]
8
13
  rules?: FormItemRule | FormItemRule[]
@@ -14,15 +19,23 @@ const props = withDefaults(defineProps<{
14
19
  showMessage?: boolean
15
20
  inlineMessage?: boolean
16
21
  size?: 'small' | 'default' | 'large'
22
+ requiredPosition?: RequiredPosition
23
+ labelGap?:string
17
24
  }>(), {
18
25
  required: false,
19
26
  showMessage: true,
20
27
  inlineMessage: true,
21
- size: 'small'
28
+ size: 'small',
29
+ labelGap:'4px'
22
30
  })
23
31
 
24
32
  provide('aceFormItemProp', props.prop)
25
33
 
34
+ const requiredPosition = computed(()=>{
35
+ return props.requiredPosition || aceFormRequiredPosition
36
+ })
37
+
38
+
26
39
  const formItem = ref<typeof ElFormItem | null>(null)
27
40
  defineExpose({
28
41
  resetField: () => {
@@ -46,20 +59,26 @@ defineExpose({
46
59
  :inline-message="inlineMessage"
47
60
  :size="size">
48
61
  <template #label>
49
- <el-text class="el-form-item__label">
50
- {{ props.label }}
51
- <span style="color:red" v-if="props.required">*</span>
52
- <el-tooltip
53
- v-if="labelRemark"
54
- placement="top">
55
- <el-icon>
56
- <question-filled/>
57
- </el-icon>
58
- <template #content>
59
- <div v-html="labelRemark"/>
60
- </template>
61
- </el-tooltip>
62
- </el-text>
62
+ <div style="display: flex;" :style="{
63
+ gap: labelGap
64
+ }">
65
+ <span style="color:red" v-if="props.required && requiredPosition==='left'">*</span>
66
+ <el-text class="el-form-item__label">
67
+ {{ props.label }}
68
+ <el-tooltip
69
+ v-if="labelRemark"
70
+ placement="top">
71
+ <el-icon>
72
+ <question-filled/>
73
+ </el-icon>
74
+ <template #content>
75
+ <div v-html="labelRemark"/>
76
+ </template>
77
+ </el-tooltip>
78
+ </el-text>
79
+ <span style="color:red" v-if="props.required && requiredPosition==='right'">*</span>
80
+ </div>
81
+
63
82
  </template>
64
83
  <slot></slot>
65
84
  <slot name="error"></slot>
@@ -1,81 +1,81 @@
1
- import type { FormRules ,FormItemRule} from "element-plus";
2
- import type { IAceAxios, ValidationError } from "@jari-ace/app-bolts";
3
- import { createAxiosWithoutCache } from "@jari-ace/app-bolts";
4
- import { reactive } from "vue";
5
-
6
- export type ValidationInstance = {
7
- axios: IAceAxios;
8
- rules: FormRules;
9
- removeFieldError: (prop: string) => void;
10
- clearFiledErrors: () => void;
11
- };
12
-
13
- /**
14
- * 后端校验
15
- * @param props
16
- * @param axios
17
- * @param customRules
18
- */
19
- export function useBackendValidations(
20
- props: string[],
21
- axios?: IAceAxios,
22
- customRules?: FormRules,
23
- ): ValidationInstance {
24
- const rules = reactive<FormRules>({});
25
- let errors: ValidationError[] = [];
26
- if (!axios) axios = createAxiosWithoutCache();
27
- axios!.setDefaultRequestConfig({
28
- validationErrorProcessor: (errs) => {
29
- errors = errs;
30
- },
31
- });
32
-
33
- for (const p of props) {
34
- // rules[p] = [
35
- const rule = {
36
- trigger: "blur",
37
- validator: (rule: any, value: any, callback: any) => {
38
- if (!errors) return;
39
- let hasErr = false;
40
- for (const err of errors) {
41
- let fn = err.fieldName;
42
- if (fn?.endsWith("[]")) {
43
- fn = fn.substring(0, fn.length - 2);
44
- }
45
- if (fn === p) {
46
- hasErr = true;
47
- callback(new Error(err.message));
48
- }
49
- }
50
- if (!hasErr) callback();
51
- },
52
- };
53
-
54
- if (customRules&&customRules[p]) {
55
- //合并数组customRules[p]
56
- if (Array.isArray(customRules[p])) {
57
- rules[p] = [rule,...customRules[p] as FormItemRule[]];
58
- } else {
59
- rules[p] = [rule, customRules[p] as FormItemRule];
60
- }
61
- }else{
62
- rules[p] = rule
63
- }
64
-
65
-
66
- }
67
- const removeFieldError = (prop: string) => {
68
- errors = errors.filter((err) => err.fieldName !== prop);
69
- };
70
- const clearFiledErrors = () => {
71
- errors = [];
72
- };
73
-
74
-
75
- return {
76
- removeFieldError,
77
- clearFiledErrors,
78
- axios,
79
- rules,
80
- };
81
- }
1
+ import type { FormRules ,FormItemRule} from "element-plus";
2
+ import type { IAceAxios, ValidationError } from "@jari-ace/app-bolts";
3
+ import { createAxiosWithoutCache } from "@jari-ace/app-bolts";
4
+ import { reactive } from "vue";
5
+ import {mergeRules} from '../utils/formUtils'
6
+ export type ValidationInstance = {
7
+ axios: IAceAxios;
8
+ rules: FormRules;
9
+ removeFieldError: (prop: string) => void;
10
+ clearFiledErrors: () => void;
11
+ };
12
+
13
+ /**
14
+ * 后端校验
15
+ * @param props
16
+ * @param axios
17
+ * @param customRules
18
+ */
19
+ export function useBackendValidations(
20
+ props: string[],
21
+ axios?: IAceAxios,
22
+ customRules?: FormRules,
23
+ ): ValidationInstance {
24
+ const rules = reactive<FormRules>({});
25
+ let errors: ValidationError[] = [];
26
+ if (!axios) axios = createAxiosWithoutCache();
27
+ axios!.setDefaultRequestConfig({
28
+ validationErrorProcessor: (errs) => {
29
+ errors = errs;
30
+ },
31
+ });
32
+
33
+ for (const p of props) {
34
+ // rules[p] = [
35
+ const rule = {
36
+ trigger: "blur",
37
+ validator: (rule: any, value: any, callback: any) => {
38
+ if (!errors) return;
39
+ let hasErr = false;
40
+ for (const err of errors) {
41
+ let fn = err.fieldName;
42
+ if (fn?.endsWith("[]")) {
43
+ fn = fn.substring(0, fn.length - 2);
44
+ }
45
+ if (fn === p) {
46
+ hasErr = true;
47
+ callback(new Error(err.message));
48
+ }
49
+ }
50
+ if (!hasErr) callback();
51
+ },
52
+ };
53
+
54
+ if (customRules&&customRules[p]) {
55
+ //合并数组customRules[p]
56
+ if (Array.isArray(customRules[p])) {
57
+ rules[p] = [rule,...customRules[p] as FormItemRule[]];
58
+ } else {
59
+ rules[p] = [rule, customRules[p] as FormItemRule];
60
+ }
61
+ }else{
62
+ rules[p] = rule
63
+ }
64
+
65
+
66
+ }
67
+ const removeFieldError = (prop: string) => {
68
+ errors = errors.filter((err) => err.fieldName !== prop);
69
+ };
70
+ const clearFiledErrors = () => {
71
+ errors = [];
72
+ };
73
+
74
+
75
+ return {
76
+ removeFieldError,
77
+ clearFiledErrors,
78
+ axios,
79
+ rules,
80
+ };
81
+ }
@@ -0,0 +1,57 @@
1
+ import {type FormRules,type FormItemRule} from "element-plus";
2
+
3
+ /**
4
+ * 合并 rules 方法
5
+ * 将后端的rules合并到props.rules中
6
+ */
7
+ export function mergeRules(frontendRules: FormRules, backendRules: FormRules): FormRules {
8
+ //合并里面的rules
9
+ let newRules: FormRules = {}
10
+
11
+ //浅拷贝
12
+ frontendRules = {...frontendRules};
13
+ backendRules = {...backendRules};
14
+
15
+ const frontendRulesKey: string[] = Object.keys(frontendRules);
16
+ const backendRulesKey: string[] = Object.keys(backendRules);
17
+
18
+ if (frontendRulesKey.length > 0 && backendRulesKey.length === 0) {
19
+ return frontendRules;
20
+ } else if (frontendRulesKey.length === 0 && backendRulesKey.length > 0) {
21
+ return backendRules;
22
+ } else if (
23
+ frontendRulesKey.length === 0 && backendRulesKey.length === 0
24
+ ) {
25
+ return {}
26
+ } else { //frontendRulesKey 和 backendRulesKey 都有值
27
+ backendRulesKey.forEach(key => {
28
+ //frontendRulesKey中是否存在key
29
+ if (frontendRulesKey.includes(key)) {
30
+ if (Array.isArray(frontendRules[key]) && Array.isArray(backendRules[key])) {
31
+ newRules[key] = [...frontendRules[key] as FormItemRule[], ...backendRules[key] as FormItemRule[]];
32
+ }
33
+ //props.rules[key] 为对象 props.validator.rules[key]为数组
34
+ else if (!Array.isArray(frontendRules[key]) && Array.isArray(backendRules[key])) {
35
+ newRules[key] = [frontendRules[key] as FormItemRule, ...backendRules[key] as FormItemRule[]];
36
+ }
37
+ //props.rules[key] 为数组 props.validator.rules[key]为对象
38
+ else if (Array.isArray(frontendRules[key]) && !Array.isArray(backendRules[key])) {
39
+ newRules[key] = [...frontendRules[key] as FormItemRule[], backendRules[key] as FormItemRule];
40
+ }
41
+ //判断当前key的值类型是否都为对象
42
+ else if (!Array.isArray(frontendRules[key]) && !Array.isArray(backendRules[key])) {
43
+ newRules[key] = [frontendRules[key] as FormItemRule, backendRules[key] as FormItemRule];
44
+ }
45
+ } else {
46
+ newRules[key] = backendRules[key];
47
+ }
48
+ //删除对应的 key
49
+ delete frontendRules[key];
50
+ delete backendRules[key];
51
+ })
52
+ newRules = {...newRules, ...frontendRules};
53
+ return newRules;
54
+ }
55
+
56
+
57
+ }