@neatui/nuxt 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +3 -0
  2. package/package.json +43 -0
  3. package/rollup.config.js +35 -0
  4. package/src/components/basic/IDraggable.vue +84 -0
  5. package/src/components/basic/IDraggable@b.vue +80 -0
  6. package/src/components/basic/IFollowView.vue +211 -0
  7. package/src/components/basic/IPickerView.vue +351 -0
  8. package/src/components/basic/IRouterView.vue +360 -0
  9. package/src/components/basic/IScrollView.vue +127 -0
  10. package/src/components/basic/Icon.vue +54 -0
  11. package/src/components/basic/LayerView/Layer.vue +339 -0
  12. package/src/components/basic/LayerView/index.ts +5 -0
  13. package/src/components/basic/index.ts +7 -0
  14. package/src/components/display/Avatar.vue +1 -0
  15. package/src/components/display/Badge.vue +1 -0
  16. package/src/components/display/Calendar.vue +245 -0
  17. package/src/components/display/CalendarReg.vue +245 -0
  18. package/src/components/display/Card.vue +1 -0
  19. package/src/components/display/Carousel.vue +1 -0
  20. package/src/components/display/ChartView.vue +123 -0
  21. package/src/components/display/Collapse.vue +1 -0
  22. package/src/components/display/Desriptions.vue +1 -0
  23. package/src/components/display/Empty.vue +1 -0
  24. package/src/components/display/Image.vue +112 -0
  25. package/src/components/display/List.vue +1 -0
  26. package/src/components/display/PhotoEditor.vue +181 -0
  27. package/src/components/display/PhotoViewer.vue +50 -0
  28. package/src/components/display/Popover.vue +1 -0
  29. package/src/components/display/QRCode.vue +1 -0
  30. package/src/components/display/Segmented.vue +1 -0
  31. package/src/components/display/Statistic.vue +1 -0
  32. package/src/components/display/Table.vue +1 -0
  33. package/src/components/display/Tabs.vue +1 -0
  34. package/src/components/display/Tag.vue +1 -0
  35. package/src/components/display/Timeline.vue +1 -0
  36. package/src/components/display/Tooltip.vue +1 -0
  37. package/src/components/display/Tour.vue +1 -0
  38. package/src/components/display/Tree.vue +431 -0
  39. package/src/components/display/TreeView.vue +225 -0
  40. package/src/components/display/index.ts +8 -0
  41. package/src/components/form/Cascader.vue +435 -0
  42. package/src/components/form/DatePicker.vue +124 -0
  43. package/src/components/form/DateRangePicker@v2.vue.backup +224 -0
  44. package/src/components/form/DateRangePicker@v3.vue +116 -0
  45. package/src/components/form/DateRangeView@v3.vue +386 -0
  46. package/src/components/form/DateView.vue +229 -0
  47. package/src/components/form/DateView@v2.vue +386 -0
  48. package/src/components/form/DateView@v3.vue +471 -0
  49. package/src/components/form/EditUpload.vue +4 -0
  50. package/src/components/form/ImgUpload.vue +174 -0
  51. package/src/components/form/Input.vue.backup +230 -0
  52. package/src/components/form/Input@v3.vue +267 -0
  53. package/src/components/form/InputNumber.vue +200 -0
  54. package/src/components/form/InputRange.vue +235 -0
  55. package/src/components/form/MoreSelect.vue.backup +144 -0
  56. package/src/components/form/MoreSelect@v3.vue +195 -0
  57. package/src/components/form/MoreSelectList.vue +125 -0
  58. package/src/components/form/MoreSelectPanel@v3.vue +190 -0
  59. package/src/components/form/MoreSelectPicker.vue +124 -0
  60. package/src/components/form/MoreSelectTags.vue +124 -0
  61. package/src/components/form/PageMoreSelect.vue +187 -0
  62. package/src/components/form/PageSelect.vue +189 -0
  63. package/src/components/form/SearchMoreSelect.vue +173 -0
  64. package/src/components/form/SearchSelect.vue.backup +194 -0
  65. package/src/components/form/SearchSelect@v3.vue +202 -0
  66. package/src/components/form/Select@v3.vue +201 -0
  67. package/src/components/form/SelectList.vue +58 -0
  68. package/src/components/form/SelectPicker.vue +97 -0
  69. package/src/components/form/SelectTags.vue +52 -0
  70. package/src/components/form/SelectTree/SelectTree@v1.vue +227 -0
  71. package/src/components/form/Switch.vue +135 -0
  72. package/src/components/form/TextArea.vue +193 -0
  73. package/src/components/form/TimePicker.vue +11 -0
  74. package/src/components/form/TimeView.vue +244 -0
  75. package/src/components/form/Upload.vue +346 -0
  76. package/src/components/form/index.ts +82 -0
  77. package/src/components/loader/FormLoader/FormLoader@v2.vue +422 -0
  78. package/src/components/loader/FormLoader/FormLoader@v3.vue.backup +318 -0
  79. package/src/components/loader/FormLoader/index.ts +2 -0
  80. package/src/components/loader/FormLoader@v1/FormLoader.vue +506 -0
  81. package/src/components/loader/FormLoader@v1/FormRender.vue +277 -0
  82. package/src/components/loader/LimitLoader/LimitLoader.vue.backup +131 -0
  83. package/src/components/loader/LimitLoader/LimitLoader@v2.vue.backup +174 -0
  84. package/src/components/loader/LimitLoader/LimitLoader@v3.vue +183 -0
  85. package/src/components/loader/LimitLoader/index.ts +2 -0
  86. package/src/components/loader/TableLoader/TableColView.vue +115 -0
  87. package/src/components/loader/TableLoader/TableLoader.vue +360 -0
  88. package/src/components/loader/TableLoader/index.ts +2 -0
  89. package/src/components/loader/ViewLoader/ViewLoader@v1.vue +256 -0
  90. package/src/components/loader/ViewLoader/index.ts +2 -0
  91. package/src/components/loader/index.ts +5 -0
  92. package/src/components/tools/FormDraftsView.vue +330 -0
  93. package/src/components/tools/FormVerifyView.vue +206 -0
  94. package/src/components/tools/MoreTools.vue +74 -0
  95. package/src/components/tools/MoreTools@v2.vue +74 -0
  96. package/src/components/tools/Pagination@a.vue +222 -0
  97. package/src/components/tools/Pagination@b.vue +221 -0
  98. package/src/components/tools/index.ts +5 -0
  99. package/src/index.ts +9 -0
  100. package/src/shims-vue.d.ts +5 -0
  101. package/src/store/myui.ts +50 -0
  102. package/tsconfig.json +24 -0
@@ -0,0 +1,235 @@
1
+ <template>
2
+ <div :ui-form="`${theme} sz:${sz} ${state.co} type:input ${block ? ' :block' : ''} ${disabled ? 'disabled' : ''} ${readonly ? 'readonly' : ''}`" @click="emits('click', $event)">
3
+ <div v-if="ready" :ui-form-tips="state.ontips">{{ state.tips }}</div>
4
+ <div ui-form-prefix="">
5
+ <template v-for="(item, idx) in prefix" :key="idx">
6
+ <div v-html="isObject(item) ? item.html : item"></div>
7
+ </template>
8
+ <slot name="prefix"></slot>
9
+ </div>
10
+ <slot>
11
+ <div ui-flex="row lm">
12
+ <input v-model="sta" :type="type" :placeholder="placeholder" :readonly="readonly || disabled" @focus="emits('focus', $event)" @blur="emits('blur', $event)" />
13
+ <span class="o-mm">⇀</span>
14
+ <input v-model="end" :type="type" :placeholder="placeholder" :readonly="readonly || disabled" @focus="emits('focus', $event)" @blur="emits('blur', $event)" />
15
+ </div>
16
+ </slot>
17
+ <div ui-form-suffix="">
18
+ <i ui-form-clean="" v-if="clearable && sta && !readonly && !disabled" @click.stop="fClear"></i>
19
+ <slot name="suffix"></slot>
20
+ <template v-for="(item, idx) in suffix" :key="idx">
21
+ <div v-html="isObject(item) ? item.html : item"></div>
22
+ </template>
23
+ </div>
24
+ <i v-if="ready && verify" :ui-form-verify="state.verify"></i>
25
+ </div>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ import { isObject } from '@fekit/utils';
30
+ import { ref, watch, computed, PropType } from 'vue';
31
+
32
+ const emits = defineEmits(['update:modelValue', 'click', 'blur', 'focus', 'change', 'clear']);
33
+
34
+ /**
35
+ * 入参说明
36
+ *
37
+ * modelValue 值
38
+ * theme 主题
39
+ * sz 尺寸
40
+ * co 颜色
41
+ * block 撑满
42
+ * ready 准备就绪
43
+ * type 类型
44
+ * tips 提示文案
45
+ * placeholder 内容占位
46
+ * maxlength 最大长度
47
+ * minlength 最小长度
48
+ * disabled 是否禁用
49
+ * readonly 是否只读
50
+ * clearable 是否显示清除按钮
51
+ * rules 校验规则
52
+ * verify 是否是示校验图标
53
+ * prefix 前缀内容
54
+ * suffix 后缀内容
55
+ * interacted 用户是否交互
56
+ */
57
+
58
+ // 类型
59
+ interface Props {
60
+ modelValue?: Array<string | number>;
61
+ placeholder?: string;
62
+ rules?: Array<object>;
63
+ theme?: string;
64
+ sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
65
+ co?: string;
66
+ block?: boolean;
67
+ // ready?: boolean;
68
+ type?: string;
69
+ tips?: string;
70
+ maxlength?: null | number;
71
+ minlength?: null | number;
72
+ disabled?: boolean;
73
+ readonly?: boolean;
74
+ clearable?: boolean;
75
+ verify?: boolean;
76
+ prefix?: Array<any>;
77
+ suffix?: Array<any>;
78
+ interacted?: boolean;
79
+ }
80
+
81
+ const props: any = withDefaults(defineProps<Props>(), {
82
+ modelValue: () => [],
83
+ placeholder: '',
84
+ rules: () => [],
85
+ theme: '@a',
86
+ sz: '',
87
+ co: '',
88
+ block: true,
89
+ // ready: false,
90
+ type: 'text',
91
+ tips: '',
92
+ maxlength: null,
93
+ minlength: null,
94
+ disabled: false,
95
+ readonly: false,
96
+ clearable: true,
97
+ verify: false,
98
+ prefix: () => [],
99
+ suffix: () => [],
100
+ interacted: false
101
+ });
102
+ // const props = defineProps({
103
+ // theme: { type: String, default: '@a' },
104
+ // sz: { type: String, default: '' },
105
+ // co: { type: String, default: '' },
106
+ // block: { type: Boolean, default: true },
107
+ // // 值
108
+ // modelValue: {
109
+ // type: Array,
110
+ // default: () => []
111
+ // },
112
+ // // 类型
113
+ // type: {
114
+ // type: String,
115
+ // default: 'text'
116
+ // },
117
+ // // 提示文案
118
+ // tips: {
119
+ // type: String,
120
+ // default: ''
121
+ // },
122
+ // // 内容占位
123
+ // placeholder: {
124
+ // type: String,
125
+ // default: ''
126
+ // },
127
+ // // 最大长度
128
+ // maxlength: {
129
+ // type: Number,
130
+ // default: null
131
+ // },
132
+ // // 最小长度
133
+ // minlength: {
134
+ // type: Number,
135
+ // default: null
136
+ // },
137
+ // // 是否禁用
138
+ // disabled: {
139
+ // type: Boolean,
140
+ // default: false
141
+ // },
142
+ // // 是否中读
143
+ // readonly: {
144
+ // type: Boolean,
145
+ // default: false
146
+ // },
147
+ // // 是否显示清除按钮
148
+ // clearable: {
149
+ // type: Boolean,
150
+ // default: true
151
+ // },
152
+ // // 校验规则
153
+ // rules: {
154
+ // type: Array,
155
+ // default: () => []
156
+ // },
157
+ // // 是否是示校验图标
158
+ // verify: {
159
+ // type: Boolean,
160
+ // default: false
161
+ // },
162
+ // prefix: {
163
+ // type: Array as PropType<any[]>,
164
+ // default: () => []
165
+ // },
166
+ // suffix: {
167
+ // type: Array as PropType<any[]>,
168
+ // default: () => []
169
+ // }
170
+ // });
171
+
172
+ const ready: any = ref(0);
173
+ const state: any = computed(() => {
174
+ if (ready.value) {
175
+ // 提示文案
176
+ let tips = '';
177
+ // 错误类型
178
+ let type = '';
179
+ // 验证结果
180
+ let verify = '';
181
+ if (props.modelValue) {
182
+ // 有值
183
+ const res: any = props.rules?.some((rule: any) => {
184
+ const yes = rule.validator && !rule.validator(props.modelValue);
185
+ tips = rule.msg;
186
+ type = rule.type;
187
+ return yes;
188
+ });
189
+ verify = res ? 'no' : 'ok';
190
+ } else {
191
+ // 无值
192
+ const res: any = props.rules?.some((rule: any) => {
193
+ tips = rule.msg;
194
+ type = rule.type;
195
+ return rule.required;
196
+ });
197
+ verify = res ? 'no' : '';
198
+ }
199
+ if (verify !== 'no' && props.tips) {
200
+ tips = props.tips;
201
+ }
202
+ // 是否显示提示
203
+ const ontips = verify === 'no' && tips ? 'show' : '';
204
+ // 状态颜色
205
+ const co = verify === 'no' ? 'co:' + type : props.co ? 'co:' + props.co : '';
206
+ return { tips, ontips, verify, co };
207
+ } else {
208
+ return {};
209
+ }
210
+ });
211
+
212
+ const sta: any = ref('');
213
+ const end: any = ref('');
214
+
215
+ // 清空
216
+ function fClear() {
217
+ emits('update:modelValue', []);
218
+ emits('clear');
219
+ }
220
+
221
+ watch(
222
+ () => props.modelValue,
223
+ (newValue) => {
224
+ sta.value = newValue[0];
225
+ end.value = newValue[1];
226
+ },
227
+ {
228
+ deep: true,
229
+ immediate: true
230
+ }
231
+ );
232
+ watch([() => sta.value, () => end.value], () => {
233
+ emits('update:modelValue', [sta.value, end.value]);
234
+ });
235
+ </script>
@@ -0,0 +1,144 @@
1
+ <template>
2
+ <div :ui-form="`@a type:select ${sz ? 'sz:' + sz : ''}`">
3
+ <IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%">
4
+ <slot>
5
+ <Input v-bind="$props" :clearable="false" readonly v-model="state.value" :interacted="interacted">
6
+ <template #suffix><i ui-form-select=""></i></template>
7
+ </Input>
8
+ </slot>
9
+ <template #tips>
10
+ <ul v-if="props.options?.length" ui-scroll=":y s" class="nx-sm lh-ml" style="min-width: 100%; max-height: 15em">
11
+ <template v-for="(item, idx) of props.options" :key="idx">
12
+ <li v-if="item.disable" class="ux-hover nx-sm r-ss o-ms">
13
+ <label style="pointer-events: none" ui-form="@a type:checkbox :block">
14
+ <input type="checkbox" :name="state.name" :checked="modelValue?.some((i: any) => `${i}` === `${item.value}`)" />
15
+ <del class="ml-sm">{{ item.label || item }}</del>
16
+ </label>
17
+ </li>
18
+ <li v-else class="ux-hover nx-sm r-ss" @click.stop="select(item.value)">
19
+ <label style="pointer-events: none" ui-form="@a type:checkbox :block">
20
+ <input type="checkbox" :name="state.name" :checked="modelValue?.some((i: any) => `${i}` === `${item.value}`)" />
21
+ <span class="ml-sm">{{ item.label || item }}</span>
22
+ </label>
23
+ </li>
24
+ </template>
25
+ </ul>
26
+ <div v-else class="w-full ny-ms" ui-flex="col cm" v-html="spare"></div>
27
+ <ul class="nx-sm lh-ml" v-if="tools">
28
+ <li class="my-ss"><div class="o-mm" ui-line="@a"></div></li>
29
+ <li ui-flex="row xm">
30
+ <div class="ux-hover nx-sm r-ss nowrap co-main" @click.stop="allselect()">
31
+ <label style="pointer-events: none" ui-form="@a type:checkbox :block">
32
+ <input type="checkbox" :name="state.name" :checked="state.all" />
33
+ <span class="ml-sm">全选({{ props.options?.length || 0 }})</span>
34
+ </label>
35
+ </div>
36
+ <div>
37
+ <button v-show="state.has" class="co-risk" ui-btn="@a none s" @click="remove">清空</button>
38
+ </div>
39
+ </li>
40
+ </ul>
41
+ </template>
42
+ </IFollowView>
43
+ </div>
44
+ </template>
45
+
46
+ <script setup lang="ts">
47
+ import { reactive, ref, computed, watch } from 'vue';
48
+ import { Input } from '../form';
49
+ import { IFollowView } from '../basic';
50
+ const ifollow: any = ref(null);
51
+
52
+ const emits = defineEmits(['update:modelValue']);
53
+ const props: any = defineProps({
54
+ // 用户是否交互
55
+ interacted: {
56
+ type: Boolean,
57
+ default: false
58
+ },
59
+ theme: { type: String, default: '@a' },
60
+ sz: { type: String, default: '' },
61
+ co: { type: String, default: '' },
62
+ block: { type: Boolean, default: true },
63
+ // 提示文案
64
+ tips: {
65
+ type: String,
66
+ default: ''
67
+ },
68
+ placeholder: {
69
+ type: String,
70
+ default: ''
71
+ },
72
+ modelValue: {
73
+ type: Array as () => any[],
74
+ default: () => []
75
+ },
76
+ options: {
77
+ type: Array as () => any[],
78
+ default: () => []
79
+ },
80
+ // 校验规则
81
+ rules: {
82
+ type: Array,
83
+ default: () => []
84
+ },
85
+ // 是否是示校验图标
86
+ verify: {
87
+ type: Boolean,
88
+ default: false
89
+ },
90
+ tools: {
91
+ type: Boolean,
92
+ default: true
93
+ },
94
+ spare: {
95
+ type: String,
96
+ default: '当前没有可选项'
97
+ }
98
+ });
99
+
100
+ const state: any = reactive({
101
+ name: computed(() => {
102
+ return Array.from({ length: 8 }, () => String.fromCharCode(97 + Math.floor(Math.random() * 26))).join('');
103
+ }),
104
+ show: 0,
105
+ value: '',
106
+ all: computed(() => {
107
+ return props.options?.every((item: any) => props.modelValue?.some((i: any) => `${i}` === `${item.value}`));
108
+ }),
109
+ has: computed(() => {
110
+ return props.options?.some((item: any) => props.modelValue?.some((i: any) => `${i}` === `${item.value}`));
111
+ })
112
+ });
113
+
114
+ // 监听外部数据
115
+ watch(
116
+ () => props.modelValue,
117
+ (v: any = []) => {
118
+ const selectd: any = props.options?.filter((item: any) => v?.some((i: any) => `${i}` === `${item.value}`))?.map((item: any) => item.label) || [];
119
+ state.value = selectd.join(' Ι ') || '';
120
+ },
121
+ { deep: true, immediate: true }
122
+ );
123
+
124
+ // 更新
125
+ const change = (item: any) => {
126
+ emits('update:modelValue', item);
127
+ };
128
+ // 选中
129
+ const select = (item: any) => {
130
+ const s = [...props.modelValue];
131
+ s?.indexOf(item) !== -1 ? s?.splice(s?.indexOf(item), 1) : s?.push(item);
132
+ change(s);
133
+ };
134
+ // 全选
135
+ const allselect = () => {
136
+ const s = state.all ? [] : props.options?.map((item: any) => item.value);
137
+ change(s);
138
+ };
139
+ // 清除
140
+ const remove = () => {
141
+ change([]);
142
+ ifollow.value.cancel();
143
+ };
144
+ </script>
@@ -0,0 +1,195 @@
1
+ <template>
2
+ <div :ui-form="`@a type:select ${sz ? 'sz:' + sz : ''}`">
3
+ <IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%">
4
+ <slot>
5
+ <Input
6
+ v-bind="{ placeholder, rules, theme, sz, co, block, ready: true, type: 'text', tips, disabled, readonly, clearable: false, verify, prefix, suffix, interacted }"
7
+ :clearable="false"
8
+ readonly
9
+ v-model="state.value"
10
+ :interacted="interacted"
11
+ >
12
+ <template #suffix><i ui-form-select=""></i></template>
13
+ </Input>
14
+ </slot>
15
+ <template #tips>
16
+ <ul v-if="props.options?.length" ui-scroll=":y s" class="nx-sm lh-ml" style="min-width: 100%; max-height: 15em">
17
+ <template v-for="(item, idx) of props.options" :key="idx">
18
+ <li v-if="item.disabled" class="ux-hover nx-sm r-ss o-ms nowrap">
19
+ <label style="pointer-events: none" ui-form="@a type:checkbox :block">
20
+ <input type="checkbox" :name="state.name" :checked="modelValue?.some((i: any) => `${i}` === `${item.value}`)" />
21
+ <del class="ml-sm">{{ item.label || item }}</del>
22
+ </label>
23
+ </li>
24
+ <li v-else class="ux-hover nx-sm r-ss nowrap" @click.stop="select(item.value)">
25
+ <label style="pointer-events: none" ui-form="@a type:checkbox :block">
26
+ <input type="checkbox" :name="state.name" :checked="modelValue?.some((i: any) => `${i}` === `${item.value}`)" />
27
+ <span class="ml-sm">{{ item.label || item }}</span>
28
+ </label>
29
+ </li>
30
+ </template>
31
+ </ul>
32
+ <div v-else class="w-full ny-ms" ui-flex="col cm" v-html="spare"></div>
33
+ <ul class="nx-sm lh-sl" v-if="tools">
34
+ <li class="my-ss"><div class="o-mm" ui-line="@a"></div></li>
35
+ <li ui-flex="row xm">
36
+ <div class="ux-hover nx-sm ny-ss r-ss nowrap co-main" @click.stop="allselect()">
37
+ <label style="pointer-events: none" ui-form="@a type:checkbox :block">
38
+ <input type="checkbox" :name="state.name" :checked="state.all" />
39
+ <span class="ml-sm">全选({{ props.options?.length || 0 }})</span>
40
+ </label>
41
+ </div>
42
+ <div>
43
+ <button v-show="state.has" class="co-risk" ui-btn="@a none s" @click="remove">清空</button>
44
+ </div>
45
+ </li>
46
+ </ul>
47
+ </template>
48
+ </IFollowView>
49
+ </div>
50
+ </template>
51
+
52
+ <script setup lang="ts">
53
+ import { reactive, ref, computed, watch } from 'vue';
54
+ import { Input } from '.';
55
+ import { IFollowView } from '../basic';
56
+ const ifollow: any = ref(null);
57
+
58
+ const emits = defineEmits(['update:modelValue']);
59
+
60
+ /**
61
+ * 入参说明
62
+ *
63
+ * modelValue 值
64
+ * options 枚举列表
65
+ * tools 是否显示工具栏
66
+ * spare 空闲兜底内容
67
+ * search 是否显示搜索框
68
+ *
69
+ * -----------------------------------------
70
+ * theme 主题
71
+ * sz 尺寸
72
+ * co 颜色
73
+ * block 撑满
74
+ * ready 准备就绪
75
+ * type 类型
76
+ * tips 提示文案
77
+ * placeholder 内容占位
78
+ * maxlength 最大长度
79
+ * minlength 最小长度
80
+ * disabled 是否禁用
81
+ * readonly 是否只读
82
+ * clearable 是否显示清除按钮
83
+ * rules 校验规则
84
+ * verify 是否是示校验图标
85
+ * prefix 前缀内容
86
+ * suffix 后缀内容
87
+ * interacted 用户是否交互
88
+ */
89
+
90
+ // 类型
91
+ interface Props {
92
+ modelValue?: Array<string | number>;
93
+ options: Array<object>;
94
+ tools?: boolean;
95
+ spare?: string;
96
+
97
+ // Input
98
+ placeholder?: string;
99
+ rules?: Array<object>;
100
+ theme?: string;
101
+ sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
102
+ co?: string;
103
+ block?: boolean;
104
+ ready?: boolean;
105
+ type?: string;
106
+ tips?: string;
107
+ maxlength?: null | number;
108
+ minlength?: null | number;
109
+ disabled?: boolean;
110
+ readonly?: boolean;
111
+ clearable?: boolean;
112
+ verify?: boolean;
113
+ prefix?: Array<any>;
114
+ suffix?: Array<any>;
115
+ interacted?: boolean;
116
+ }
117
+ // 入参
118
+ const props: any = withDefaults(defineProps<Props>(), {
119
+ modelValue: () => [],
120
+ options: () => [],
121
+ tools: true,
122
+ spare: '当前没有可选项',
123
+
124
+ // Input
125
+ placeholder: '',
126
+ rules: () => [],
127
+ theme: '@a',
128
+ sz: '',
129
+ co: '',
130
+ block: true,
131
+ ready: false,
132
+ type: 'text',
133
+ tips: '',
134
+ maxlength: null,
135
+ minlength: null,
136
+ disabled: false,
137
+ readonly: false,
138
+ clearable: true,
139
+ verify: false,
140
+ prefix: () => [],
141
+ suffix: () => [],
142
+ interacted: false
143
+ });
144
+ // 内部数据
145
+ const state: any = reactive({
146
+ name: computed(() => {
147
+ return Array.from({ length: 8 }, () => String.fromCharCode(97 + Math.floor(Math.random() * 26))).join('');
148
+ }),
149
+ show: 0,
150
+ value: '',
151
+ all: computed(() => {
152
+ return props.options?.every((item: any) => props.modelValue?.some((i: any) => `${i}` === `${item.value}`));
153
+ }),
154
+ has: computed(() => {
155
+ return props.options?.some((item: any) => props.modelValue?.some((i: any) => `${i}` === `${item.value}`));
156
+ })
157
+ });
158
+
159
+ // 监听外部数据
160
+ watch(
161
+ [() => props.modelValue, () => props.options],
162
+ ([v = [], o = []]: any = []) => {
163
+ const selectd: any = o?.filter((item: any) => v?.some((i: any) => `${i}` === `${item.value}`))?.map((item: any) => item.label) || [];
164
+ state.value = selectd?.join(' Ι ') || '';
165
+ },
166
+ { deep: true, immediate: true }
167
+ );
168
+
169
+ // 更新
170
+ const change = (item: any) => {
171
+ emits('update:modelValue', item);
172
+ };
173
+ // 选中
174
+ const select = (item: any) => {
175
+ const s = [...props.modelValue];
176
+ // s?.indexOf(item) !== -1 ? s?.splice(s?.indexOf(item), 1) : s?.push(item);
177
+ if (s?.indexOf(item) !== -1) {
178
+ s?.splice(s?.indexOf(item), 1);
179
+ } else {
180
+ s?.push(item);
181
+ }
182
+ change(s);
183
+ };
184
+ // 全选
185
+ const allselect = () => {
186
+ const s = state.all ? [] : props.options?.map((item: any) => item.value);
187
+ change(s);
188
+ };
189
+ // 清除
190
+ const remove = () => {
191
+ change([]);
192
+ ifollow.value.cancel();
193
+ };
194
+ </script>
195
+ . .
@@ -0,0 +1,125 @@
1
+ <template>
2
+ <ul v-if="props.options?.length" class="pr my-sm-sub">
3
+ <li v-if="ready" :ui-form-tips="state.ontips">{{ state.tips }}</li>
4
+ <li
5
+ v-for="(item, idx) of props.options"
6
+ :key="idx"
7
+ :class="`${mv?.some((i: any) => `${i}` === `${item.value}`) ? 'bg-main-ss bk-main-ml' : 'bk-case'}`"
8
+ class="n-sm r-ss b-solid b-xs"
9
+ @click.stop="select(item.value)"
10
+ >
11
+ <label ui-form="@a type:checkbox :block" style="pointer-events: none">
12
+ <input :checked="mv?.some((i: any) => `${i}` === `${item.value}`)" :name="field" type="checkbox" />
13
+ <span class="ml-sm">{{ item.label || item }}</span>
14
+ </label>
15
+ </li>
16
+ </ul>
17
+ </template>
18
+
19
+ <script lang="ts" setup>
20
+ import { ref, watch, computed, onMounted } from 'vue';
21
+
22
+ const emits = defineEmits(['update:modelValue']);
23
+ const props: any = defineProps({
24
+ theme: { type: String, default: '@a' },
25
+ sz: { type: String, default: 'm' },
26
+ co: { type: String, default: '' },
27
+ block: { type: Boolean, default: true },
28
+ tips: { type: String, default: '' },
29
+ placeholder: { type: String, default: '' },
30
+ modelValue: {
31
+ type: Array as () => any[],
32
+ default: () => []
33
+ },
34
+ options: {
35
+ type: Array as () => any[],
36
+ default: () => []
37
+ },
38
+ rules: {
39
+ type: Array,
40
+ default: () => []
41
+ },
42
+ field: {
43
+ type: String,
44
+ default: () => {
45
+ const _name = (l: any) => Array.from({ length: l }, () => 'abcdefghijklmnopqrstuvwxyz'[Math.floor(Math.random() * 26)]).join('');
46
+ return _name(8);
47
+ }
48
+ }
49
+ });
50
+
51
+ const mv: any = ref(props.modelValue);
52
+
53
+ const state: any = computed(() => {
54
+ if (ready.value) {
55
+ // 提示文案
56
+ let tips = '';
57
+ // 错误类型
58
+ let type = '';
59
+ // 验证结果
60
+ let verify = '';
61
+ if (mv.value) {
62
+ // 有值
63
+ const res: any = props.rules?.some((rule: any) => {
64
+ const yes = rule.validator && !rule.validator(props.modelValue);
65
+ tips = rule.msg;
66
+ type = rule.type;
67
+ return yes;
68
+ });
69
+ verify = res ? 'no' : 'ok';
70
+ } else {
71
+ // 无值
72
+ const res: any = props.rules?.some((rule: any) => {
73
+ tips = rule.msg;
74
+ type = rule.type;
75
+ return rule.required;
76
+ });
77
+ verify = res ? 'no' : '';
78
+ }
79
+ if (verify !== 'no' && props.tips) {
80
+ tips = props.tips;
81
+ }
82
+ // 是否显示提示
83
+ const ontips = verify === 'no' && tips ? 'show' : '';
84
+ // 状态颜色
85
+ const co = verify === 'no' ? 'co:' + type : props.co ? 'co:' + props.co : '';
86
+ return { tips, ontips, verify, co };
87
+ } else {
88
+ return {};
89
+ }
90
+ });
91
+
92
+ // 选中
93
+ const select = (item: any) => {
94
+ const values = [...mv.value];
95
+ // values?.indexOf(item) !== -1 ? values?.splice(values?.indexOf(item), 1) : values?.push(item);
96
+ if (values?.indexOf(item) !== -1) {
97
+ values?.splice(values?.indexOf(item), 1);
98
+ } else {
99
+ values?.push(item);
100
+ }
101
+ mv.value = values;
102
+ };
103
+
104
+ watch(
105
+ () => props.modelValue,
106
+ () => {
107
+ mv.value = props.modelValue;
108
+ },
109
+ { deep: true, immediate: true }
110
+ );
111
+ watch(
112
+ () => mv.value,
113
+ (v: any) => {
114
+ emits('update:modelValue', v);
115
+ },
116
+ { deep: true, immediate: true }
117
+ );
118
+
119
+ const ready: any = ref(0);
120
+ onMounted(() => {
121
+ setTimeout(() => {
122
+ ready.value = 1;
123
+ }, 300);
124
+ });
125
+ </script>