@yxhl/specter-pui-vtk 1.0.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 (49) hide show
  1. package/README.md +122 -0
  2. package/dist/specter-pui-vtk.css +1 -0
  3. package/dist/specter-pui.es.js +3289 -0
  4. package/dist/specter-pui.es.js.map +1 -0
  5. package/dist/specter-pui.umd.js +2 -0
  6. package/dist/specter-pui.umd.js.map +1 -0
  7. package/package.json +65 -0
  8. package/src/assets/css/globals.scss +250 -0
  9. package/src/assets/css/index.scss +271 -0
  10. package/src/assets/css/settings.scss +10 -0
  11. package/src/assets/css/variables.scss +0 -0
  12. package/src/assets/icon/logo.svg +9 -0
  13. package/src/assets/img/background.png +0 -0
  14. package/src/assets/img/dtx.png +0 -0
  15. package/src/commons/filters/dictionary.js +75 -0
  16. package/src/commons/filters/format.js +112 -0
  17. package/src/commons/filters/mask.js +25 -0
  18. package/src/commons/index.js +17 -0
  19. package/src/commons/request.js +89 -0
  20. package/src/commons/storage.js +41 -0
  21. package/src/commons/themes.js +153 -0
  22. package/src/commons/validation.js +72 -0
  23. package/src/components/README.md +35 -0
  24. package/src/components/assembly/VtkArea.vue +259 -0
  25. package/src/components/assembly/VtkCheckbox.vue +168 -0
  26. package/src/components/assembly/VtkCount.vue +403 -0
  27. package/src/components/assembly/VtkDatePicker.vue +326 -0
  28. package/src/components/assembly/VtkEmpty.vue +107 -0
  29. package/src/components/assembly/VtkFab.vue +78 -0
  30. package/src/components/assembly/VtkFormItem.vue +166 -0
  31. package/src/components/assembly/VtkImg.vue +372 -0
  32. package/src/components/assembly/VtkPage.vue +156 -0
  33. package/src/components/assembly/VtkPdf.vue +424 -0
  34. package/src/components/assembly/VtkProj.vue +539 -0
  35. package/src/components/assembly/VtkRadio.vue +82 -0
  36. package/src/components/assembly/VtkSearch.vue +145 -0
  37. package/src/components/assembly/VtkSelect.vue +104 -0
  38. package/src/components/assembly/VtkStepper.vue +160 -0
  39. package/src/components/message/alert.vue +31 -0
  40. package/src/components/message/confirm.vue +44 -0
  41. package/src/components/message/index.js +55 -0
  42. package/src/components/message/loading.vue +33 -0
  43. package/src/components/message/prompt.vue +57 -0
  44. package/src/components/message/toast.vue +45 -0
  45. package/src/components/message/vtkMessage.vue +27 -0
  46. package/src/composables/useMixins.js +2 -0
  47. package/src/composables/usePage.js +311 -0
  48. package/src/index.js +109 -0
  49. package/src/stores/message.js +79 -0
@@ -0,0 +1,259 @@
1
+ <template>
2
+ <div class="d-inline-block d-flex">
3
+ <VSelect
4
+ v-model="entity.area2"
5
+ @update:model-value="nextArea(entity.area2, 1)"
6
+ @click:clear="clear(1)"
7
+ :placeholder="user.areacode?.length >= 2 ? entity.name2 : '---省级---'"
8
+ :items="areaData.area2"
9
+ item-title="areaName"
10
+ item-value="areaCode"
11
+ class="d-inline-block sel_box mr-3"
12
+ hide-details
13
+ density="compact"
14
+ variant="outlined"
15
+ clearable
16
+ :disabled="user.areacode?.length >= 2"
17
+ :menu-props="{ offsetY: true }"
18
+ :style="areaStyle"></VSelect>
19
+ <VSelect
20
+ v-if="maxArea >= 4"
21
+ v-model="entity.area4"
22
+ @update:model-value="nextArea(entity.area4, 2)"
23
+ @click:clear="clear(2)"
24
+ :placeholder="user.areacode?.length >= 4 ? entity.name4 : '---市级---'"
25
+ :items="areaData.area4"
26
+ item-title="areaName"
27
+ item-value="areaCode"
28
+ class="d-inline-block sel_box"
29
+ :class="maxArea > 4 && 'mr-3'"
30
+ hide-details
31
+ density="compact"
32
+ variant="outlined"
33
+ clearable
34
+ :disabled="user.areacode?.length >= 4"
35
+ :menu-props="{ offsetY: true }"
36
+ :style="areaStyle"></VSelect>
37
+ <VSelect
38
+ v-if="maxArea >= 6"
39
+ v-model="entity.area6"
40
+ @update:model-value="nextArea(entity.area6, 3)"
41
+ @click:clear="clear(3)"
42
+ :placeholder="user.areacode?.length >= 6 ? entity.name6 : '---区/县---'"
43
+ :items="areaData.area6"
44
+ item-title="areaName"
45
+ item-value="areaCode"
46
+ class="d-inline-block sel_box"
47
+ :class="maxArea > 6 && 'mr-3'"
48
+ hide-details
49
+ density="compact"
50
+ variant="outlined"
51
+ clearable
52
+ :disabled="user.areacode?.length >= 6"
53
+ :menu-props="{ offsetY: true }"
54
+ :style="areaStyle"></VSelect>
55
+ <VSelect
56
+ v-if="maxArea >= 9"
57
+ v-model="entity.area9"
58
+ @update:model-value="nextArea(entity.area9, 4)"
59
+ @click:clear="clear(4)"
60
+ :placeholder="user.areacode?.length >= 9 ? entity.name9 : '---街/镇---'"
61
+ :items="areaData.area9"
62
+ item-title="areaName"
63
+ item-value="areaCode"
64
+ class="d-inline-block sel_box"
65
+ :class="maxArea > 9 && 'mr-3'"
66
+ hide-details
67
+ density="compact"
68
+ variant="outlined"
69
+ clearable
70
+ :disabled="user.areacode?.length >= 9"
71
+ :menu-props="{ offsetY: true }"
72
+ :style="areaStyle"></VSelect>
73
+ <VSelect
74
+ v-if="maxArea >= 12"
75
+ v-model="entity.area12"
76
+ @update:model-value="nextArea(entity.area12, 5)"
77
+ @click:clear="clear(5)"
78
+ :placeholder="user.areacode?.length >= 12 ? entity.name12 : '---村/社---'"
79
+ :items="areaData.area12"
80
+ item-title="areaName"
81
+ item-value="areaCode"
82
+ class="d-inline-block"
83
+ style="width: 188px"
84
+ hide-details
85
+ density="compact"
86
+ variant="outlined"
87
+ clearable
88
+ :disabled="user.areacode?.length >= 12"
89
+ :menu-props="{ offsetY: true }"
90
+ :style="areaStyle"></VSelect>
91
+ </div>
92
+ </template>
93
+
94
+ <script setup>
95
+ import { ref, reactive, onMounted } from 'vue';
96
+ import Request from "../../commons/request"
97
+
98
+ // 定义组件名称和选项
99
+ defineOptions({
100
+ name: "VtkArea",
101
+ inheritAttrs: false,
102
+ });
103
+
104
+ // 定义props
105
+ const props = defineProps({
106
+ maxArea: {
107
+ type: Number,
108
+ default: 12,
109
+ },
110
+ minArea: {
111
+ type: Number,
112
+ default: null,
113
+ },
114
+ areaStyle: {
115
+ type: String,
116
+ default: "",
117
+ },
118
+ });
119
+
120
+ // 定义emits
121
+ const emit = defineEmits(['update:modelValue']);
122
+
123
+ // 响应式数据
124
+ const entity = reactive({
125
+ area2: null,
126
+ area4: null,
127
+ area6: null,
128
+ area9: null,
129
+ area12: null,
130
+ name2: '',
131
+ name4: '',
132
+ name6: '',
133
+ name9: '',
134
+ name12: ''
135
+ });
136
+
137
+ const user = ref({ areacode: "" });
138
+ const areaData = reactive({
139
+ area2: [],
140
+ area4: [],
141
+ area6: [],
142
+ area9: [],
143
+ area12: []
144
+ });
145
+
146
+ // 安全获取 vtk 对象
147
+ const getVtk = () => {
148
+ // if (typeof window !== 'undefined' && window.$vtk) {
149
+ // return window.$vtk;
150
+ // }
151
+ // return null;
152
+ };
153
+
154
+ // 安全获取用户信息
155
+ const getUserInfo = () => {
156
+ try {
157
+ // const vtk = getVtk();
158
+ // if (vtk && typeof vtk.storage?.get === 'function') {
159
+ // return vtk.storage.get("user") || { areacode: "" };
160
+ // }
161
+ return { areacode: "" };
162
+ } catch (error) {
163
+ console.warn('获取用户信息失败:', error);
164
+ return { areacode: "" };
165
+ }
166
+ };
167
+
168
+ // 组件挂载时执行
169
+ onMounted(() => {
170
+ user.value = getUserInfo();
171
+ area();
172
+ });
173
+
174
+ // 所属地区
175
+ const area = () => {
176
+ // const vtk = getVtk();
177
+ // if (!vtk) {
178
+ // console.warn('Vtk 对象未初始化');
179
+ // return;
180
+ // }
181
+
182
+ try {
183
+ // vtk.message.loading.show();
184
+ Request.postForm(`/dict/area/show/${user.value.areacode}`).then((res) => {
185
+ // vtk.message.loading.hide();
186
+ if (res.meta.success) {
187
+ entity[`area${res.data.areaLeve}`] = res.data.areaCode;
188
+ entity.name2 = res.data.province;
189
+ entity.name4 = res.data.city;
190
+ entity.name6 = res.data.district;
191
+ entity.name9 = res.data?.town;
192
+ entity.name12 = res.data?.village;
193
+ nextArea(user.value.areacode);
194
+ } else {
195
+ // vtk.message.toast(res.meta.message);
196
+ }
197
+ }).catch(error => {
198
+ // vtk.message.loading.hide();
199
+ console.error('加载区域数据失败:', error);
200
+ // vtk.message.toast('加载区域数据失败');
201
+ });
202
+ } catch (error) {
203
+ console.error('初始化区域数据失败:', error);
204
+ // if (vtk.message?.loading?.hide) {
205
+ // vtk.message.loading.hide();
206
+ // }
207
+ }
208
+ };
209
+
210
+ // 下一级地区列表
211
+ const nextArea = (areaCode, index) => {
212
+ inputFn(areaCode);
213
+ // const vtk = getVtk();
214
+ // if (!vtk || !areaCode) return;
215
+
216
+ if (areaCode?.length < 12) {
217
+ Request.postForm(`/dict/area/next/${areaCode}`).then((res) => {
218
+ vtk.message.loading.hide();
219
+ if (res.meta.success) {
220
+ if (index) {
221
+ Object.keys(areaData)
222
+ .slice(index, 5)
223
+ .forEach((e) => {
224
+ areaData[e] = [];
225
+ entity[e] = null;
226
+ });
227
+ }
228
+ areaData[`area${res.data[0].areaLeve}`] = res.data;
229
+ } else {
230
+ vtk.message.toast(res.meta.message);
231
+ }
232
+ }).catch(error => {
233
+ console.error('加载下级区域数据失败:', error);
234
+ // vtk.message.toast('加载下级区域数据失败');
235
+ });
236
+ }
237
+ };
238
+
239
+ // 清除
240
+ const clear = (index) => {
241
+ let arr = Object.keys(areaData);
242
+ inputFn(entity[arr[index - 2]]);
243
+ arr.slice(index, 5).forEach((e) => {
244
+ areaData[e] = [];
245
+ entity[e] = null;
246
+ });
247
+ };
248
+
249
+ // 输入事件
250
+ const inputFn = (e) => {
251
+ e && emit("update:modelValue", e);
252
+ };
253
+ </script>
254
+
255
+ <style lang="scss" scoped>
256
+ .sel_box {
257
+ width: 164px;
258
+ }
259
+ </style>
@@ -0,0 +1,168 @@
1
+ <template>
2
+ <VInput
3
+ v-bind="inputAttrs"
4
+ :model-value="inputValue"
5
+ >
6
+ <div class="checkGroup" :class="inline ? 'd-flex flex-wrap align-top' : 'd-inline-block'">
7
+ <VCheckbox
8
+ v-for="item in items"
9
+ hide-details
10
+ :key="item.id || item.code"
11
+ :label="item.codeValue"
12
+ :value="item.code"
13
+ v-model="localValue"
14
+ v-bind="checkboxAttrs"
15
+ :class="inline ? 'mr-4' : ''"
16
+ />
17
+ </div>
18
+ </VInput>
19
+ </template>
20
+
21
+ <script setup>
22
+ import { ref, onMounted, useAttrs, computed, watch } from 'vue';
23
+ import Request from '../../commons/request';
24
+
25
+ // 定义组件名称
26
+ defineOptions({
27
+ name: "VtkCheckbox",
28
+ inheritAttrs: false,
29
+ });
30
+
31
+ // 定义 props
32
+ const props = defineProps({
33
+ /**
34
+ * 字典来源:
35
+ * - 若为静态数据,格式如:"0:否/1:是"
36
+ * - 若为字典键,格式如:"DISABLE_TYPE"
37
+ */
38
+ list: {
39
+ type: String,
40
+ required: true,
41
+ },
42
+ /**
43
+ * 是否横向排列
44
+ */
45
+ inline: {
46
+ type: Boolean,
47
+ default: false,
48
+ },
49
+ /**
50
+ * 绑定值
51
+ */
52
+ modelValue: {
53
+ type: [Array, String],
54
+ default: () => []
55
+ }
56
+ });
57
+
58
+ // 定义 emits
59
+ const emit = defineEmits(['update:modelValue']);
60
+
61
+ // 本地选中值
62
+ const localValue = ref([]);
63
+
64
+ // 防止递归更新的标志位
65
+ const isUpdatingLocal = ref(false);
66
+ const isUpdatingModel = ref(false);
67
+
68
+ // 同步外部 modelValue 到本地值
69
+ watch(() => props.modelValue, (newVal) => {
70
+ if (isUpdatingModel.value) {
71
+ isUpdatingModel.value = false;
72
+ return;
73
+ }
74
+
75
+ isUpdatingLocal.value = true;
76
+ if (Array.isArray(newVal)) {
77
+ localValue.value = [...newVal];
78
+ } else if (typeof newVal === 'string') {
79
+ localValue.value = newVal ? [newVal] : [];
80
+ } else {
81
+ localValue.value = [];
82
+ }
83
+ }, { immediate: true });
84
+
85
+ // 同步本地值到外部 modelValue
86
+ watch(localValue, (newVal) => {
87
+ if (isUpdatingLocal.value) {
88
+ isUpdatingLocal.value = false;
89
+ return;
90
+ }
91
+
92
+ isUpdatingModel.value = true;
93
+ emit('update:modelValue', newVal);
94
+ }, { deep: true });
95
+
96
+ // 获取透传属性
97
+ const attrs = useAttrs();
98
+
99
+ // 分离传递给 input 和传递给 checkbox 的属性
100
+ const inputAttrs = computed(() => {
101
+ const { list, inline, modelValue, ...rest } = attrs;
102
+ return rest;
103
+ });
104
+
105
+ const checkboxAttrs = computed(() => {
106
+ // 移除表单验证相关属性,避免重复应用
107
+ const {
108
+ list,
109
+ inline,
110
+ modelValue,
111
+ error,
112
+ 'error-messages': errorMessages,
113
+ rules,
114
+ hint,
115
+ 'persistent-hint': persistentHint,
116
+ ...rest
117
+ } = attrs;
118
+ return rest;
119
+ });
120
+
121
+ // 为 v-input 提供一个值
122
+ const inputValue = computed(() => {
123
+ return localValue.value && localValue.value.length > 0 ? localValue.value : null;
124
+ });
125
+
126
+ // 响应式数据
127
+ const items = ref([]);
128
+
129
+ // 处理静态数据(如 "0:否/1:是")
130
+ const statc = () => {
131
+ props.list.split('/').forEach(it => {
132
+ const [code, codeValue] = it.split(':');
133
+ items.value.push({ code, codeValue });
134
+ });
135
+ };
136
+
137
+ // 请求远程字典数据
138
+ const miscs = async () => {
139
+ try {
140
+ const res = await Request.getForm(`dict/misc/list/${props.list}`);
141
+ items.value = res.data || [];
142
+ } catch (error) {
143
+ console.error('[VtkCheckbox] Failed to load dictionary:', error);
144
+ items.value = [];
145
+ }
146
+ };
147
+
148
+ // 组件挂载时初始化数据
149
+ onMounted(() => {
150
+ if (props.list.includes(':')) {
151
+ statc();
152
+ } else {
153
+ miscs();
154
+ }
155
+ });
156
+ </script>
157
+
158
+ <style scoped>
159
+ :deep(.v-checkbox .v-selection-control) {
160
+ margin: 0;
161
+ padding: 0;
162
+ min-height: 32px;
163
+ }
164
+
165
+ :deep(.v-input__details) {
166
+ padding-inline: 16px;
167
+ }
168
+ </style>