@yqg/permission 1.3.0-alpha.0 → 1.3.0-alpha.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@yqg/permission",
3
- "version": "1.3.0-alpha.0",
3
+ "version": "1.3.0-alpha.10",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "type": "module",
package/src/App.vue CHANGED
@@ -9,13 +9,12 @@ const color = ref<string>('#1677ff');
9
9
  const locale = ref<LocaleType>('zh-CN');
10
10
 
11
11
  const permissions = reactive([
12
- 'test222.testlyt2',
13
- 'test222.testplyt',
14
- 'test222.tstplyt3',
15
- 'test222.tstplyt4',
16
- 'test222.tstplyt5',
17
- 'test222.wjkwd13',
18
- 'test222.YEWEITEST.query01',
12
+ 'CRANE.PERMISSION.QUERY',
13
+ 'CRANE.EMPLOYEE.QUERY',
14
+ 'CRANE.EMPLOYEE.DETAIL_QUERY',
15
+ 'CRANE.EMPLOYEE.ATTRIBUTE_CREATE',
16
+ 'CRANE.EMPLOYEE.ROLE_ASSIGN',
17
+ 'CRANE.EMPLOYEE.DEPARTMENT_ROLE.ATTRIBUTE_ROLE_CREATE',
19
18
  ]);
20
19
  // const permissions = reactive(['CRANE.BUSINESS.QUERY', 'RANE.BUSINESS.CREATE', 'CRANE.BUSINESS.UPDATE', 'CRANE.BUSINESS.DELETE']);
21
20
  const changeColor = () => {
@@ -35,25 +34,15 @@ const changeLocale = () => {
35
34
  <div class="case-card">
36
35
  <div>1:默认组件</div>
37
36
  <!-- 03541 -->
38
- <!-- 02124 -->
39
- <!-- 05184 -->
40
- <yqg-permission
41
- :permissions="permissions"
42
- workNumber="05184"
43
- :color="color"
44
- :locale="locale"
45
- @onSuccess="() => {console.log('成功')}"
46
- >
37
+ <!-- 02124 -->
38
+ <!-- 05184 -->
39
+ <yqg-permission :permissions="permissions" workNumber="04697" :color="color" :locale="locale"
40
+ @onSuccess="() => {console.log('成功')}">
47
41
  </yqg-permission>
48
42
  </div>
49
43
  <data class="case-card">
50
44
  <div>2:文字组件</div>
51
- <yqg-permission
52
- :permissions="['ddd']"
53
- :color="color"
54
- workNumber="02124"
55
- type="text"
56
- >
45
+ <yqg-permission :permissions="permissions" :color="color" workNumber="04697" type="text">
57
46
  </yqg-permission>
58
47
  </data>
59
48
 
@@ -9,8 +9,8 @@
9
9
  {{t('noPermissionTips')}}
10
10
  </span>
11
11
 
12
- <Tree checkable :defaultExpandAll="true" :tree-data="permissionList" :height="200"
13
- :checkedKeys="formState.features" class="crane-permission-tree" @check="onCheck">
12
+ <Tree checkable :default-expand-all="true" :tree-data="permissionList" :height="200" :expandedKeys="expandedKeys"
13
+ :checkedKeys="formState.features" class="crane-permission-tree" @check="onCheck" @expand="expandedKeys = $event">
14
14
  <template #title="item: PermissionType">
15
15
  <div v-if="item.children && item.children.length">
16
16
  {{ item.shortName }}
@@ -69,6 +69,10 @@ import SuccessModal from './success-modal.vue';
69
69
  import ApprovalSteps from './approval-steps.vue';
70
70
  import t, {throttle, deepTree} from '../utils';
71
71
  import useCategory from '../hooks/useCategory';
72
+ import useDefaultTime from '../hooks/useDefaultTime';
73
+
74
+ const OWNER_STATUS = 'OWNER';
75
+ const MAX_COUNT = 5;
72
76
 
73
77
  const CategorySelector = defineAsyncComponent(() =>
74
78
  import('./category-selector.vue')
@@ -107,6 +111,7 @@ const categoryRef = ref();
107
111
  let stepNodes = ref([]);
108
112
  const categoryList = ref<CategoryType[]>([]);
109
113
  const validTimeOptions = ref([]);
114
+ const expandedKeys = ref<any[]>([]);
110
115
  const formState = reactive<formStateType>({
111
116
  features: [],
112
117
  roleVoList: [],
@@ -154,7 +159,6 @@ const getParams = () => {
154
159
  };
155
160
 
156
161
  });
157
-
158
162
  deepTree(permissionList.value, (item: any) => {
159
163
  if (!item.children && formState.features.includes(item.feature)) {
160
164
  roleVoList.push({
@@ -179,6 +183,7 @@ const setDefaultTime = (permission: PermissionType) => {
179
183
 
180
184
  const onChangeTime = throttle(async () => {
181
185
  const params = getParams();
186
+
182
187
  if (params.roleVoList.length === 0) {
183
188
  stepNodes.value = [];
184
189
  return;
@@ -198,44 +203,59 @@ const onCheck = (checkedIds:any, info:any) => {
198
203
  if (!item.children && formState.features.includes(item.feature)) {
199
204
  curTotal += 1;
200
205
  }
206
+ if (!item.children && !formState.features.includes(item.feature)) {
207
+ // 新选择的节点,设置默认时间
208
+ item.validTime = useDefaultTime(item, OWNER_STATUS);
209
+ }
201
210
  })
202
211
 
203
- if (curTotal === 5) {
204
- message.warning(t('maxCountTips', {count: 5}));
212
+ if (curTotal > MAX_COUNT) {
213
+ message.warning(t('maxCountTips', { count: MAX_COUNT }));
205
214
  return;
206
215
  }
207
- onChangeTime();
208
- if (!info.node.children && total > 5) {
216
+ if (!info.node.children && total > MAX_COUNT) {
209
217
  //选择的是子节点
210
218
  formState.features = formState.features.filter((item) => item !== info.node.feature);
211
- message.warning(t('maxCountTips', {count: 5}));
219
+ message.warning(t('maxCountTips', { count: MAX_COUNT }));
220
+ onChangeTime();
221
+ categoryList.value = useCategory(permissionList.value, formState.features);
212
222
  return;
213
223
  }
214
224
 
215
- if (info.node.children && total > 5) {
225
+ if (info.node.children && total > MAX_COUNT) {
216
226
  //选择的是父节点,则找出刚选的所有叶子节点, 并且删除其中多余(total-5)的节点
217
- const diff = total - 5;
227
+ const diff = total - MAX_COUNT;
218
228
  let leafNodes:string[] = [];
219
229
  deepTree([info.node], (item: any) => {
220
- if (!item.children && !formState.features.includes(item.feature)) {
230
+ if (!item.children && !item.disabled && !formState.features.includes(item.feature)) {
221
231
  leafNodes.push(item.feature);
222
232
  }
223
233
  })
224
234
  // 从后面删除多余的节点
225
235
  leafNodes = leafNodes.slice(0, leafNodes.length - diff);
226
236
  formState.features = formState.features.concat(leafNodes);
227
- message.warning(t('maxCountTips', {count: 5}));
237
+ message.warning(t('maxCountTips', { count: MAX_COUNT }));
238
+ onChangeTime();
239
+ categoryList.value = useCategory(permissionList.value, formState.features);
228
240
  return;
229
241
  };
230
242
 
231
243
  formState.features = checkedIds;
232
-
244
+ onChangeTime();
233
245
  // 收集需要展示的数据属性
234
246
  categoryList.value = useCategory(permissionList.value, formState.features);
235
-
236
247
  // 预览审批流程
237
248
  }
238
249
 
250
+ watch(() => props.permissionList, (cur) => {
251
+ expandedKeys.value = [];
252
+ deepTree(cur, (item: any) => {
253
+ if (item.children && item.children.length) {
254
+ expandedKeys.value.push(item.feature);
255
+ }
256
+ })
257
+ })
258
+
239
259
  watch(() => open.value, (cur) => {
240
260
  if (cur) {
241
261
  formRef.value?.resetFields();
@@ -19,7 +19,7 @@
19
19
  </template>
20
20
  </TreeSelect>
21
21
  <span v-if="item.attributeValueIds_view?.includes(-1)" style="color: #ff4d4f; font-size: 12px;">
22
- {{ t('categoryChangeTips') }}
22
+ {{ t('categoryChangeTips', { category: item.categoryName }) }}
23
23
  </span>
24
24
  </FormItem>
25
25
  </template>
@@ -55,7 +55,7 @@ const showForm = computed(() => {
55
55
  });
56
56
  const formRef = ref();
57
57
  const searchValue = ref('');
58
- const { categoryValuesMap } = useAttributesCache(props.categoryList);
58
+ const { categoryValuesMap } = useAttributesCache(props);
59
59
 
60
60
  // 返回promise
61
61
  const validate = () => {
@@ -62,16 +62,16 @@
62
62
  any) => {
63
63
  return item.categoryName;
64
64
  }).join('、')
65
- }}325kjfhkjdhfkdshfkjdshglkjshdfgkjkjdhfkdshfkjdshglkjshdfgkjkjdhfkdshfkjdshglkjshdfgkjkjdhfkdshfkjdshglkjshdfgkjsfd
65
+ }}
66
66
  </div>
67
67
  </Popover>
68
68
 
69
69
  <!-- 选择框 -->
70
70
  <span v-if="checkedKeys.includes(item.feature)" class="crane-weak-color crane-margin-left-12">
71
71
  {{ t('availableTime') }}:
72
- <Select v-model:value="validTime" style="width: 100px"
73
- :disabled="DISABLED_STATUS.includes(item.businessApplyType)"
74
- :options="DISABLED_STATUS.includes(item.businessApplyType) ? validTimeOptions : tempTimeOptions"
72
+ <Select v-model:value="item.validTime" style="width: 100px"
73
+ :disabled="item.businessApplyType === OWNER_STATUS"
74
+ :options="item.businessApplyType === OWNER_STATUS ? validTimeOptions : tempTimeOptions"
75
75
  @change="onChangeTimeHandler" size="small">
76
76
  </Select>
77
77
  </span>
@@ -79,7 +79,7 @@
79
79
  </div>
80
80
  </template>
81
81
  <script lang="ts" setup>
82
- import { PropType, ref, watch, defineEmits, computed } from 'vue';
82
+ import { PropType, defineEmits, computed } from 'vue';
83
83
  import { Tag, Popover, Select } from 'ant-design-vue';
84
84
  import { QuestionCircleOutlined } from '@ant-design/icons-vue';
85
85
  import departmentImg from '@/assets/department.png';
@@ -87,8 +87,6 @@ import categoryImg from '@/assets/category.png';
87
87
  import t from '../utils';
88
88
 
89
89
  const OWNER_STATUS = 'OWNER';
90
- const PENDING_STATUS = 'PENDING';
91
- const DISABLED_STATUS = [OWNER_STATUS, PENDING_STATUS];
92
90
 
93
91
  const levelMap:LevelMapType = {
94
92
  L1: {
@@ -127,7 +125,6 @@ let props = defineProps({
127
125
  });
128
126
 
129
127
  const statusMap = t('status');
130
- const validTime = ref('');
131
128
 
132
129
  const tempTimeOptions = computed(() => {
133
130
  return props.validTimeOptions.filter((item: any) => {
@@ -136,42 +133,11 @@ const tempTimeOptions = computed(() => {
136
133
  });
137
134
 
138
135
 
139
- //1登录人所在部门 = 权限适用范围,都默认90天,不需要区分等级和类型,
140
- //2登录人所在部门 ≠ 权限适用范围,根据等级来,高(L3)默认给7天,中(L2)默认给30天,低(L1)默认给60天
141
- const setDefaultTime = (item: PermissionType) => {
142
- if (OWNER_STATUS.includes(item.businessApplyType)) {
143
- return item.virtualOwnState?.timeStatus
144
- }
145
- if (PENDING_STATUS.includes(item.businessApplyType)) {
146
- return item.pendingValidTime
147
- }
148
- const validMap = {
149
- L1: 'SIXTY_DAYS',
150
- L2: 'THIRTY_DAYS',
151
- L3: 'SEVEN_DAYS',
152
- };
153
- const { relatedDepartmentIds = [], curDepartmentId = 0, securityLevel } = item;
154
- if (relatedDepartmentIds?.includes(curDepartmentId as number)) {
155
- item.validTime = 'NINETY_DAYS';
156
- } else {
157
- item.validTime = validMap[securityLevel];
158
- }
159
- return item.validTime;
160
- };
161
-
162
136
  const getCategoryValue = (category: CategoryType) => {
163
137
  return `【${category.categoryName}】:${category.attributeValues?.map((item: any) => item.attributeName)?.join('、') || t('empty')}`;
164
138
  };
165
-
166
- watch(() => props.checkedKeys, (newVal, oldVal) => {
167
- if ((oldVal && !oldVal.includes(props.item.feature)) && newVal.includes(props.item.feature)) {
168
- validTime.value = setDefaultTime(props.item);
169
- props.item.validTime = setDefaultTime(props.item);
170
- emit('updateTime', props.item);
171
- }}, { immediate: true });
172
139
 
173
- const onChangeTimeHandler = (value:any) => {
174
- props.item.validTime = value;
140
+ const onChangeTimeHandler = () => {
175
141
  emit('updateTime', props.item);
176
142
  emit('onChangeTime', props.item);
177
143
  };
@@ -2,7 +2,7 @@
2
2
  <contextHolder></contextHolder>
3
3
  </template>
4
4
  <script lang="ts" setup>
5
- import { createVNode } from 'vue';
5
+ import { createVNode } from 'vue';
6
6
  import { CheckCircleFilled } from '@ant-design/icons-vue';
7
7
  import { Modal } from 'ant-design-vue';
8
8
  import t from '../utils';
@@ -53,8 +53,8 @@
53
53
  defineExpose({countDown});
54
54
 
55
55
  </script>
56
- <style scoped>
57
- :deep(.yqg-permission-modal-wrap .yqg-permission-modal-confirm-btns) {
56
+ <style>
57
+ .yqg-permission-modal-wrap .yqg-permission-modal-confirm-btns {
58
58
  text-align: center!important;
59
59
  }
60
60
  </style>
@@ -63,7 +63,7 @@
63
63
  </div>
64
64
 
65
65
  <ApplyModal v-model="open" :permissionList="permissionList" :spining="loading" :workNumber="workNumber"
66
- :businessCode="businessCode" @onSuccess="() => emit('onSuccess')" @onSubmit="getPermissions">
66
+ @onSuccess="() => emit('onSuccess')" @onSubmit="getPermissions">
67
67
  </ApplyModal>
68
68
 
69
69
  </ConfigProvider>
@@ -144,13 +144,6 @@ import useFormat from '../hooks/useFormat';
144
144
  return props.permissions?.split(',')?.filter((item) => item.trim()) || [];
145
145
  });
146
146
 
147
- const businessCode = computed(() => {
148
- const code = allPermissions.value[0] || '';
149
- if (!code) return '';
150
-
151
- return code.split('.')[0];
152
- })
153
-
154
147
  const goViewApproval = () => {
155
148
  const url = curApproving.value?.oaFlowUrl;
156
149
  if (!url) return;
@@ -162,14 +155,13 @@ import useFormat from '../hooks/useFormat';
162
155
  const { workNumber } = props;
163
156
  const permissions = allPermissions.value;
164
157
  if (!permissions?.length || !workNumber) return;
165
-
158
+
166
159
  const params = {
167
160
  workNumber,
168
161
  features: permissions.toString(),
169
162
  };
170
163
 
171
164
  loading.value = true;
172
-
173
165
  const res = await Http.getPermissions(params);
174
166
  permissionList.value = useFormat(res.body || []);
175
167
  curStatus.value = useStatus(permissionList.value, curApproving);
@@ -177,18 +169,21 @@ import useFormat from '../hooks/useFormat';
177
169
  };
178
170
 
179
171
  const showModal = () => {
180
- getPermissions();
181
172
  open.value = !open.value;
173
+ getPermissions();
182
174
  };
183
175
 
184
176
  const { currentTop, dragElement } = useDraggable(props, showModal);
185
177
 
186
- watchEffect(getPermissions);
187
-
178
+ watchEffect(() => {
179
+ if (props.type === COM_TYPE.DEFAULT) {
180
+ getPermissions();
181
+ }
182
+ });
188
183
  watch(() => props.locale, (cur, pre) => {
189
184
  if (cur === pre) return;
190
185
  localStorage.setItem('permission_locale', props.locale);
191
- }, {immediate: true})
186
+ }, {immediate: true});
192
187
  </script>
193
188
 
194
189
  <style scoped>
@@ -2,10 +2,10 @@ import { watch, reactive } from 'vue';
2
2
  import Http from '../axios/index';
3
3
 
4
4
  const categoryValuesMap = reactive<Record<number, []>>({});
5
- export default function useAttributesCache(categoryList: CategoryType[]) {
5
+ export default function useAttributesCache(props: any) {
6
6
 
7
- watch(() => categoryList, (newVal) => {
8
- newVal.forEach(async (item) => {
7
+ watch(() => props.categoryList, (newVal) => {
8
+ newVal.forEach(async (item:CategoryType) => {
9
9
  if (!categoryValuesMap[item.id]) {
10
10
  const res = await Http.getCategoryValues(item.id);
11
11
  const { flatAttributeValue, treeAttributeValue, showWay } = res.body;
@@ -13,7 +13,7 @@ export default function useAttributesCache(categoryList: CategoryType[]) {
13
13
  }
14
14
  });
15
15
 
16
- }, { immediate: true });
16
+ }, { immediate: true, deep: true });
17
17
 
18
18
  return {
19
19
  categoryValuesMap
@@ -5,7 +5,6 @@ export default function useCategory(tree: PermissionType[], checkedIds: string[]
5
5
  const categoryList: CategoryType[] = [];
6
6
  deepTree(tree, (item) => {
7
7
  if (!item.children && checkedIds.includes(item.feature)) {
8
-
9
8
  item.categoryVOS.forEach((category: any) => {
10
9
  category.attributeValueIds_view = category?.attributeValueIds || [];
11
10
  categoryList.push(category);
@@ -0,0 +1,20 @@
1
+
2
+ //1登录人所在部门 = 权限适用范围,都默认90天,不需要区分等级和类型,
3
+ //2登录人所在部门 ≠ 权限适用范围,根据等级来,高(L3)默认给7天,中(L2)默认给30天,低(L1)默认给60天
4
+ export default function useDefaultTime (item: PermissionType, status:string):string {
5
+ if (item.businessApplyType === status) {
6
+ return item.virtualOwnState?.timeStatus
7
+ }
8
+ const validMap = {
9
+ L1: 'SIXTY_DAYS',
10
+ L2: 'THIRTY_DAYS',
11
+ L3: 'SEVEN_DAYS',
12
+ };
13
+ const { relatedDepartmentIds = [], curDepartmentId = 0, securityLevel } = item;
14
+ if (relatedDepartmentIds?.includes(curDepartmentId as number)) {
15
+ item.validTime = 'NINETY_DAYS';
16
+ } else {
17
+ item.validTime = validMap[securityLevel];
18
+ }
19
+ return item.validTime;
20
+ };
@@ -9,42 +9,48 @@ const StatusType = {
9
9
  TEMP_OWNER: 'TEMP_OWNER'
10
10
  }
11
11
  export default function useFormat(tree: PermissionListType) {
12
- function sortTree(tree: PermissionListType, sortMap: Map<string | null, number>, levelSortMap: Map<string | null, number>) {
13
- // 对当前层的节点进行排序
14
- tree.sort((a, b) => {
15
- return (sortMap.get(a.businessApplyType) ?? 0) - (sortMap.get(b.businessApplyType) ?? 0)
16
- || (levelSortMap.get(a.securityLevel) ?? 0) - (levelSortMap.get(b.securityLevel) ?? 0);
17
- });
18
-
19
- // 递归对每个节点的子节点进行排序
20
- tree.forEach(node => {
12
+ function sortTree(
13
+ tree: PermissionListType,
14
+ sortMap: Map<string | null, number>,
15
+ levelSortMap: Map<string | null, number>
16
+ ) {
17
+ return tree.map((node) => {
21
18
  node.key = node.feature;
22
- node.desc = 'ddddd'
23
- if (!node.children) {
19
+
20
+ if (!node.children || node.children.length === 0) {
24
21
  node.categoryVOS = (node.categoryVOS || []).filter((item: any) => item.configWay !== Category.AUTO);
25
22
 
26
- if ([StatusType.NO].includes(node.businessApplyType)) {
23
+ if ([StatusType.NO, StatusType.PENDING].includes(node.businessApplyType)) {
27
24
  node.disabled = true;
28
25
  }
29
26
 
30
- if ([StatusType.OWNER, StatusType.PENDING].includes(node.businessApplyType) && !node.categoryVOS.length) {
27
+ if ([StatusType.OWNER].includes(node.businessApplyType) && !node.categoryVOS.length) {
28
+ node.disabled = true;
29
+ }
30
+ } else {
31
+ // 递归对子节点进行排序
32
+ node.children = sortTree(node.children, sortMap, levelSortMap);
33
+
34
+ // 检查所有子节点是否 `disabled === true`
35
+ if (node.children.every((child) => child.disabled)) {
31
36
  node.disabled = true;
32
37
  }
33
38
  }
34
- if (node.children && node.children.length > 0) {
35
- sortTree(node.children, sortMap, levelSortMap);
36
- }
37
- });
38
39
 
39
- return tree;
40
+ return node;
41
+ }).sort((a, b) => {
42
+ return (sortMap.get(a.businessApplyType) ?? 0) - (sortMap.get(b.businessApplyType) ?? 0)
43
+ || (levelSortMap.get(a.securityLevel) ?? 0) - (levelSortMap.get(b.securityLevel) ?? 0);
44
+ });
40
45
  }
41
46
 
42
47
  // 需要排序,规则:businessApplyType 为 null 在前面, PENDING. OWNER 在中间, NO 在后面
43
48
  // 然后再根据 L1, L2, L3 排序
44
49
  const sort = [null, StatusType.TEMP_OWNER, StatusType.PENDING, StatusType.OWNER, StatusType.NO];
45
- const levelSort = [null, 'L1', 'L2', 'L3'];
50
+ const levelSort = [null, "L1", "L2", "L3"];
46
51
  const sortMap = new Map(sort.map((value, index) => [value, index]));
47
52
  const levelSortMap = new Map(levelSort.map((value, index) => [value, index]));
48
53
 
49
54
  return sortTree(tree, sortMap, levelSortMap);
50
- };
55
+ }
56
+
package/src/i18n/zh-CH.ts CHANGED
@@ -36,8 +36,8 @@ export default {
36
36
  categoryTips: '当前您所拥有的数据范围如下:',
37
37
  empty: '空',
38
38
  category: '数据权限',
39
- categotySelectTips: '上方选中的权限包含数据权限,请根据实际工作需要申请/更改数据范围',
40
- categoryChangeTips: '提醒:您选择的数据权限范围较大!请确认实际工作场景是否需要全量「部门」权限,并在申请理由中写明,避免审批不通过!',
39
+ categotySelectTips: '上方选中的权限包含数据权限,请根据实际工作需要申请/更改数据范围。',
40
+ categoryChangeTips: '提醒:您选择的数据权限范围较大!请确认实际工作场景是否需要全量「{category}」权限,并在申请理由中写明,避免审批不通过!',
41
41
  availiables: {
42
42
  SEVEN_DAYS: '7天',
43
43
  THIRTY_DAYS: '30天',
@@ -4,8 +4,8 @@ type optionsType = {
4
4
  [key: string]: any;
5
5
  };
6
6
  const t = (key: string, options?: optionsType) => {
7
- // key的格式为:'xxx.xxx.xxx'
8
- const en = localStorage.getItem('permission_locale') || 'en-US';
7
+ // key的格式为:'xxx.xxx.xxx'//国际化todo
8
+ const en = localStorage.getItem('permission_locale') || 'zh-CN';
9
9
  const keys = key.split('.');
10
10
  let result = language[en as string] || language['en-US'];
11
11
  for (let i = 0; i < keys.length; i++) {
@@ -36,7 +36,6 @@ class YqgPermission implements YqgPermissionType {
36
36
  return;
37
37
  }
38
38
  if (this.hasInit) {
39
- console.warn('yqg-permission has already been initialized');
40
39
  return;
41
40
  }
42
41
 
package/tsconfig.app.json CHANGED
@@ -25,8 +25,9 @@
25
25
  "src/**/*.ts",
26
26
  "src/**/*.d.ts",
27
27
  "src/**/*.tsx",
28
- "src/**/*.vue"
29
- ],
28
+ "src/**/*.vue",
29
+ "src/i18n/zh-CH.js"
30
+ ],
30
31
  "exclude": [
31
32
  "node_modules",
32
33
  "vite.config.ts" // 如果不需要解析 vite.config.ts