@yqg/permission 1.3.0-alpha.9 → 1.3.1-1.beta.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yqg/permission",
3
- "version": "1.3.0-alpha.9",
3
+ "version": "1.3.11.beta.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "type": "module",
@@ -14,31 +14,30 @@
14
14
  "preview": "vite preview",
15
15
  "demo:build": "vue-tsc -b && STAGE=test vite build",
16
16
  "prod:build": "vue-tsc -b && STAGE=prod vite build"
17
-
18
17
  },
19
18
  "devDependencies": {
19
+ "@alicloud/cdn20180510": "3.1.2",
20
+ "@alicloud/openapi-client": "0.4.12",
20
21
  "@ant-design/icons-vue": "^7.0.1",
21
22
  "@commitlint/cli": "^19.5.0",
22
23
  "@commitlint/config-conventional": "^19.5.0",
24
+ "@originjs/vite-plugin-commonjs": "1.0.3",
23
25
  "@types/vue": "^2.0.0",
24
26
  "@typescript-eslint/parser": "^8.13.0",
25
27
  "@vitejs/plugin-vue": "^5.1.4",
28
+ "@yqg/max-utils": "^1.0.2",
29
+ "ali-oss": "6.17.1",
26
30
  "ant-design-vue": "4.x",
27
31
  "axios": "^1.7.7",
32
+ "chalk": "5.3.0",
28
33
  "eslint": "^9.14.0",
29
34
  "husky": "^9",
30
35
  "lint-staged": "^13.2.0",
36
+ "ora": "5.4.1",
31
37
  "typescript": "~5.5.4",
32
38
  "vite": "^5.4.9",
33
39
  "vite-plugin-css-injected-by-js": "^3.5.2",
34
40
  "vue": "^3.5.12",
35
- "vue-tsc": "^2.1.8",
36
- "@alicloud/cdn20180510": "3.1.2",
37
- "@alicloud/openapi-client": "0.4.12",
38
- "@originjs/vite-plugin-commonjs": "1.0.3",
39
- "@yqg/max-utils": "^1.0.2",
40
- "ali-oss": "6.17.1",
41
- "chalk": "5.3.0",
42
- "ora": "5.4.1"
41
+ "vue-tsc": "^2.1.8"
43
42
  }
44
43
  }
package/src/App.vue CHANGED
@@ -1,30 +1,26 @@
1
1
  <script setup lang="ts">
2
- import {reactive, ref} from 'vue';
2
+ import { ref } from 'vue';
3
3
  import {Button} from 'ant-design-vue';
4
4
 
5
5
  // 中英印尼菲律宾
6
6
  type LocaleType = 'zh-CN' | 'en-US' | 'id-ID' | 'fil-PH';
7
7
 
8
8
  const color = ref<string>('#1677ff');
9
- const locale = ref<LocaleType>('zh-CN');
9
+ const locale = ref<LocaleType>('id-ID');
10
10
 
11
- const permissions = reactive([
12
- 'CRANE.PERMISSION.QUERY',
13
- 'CRANE.PERMISSION.CREATE',
14
- 'CRANE.PERMISSION.UPDATE',
15
- 'CRANE.PERMISSION.DELETE',
16
- 'CRANE.PERMISSION.DETAIL_QUERY',
17
- 'CRANE.PERMISSION.ROLE_ASSIGN',
18
- 'CRANE.PERMISSION.EXPORT',
19
- ]);
20
- // const permissions = reactive(['CRANE.BUSINESS.QUERY', 'RANE.BUSINESS.CREATE', 'CRANE.BUSINESS.UPDATE', 'CRANE.BUSINESS.DELETE']);
11
+ // const permissions = ref('CALL_CENTER.DATA_BUSINESS.QUERY,CALL_CENTER.ENTER_ADMIN,CALL_CENTER.USER.QUERY,CALL_CENTER.USER.MANAGE,CALL_CENTER.BUSINESS.QUERY,CALL_CENTER.SKILL_GROUP.QUERY');
12
+ // const permissions = 'RECONCILIATION.DATA_INGESTION.RESOLVE_TASK.QUERY';
13
+ //05615
14
+ // const permissions = reactive(['CRANE.BUSINESS.QUERY', 'CRANE.BUSINESS.CREATE', 'CRANE.BUSINESS.UPDATE', 'CRANE.BUSINESS.DELETE']);
21
15
  const changeColor = () => {
22
16
  color.value = color.value === '#f00' ? '#1677ff' : '#f00';
23
17
  }
24
18
  const changeLocale = () => {
25
- locale.value = locale.value === 'zh-CN' ? 'en-US' : 'zh-CN';
19
+ locale.value = locale.value === 'id-ID' ? 'en-US' : 'id-ID';
26
20
  }
27
21
 
22
+ const permissions = ref('TECH.SCHEDULER.JOB.VISIBLE,TECH.SCHEDULER.JOB.QUERY,TECH.SCHEDULER.JOB.MODIFY');
23
+
28
24
  </script>
29
25
 
30
26
  <template>
@@ -35,25 +31,15 @@ const changeLocale = () => {
35
31
  <div class="case-card">
36
32
  <div>1:默认组件</div>
37
33
  <!-- 03541 -->
38
- <!-- 02124 -->
39
- <!-- 05184 -->
40
- <yqg-permission
41
- :permissions="permissions"
42
- workNumber="05621"
43
- :color="color"
44
- :locale="locale"
45
- @onSuccess="() => {console.log('成功')}"
46
- >
34
+ <!-- 02124 -->
35
+ <!-- 05184 -->
36
+ <yqg-permission :omitCategoryIds="[]" :permissions="permissions" workNumber="03541" :color="color" :locale="locale"
37
+ @onSuccess="() => {console.log('成功')}">
47
38
  </yqg-permission>
48
39
  </div>
49
40
  <data class="case-card">
50
41
  <div>2:文字组件</div>
51
- <yqg-permission
52
- :permissions="['ddd']"
53
- :color="color"
54
- workNumber="02124"
55
- type="text"
56
- >
42
+ <yqg-permission :permissions="permissions" :color="color" workNumber="04697" type="text">
57
43
  </yqg-permission>
58
44
  </data>
59
45
 
@@ -9,7 +9,7 @@ type apiType = {
9
9
  export default {
10
10
  getPermissions: (params: any) => axios.get(`${urlPrefix}/permission/apply`, {params}),
11
11
 
12
- getFlowPreview: (params: any)=> axios.post(`${urlPrefix}/permission/apply/oa/flow/submit/preview`, params),
12
+ getFlowPreview: (params: any) => axios.post(`${urlPrefix}/permission/apply/oa/flow/submit/preview`, params),
13
13
 
14
14
  submitApply: (params: any) => axios.post(`${urlPrefix}/permission/apply/oa/flow/submit`, params),
15
15
 
@@ -1,59 +1,79 @@
1
1
  <template>
2
- <Modal v-model:open="open" :title="t('permissionApply')" width="1100px" @ok="handleOk" :okText="t('submit')"
3
- :maskClosable="false" :ok-button-props="{ loading: loading }" :cancelText="t('cancel')">
4
- <Form ref="formRef" :model="formState" :labelCol="{ span: 4 }" :wrapperCol="{ span: 19 }">
5
- <FormItem :label="t('applyPermission')" name="features"
6
- :rules="[{ required: true, message: t('selectPlaceholder')}]">
7
- <Spin :spinning="spining">
8
- <span v-if="!permissionList.length">
9
- {{t('noPermissionTips')}}
2
+ <Modal v-model:open="open" width="1100px" :maskClosable="false" :zIndex="zIndex">
3
+ <template #footer>
4
+ <Button @click="open = false" v-show="!isAllChecked && permissionList.length">{{ t('cancel') }}</Button>
5
+ <Button type="primary" @click="handleOk" :loading="loading">{{ t('submit') }}</Button>
6
+ </template>
7
+ <template #title>
8
+ <span>{{ t('permissionApply') }}</span>
9
+ <span v-show="isAllChecked && permissionList.length" class="crane-permission-title-tips">{{
10
+ t('isAllOwnTips') }}</span>
11
+ </template>
12
+ <ConfigProvider :getPopupContainer="getPopupContainer" prefixCls="yqg-permission" :theme="{
13
+ token: {
14
+ colorPrimary: color,
15
+ }
16
+ }">
17
+ <Form ref="formRef" :model="formState" :labelCol="{ span: 4 }" :wrapperCol="{ span: 19 }">
18
+ <FormItem :label="t('applyPermission')" name="features"
19
+ :rules="[{ required: true, message: t('selectPlaceholder') }]">
20
+ <Spin :spinning="spining">
21
+ <span v-if="!permissionList.length">
22
+ {{ t('noPermissionTips') }}
23
+ </span>
24
+ <div v-else :class="{ 'yqg-permission-tree-list-wraper': showScrollBar }">
25
+ <Tree checkable :default-expand-all="true" :tree-data="permissionList" :height="200"
26
+ :expandedKeys="expandedKeys" :checkedKeys="formState.features" @check="onCheck"
27
+ @expand="expandedKeys = $event">
28
+ <template #title="item: PermissionType">
29
+ <div v-if="item.children && item.children.length">
30
+ {{ item.shortName }}
31
+ </div>
32
+ <PermissionItem v-else :checkedKeys="formState.features" :item="item"
33
+ @onChangeTime="onChangeTime" @updateTime="setDefaultTime"
34
+ :validTimeOptions="validTimeOptions" />
35
+ </template>
36
+ </Tree>
37
+ </div>
38
+ <CategorySelector v-if="categoryList.length" :categoryList="categoryList" ref="categoryRef" />
39
+ </Spin>
40
+ </FormItem>
41
+ <FormItem name="applyReason" :label="t('applyReason')" :rules="[{
42
+ required: true, message: t('reasonPlaceholder'), trigger: ['change']
43
+ }, {
44
+ max: 300, message: t('maxLengthTips', { length: 300 }), trigger: ['change', 'blur']
45
+ }]">
46
+ <Textarea v-model:value.trim="formState.applyReason" :placeholder="t('applyReasonPlaceholder')"
47
+ :auto-size="{ minRows: 4, maxRows: 4 }" :disabled="isAllChecked || !permissionList.length">
48
+ </Textarea>
49
+ <span class="reason-tips" style="font-size: 12px">
50
+ {{ t('applyReasonTips') }}
10
51
  </span>
52
+ </FormItem>
53
+
54
+ <FormItem :label="t('approvalProcess')">
55
+ <ApprovalSteps :stepNodes="stepNodes" />
56
+ </FormItem>
57
+
58
+ </Form>
11
59
 
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
- <template #title="item: PermissionType">
15
- <div v-if="item.children && item.children.length">
16
- {{ item.shortName }}
17
- </div>
18
- <PermissionItem v-else :checkedKeys="formState.features" :item="item"
19
- @onChangeTime="onChangeTime" @updateTime="setDefaultTime"
20
- :validTimeOptions="validTimeOptions" />
21
- </template>
22
- </Tree>
23
- <CategorySelector v-if="categoryList.length" :categoryList="categoryList" ref="categoryRef" />
24
- </Spin>
25
- </FormItem>
26
- <FormItem name="applyReason" :label="t('applyReason')" :rules="[{
27
- required: true, message: t('reasonPlaceholder'), trigger: ['change']
28
- }, {
29
- max: 300, message: t('maxLengthTips', {length: 300}), trigger: ['change', 'blur']
30
- }]">
31
- <Textarea v-model:value.trim="formState.applyReason" :placeholder="t('applyReasonPlaceholder')"
32
- :auto-size="{ minRows: 4, maxRows: 4 }">
33
- </Textarea>
34
- <span class="reason-tips" style="font-size: 12px">
35
- {{t('applyReasonTips')}}
36
- </span>
37
- </FormItem>
38
-
39
- <FormItem :label="t('approvalProcess')">
40
- <ApprovalSteps :stepNodes="stepNodes" />
41
- </FormItem>
42
- </Form>
43
-
44
- <SuccessModal ref="successModal" />
60
+ </ConfigProvider>
45
61
 
46
62
  </Modal>
63
+
64
+ <SuccessModal ref="successModal" />
65
+
47
66
  </template>
48
67
  <script lang="ts" setup>
49
- import {
50
- reactive,
51
- defineAsyncComponent,
52
- toRef,
53
- ref,
68
+ import {
69
+ reactive,
70
+ defineAsyncComponent,
71
+ toRef,
72
+ ref,
54
73
  watch,
55
74
  PropType,
56
- computed
75
+ computed,
76
+ nextTick
57
77
  } from 'vue';
58
78
  import Http from '../axios/index';
59
79
  import {
@@ -63,11 +83,13 @@ import {
63
83
  Textarea,
64
84
  message,
65
85
  Tree,
66
- Spin
86
+ Spin,
87
+ Button,
88
+ ConfigProvider,
67
89
  } from 'ant-design-vue';
68
90
  import SuccessModal from './success-modal.vue';
69
91
  import ApprovalSteps from './approval-steps.vue';
70
- import t, {throttle, deepTree} from '../utils';
92
+ import t, { throttle, deepTree } from '../utils';
71
93
  import useCategory from '../hooks/useCategory';
72
94
  import useDefaultTime from '../hooks/useDefaultTime';
73
95
 
@@ -93,9 +115,25 @@ const props = defineProps({
93
115
  spining: {
94
116
  type: Boolean,
95
117
  default: false
118
+ },
119
+ defaultCheckedIds: {
120
+ type: Array as PropType<string[]>,
121
+ default: () => []
122
+ },
123
+ isAllChecked: {
124
+ type: Boolean,
125
+ default: false
126
+ },
127
+ zIndex: {
128
+ type: Number,
129
+ default: 1000
130
+ },
131
+ color: {
132
+ type: String,
133
+ default: '#1677ff'
96
134
  }
97
-
98
- });
135
+
136
+ });
99
137
  const emit = defineEmits(['onSubmit', 'onSuccess']);
100
138
 
101
139
  const open = defineModel({
@@ -109,13 +147,14 @@ const successModal = ref<InstanceType<typeof SuccessModal>>();
109
147
  const formRef = ref();
110
148
  const categoryRef = ref();
111
149
  let stepNodes = ref([]);
150
+ const showScrollBar = ref(false);
112
151
  const categoryList = ref<CategoryType[]>([]);
113
152
  const validTimeOptions = ref([]);
114
153
  const expandedKeys = ref<any[]>([]);
115
154
  const formState = reactive<formStateType>({
116
155
  features: [],
117
156
  roleVoList: [],
118
- applyReason: '',
157
+ applyReason: t('applyReasonTips'),
119
158
  dataRule: {
120
159
  ruleItems: [],
121
160
  },
@@ -128,39 +167,48 @@ const getValidTimeOptions = async () => {
128
167
  };
129
168
 
130
169
  getValidTimeOptions();
131
- const handleOk = async() => {
132
- await Promise.all([formRef.value.validate(), categoryRef.value?.validate()])
133
- loading.value = true;
134
- const params = getParams();
135
- let res = await Http.submitApply(params);
136
- const url = res?.body?.oaFlowUrl;
137
- open.value = false;
138
- loading.value = false;
139
- emit('onSubmit');
140
- successModal.value?.countDown(url, () => emit('onSuccess'));
141
- };
170
+ const handleOk = async () => {
171
+ if (props.isAllChecked || !permissionList.value.length) {
172
+ open.value = false;
173
+ return;
174
+ }
175
+ if (loading.value) return;
176
+ try {
177
+ await Promise.all([formRef.value.validate(), categoryRef.value?.validate()])
178
+ loading.value = true;
179
+ const params = getParams();
180
+ let res = await Http.submitApply(params);
181
+ const url = res?.body?.oaFlowUrl;
182
+ open.value = false;
183
+ loading.value = false;
184
+ emit('onSubmit');
185
+ successModal.value?.countDown(url, () => emit('onSuccess'));
186
+ } catch (e) {
187
+ loading.value = false;
188
+ }
189
+ };
142
190
 
143
191
 
144
192
  const getParams = () => {
145
193
  formState.submitWorkNumber = submitWorkNumber.value;
146
- const roleVoList:{
194
+ const roleVoList: {
147
195
  roleId: number;
148
196
  validTime: string;
149
197
  }[] = [];
150
198
 
151
- const ruleItems: { attributeCategoryId: number, attributeValueIds: number[]}[] = [];
199
+ const ruleItems: { attributeCategoryId: number, attributeValueIds: number[] }[] = [];
152
200
  categoryList.value.forEach((category: CategoryType) => {
153
201
  // 添加有数据范围值的属性
154
202
  if (category.attributeValueIds_view.length) {
155
203
  ruleItems.push({
156
204
  attributeCategoryId: category.id,
157
- attributeValueIds: category.attributeValueIds_view
205
+ attributeValueIds: category.attributeValueIds_view,
158
206
  })
159
207
  };
160
-
208
+
161
209
  });
162
210
  deepTree(permissionList.value, (item: any) => {
163
- if (!item.children && formState.features.includes(item.feature)) {
211
+ if (!item.children && formState.features.includes(item.feature) && !item.disabled) {
164
212
  roleVoList.push({
165
213
  roleId: item.roleId,
166
214
  validTime: item.validTime
@@ -187,20 +235,22 @@ const onChangeTime = throttle(async () => {
187
235
  if (params.roleVoList.length === 0) {
188
236
  stepNodes.value = [];
189
237
  return;
190
- }
238
+ };
239
+
191
240
  let res = await Http.getFlowPreview(params);
192
241
  stepNodes.value = res?.body?.nodes || [];
193
- }, 0)
194
- const onCheck = (checkedIds:any, info:any) => {
242
+ }, 1)
243
+ const onCheck = (checkedIds: any, info: any) => {
195
244
  // 如果选择的是子节点,判断是否超过5个,超过的话,删除当前选的节点,并给予提示
196
245
  // 如果选择的是父节点,判断是否超过5个,超过的话,从当前选择的父节点的叶子节点中删除多出的个数,并给予提示
197
246
  let total = 0;
198
247
  let curTotal = 0;
248
+
199
249
  deepTree(permissionList.value, (item: any) => {
200
- if (!item.children && checkedIds.includes(item.feature)) {
250
+ if (!item.children && checkedIds.includes(item.feature) && !item.disabled) {
201
251
  total += 1;
202
252
  }
203
- if (!item.children && formState.features.includes(item.feature)) {
253
+ if (!item.children && formState.features.includes(item.feature) && !item.disabled) {
204
254
  curTotal += 1;
205
255
  }
206
256
  if (!item.children && !formState.features.includes(item.feature)) {
@@ -225,7 +275,7 @@ const onCheck = (checkedIds:any, info:any) => {
225
275
  if (info.node.children && total > MAX_COUNT) {
226
276
  //选择的是父节点,则找出刚选的所有叶子节点, 并且删除其中多余(total-5)的节点
227
277
  const diff = total - MAX_COUNT;
228
- let leafNodes:string[] = [];
278
+ let leafNodes: string[] = [];
229
279
  deepTree([info.node], (item: any) => {
230
280
  if (!item.children && !item.disabled && !formState.features.includes(item.feature)) {
231
281
  leafNodes.push(item.feature);
@@ -247,15 +297,33 @@ const onCheck = (checkedIds:any, info:any) => {
247
297
  // 预览审批流程
248
298
  }
249
299
 
300
+ const initScrollBar = () => {
301
+ const treeHeight = document.querySelector('.yqg-permission-tree-list-holder')?.children?.[0]?.clientHeight || 0;
302
+ if (treeHeight > 200) {
303
+ // 设置树的高度
304
+ showScrollBar.value = true;
305
+ } else {
306
+ showScrollBar.value = false;
307
+ }
308
+ }
309
+
250
310
  watch(() => props.permissionList, (cur) => {
251
311
  expandedKeys.value = [];
252
312
  deepTree(cur, (item: any) => {
253
313
  if (item.children && item.children.length) {
254
314
  expandedKeys.value.push(item.feature);
255
315
  }
316
+ });
317
+
318
+ nextTick(() => {
319
+ initScrollBar();
256
320
  })
257
321
  })
258
322
 
323
+ watch(() => props.defaultCheckedIds, (cur) => {
324
+ formState.features = cur.concat(formState.features);
325
+ }, { immediate: true })
326
+
259
327
  watch(() => open.value, (cur) => {
260
328
  if (cur) {
261
329
  formRef.value?.resetFields();
@@ -263,12 +331,26 @@ watch(() => open.value, (cur) => {
263
331
  stepNodes.value = [];
264
332
  }
265
333
  })
334
+
335
+ const getPopupContainer = ():HTMLElement => {
336
+ const modalRoot = document.querySelector('.yqg-permission-modal-content');
337
+
338
+ return (modalRoot || document.body) as HTMLElement;
339
+ }
266
340
  </script>
267
341
 
268
342
  <style scoped>
343
+ .crane-permission-title-tips {
344
+ color: #FF4D4F;
345
+ font-size: 14px;
346
+ margin-left: 8px;
347
+ font-weight: 400;
348
+ }
349
+
269
350
  :deep(.yqg-permission-tree-list) {
270
351
  margin-top: 4px;
271
352
  }
353
+
272
354
  :deep(.yqg-permission-tree-node-selected) {
273
355
  background: none !important;
274
356
  }
@@ -284,8 +366,9 @@ watch(() => open.value, (cur) => {
284
366
  :deep(.yqg-permission-tree-checkbox+span:hover) {
285
367
  background: none !important;
286
368
  }
369
+
287
370
  :deep(.yqg-permission-tree-treenode) {
288
- width: 100%!important;
371
+ width: 100% !important;
289
372
  }
290
373
 
291
374
  :deep(.yqg-permission-tree-node-content-wrapper-normal) {
@@ -296,4 +379,8 @@ watch(() => open.value, (cur) => {
296
379
  width: 100% !important;
297
380
  }
298
381
 
382
+ .yqg-permission-tree-list-wraper :deep(.yqg-permission-tree-list-scrollbar) {
383
+ display: block !important;
384
+ }
385
+
299
386
  </style>
@@ -1,51 +1,48 @@
1
1
  <template>
2
- <div v-if="stepNodes?.length > 1" class="crane-step-wraper">
3
- <div v-for="(item, index) in stepNodes" :key="item.auditorName" class="crane-step-node">
4
- <span style="white-space: nowrap;">
5
- {{ item.auditorName }}
6
- <Popover v-if="item.employeeNameList?.length">
7
- <template #content>
8
- <div style="max-width: 400px;">
9
- {{ item.employeeNameList.join('、')}}
10
- </div>
11
- </template>
12
- <ExclamationCircleOutlined style="margin: 0 2px; color: #1677ff;"/>
13
- </Popover>
14
- {{ getSubTip(index) }}
15
- </span>
2
+ <div v-if="stepNodes?.length > 1" class="crane-step-wraper">
3
+ <div v-for="(item, index) in stepNodes" :key="item.auditorName" class="crane-step-node">
4
+ <span style="white-space: nowrap;">
5
+ {{ item.auditorName }}
6
+ <Popover v-if="item.employeeNameList?.length">
7
+ <template #content>
8
+ <div style="max-width: 400px;">
9
+ {{ item.employeeNameList.join('、') }}
10
+ </div>
11
+ </template>
12
+ <ExclamationCircleOutlined style="margin: 0 2px; color: #1677ff;" />
13
+ </Popover>
14
+ {{ getSubTip(index) }}
15
+ </span>
16
+
17
+ <img v-if="index !== stepNodes.length - 1" :src="arrowImg" class="crane-step-icon">
16
18
 
17
- <img
18
- v-if="index !== stepNodes.length - 1"
19
- :src="arrowImg"
20
- class="crane-step-icon">
21
-
22
- </div>
23
19
  </div>
24
- <span v-else-if="stepNodes?.length === 1">
25
- {{t('noNeed')}}
26
- </span>
27
- <span v-else>-</span>
20
+ </div>
21
+ <span v-else-if="stepNodes?.length === 1">
22
+ {{ t('noNeed') }}
23
+ </span>
24
+ <span v-else>-</span>
28
25
  </template>
29
26
  <script lang="ts" setup>
30
- import { PropType, toRef } from 'vue';
31
- import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
32
- import arrowImg from '@/assets/arrow.png';
33
- import { Popover } from 'ant-design-vue';
34
- import t from '../utils';
27
+ import { PropType, toRef } from 'vue';
28
+ import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
29
+ import arrowImg from '@/assets/arrow.png';
30
+ import { Popover } from 'ant-design-vue';
31
+ import t from '../utils';
35
32
 
36
- const props = defineProps({
37
- stepNodes: {
38
- type: Array as PropType<any[]>,
39
- required: true,
40
- default: () => []
41
- },
42
- });
33
+ const props = defineProps({
34
+ stepNodes: {
35
+ type: Array as PropType<any[]>,
36
+ required: true,
37
+ default: () => []
38
+ },
39
+ });
43
40
 
44
- const stepNodes = toRef(props, 'stepNodes');
41
+ const stepNodes = toRef(props, 'stepNodes');
45
42
 
46
- const getSubTip = (index: number) => {
47
- return index === stepNodes.value.length - 1 ? `[${t('end')}]` : index === 0 ? `[${t('start')}]` : '';
48
- }
43
+ const getSubTip = (index: number) => {
44
+ return index === stepNodes.value.length - 1 ? `[${t('end')}]` : index === 0 ? `[${t('start')}]` : '';
45
+ }
49
46
 
50
47
  </script>
51
48
  <style scoped>
@@ -57,10 +54,12 @@
57
54
  line-height: 32px;
58
55
  padding-bottom: 8px;
59
56
  }
57
+
60
58
  .crane-step-node {
61
59
  display: flex;
62
60
  align-items: center;
63
61
  }
62
+
64
63
  .crane-step-icon {
65
64
  margin: 0 8px;
66
65
  height: auto;