@ebiz/designer-components 0.0.18 → 0.0.19
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 +3 -2
- package/src/apiService/mockDataService.js +116 -0
- package/src/apiService/simpleDataService.js +186 -80
- package/src/components/Button.vue +72 -22
- package/src/components/EbizAvatar.vue +116 -0
- package/src/components/EbizCheckbox.vue +94 -0
- package/src/components/EbizCheckboxGroup.vue +70 -0
- package/src/components/EbizDetailBlock.vue +82 -0
- package/src/components/EbizDialog.vue +244 -56
- package/src/components/EbizEmployeeInfo.vue +139 -0
- package/src/components/EbizFileUpload.vue +202 -0
- package/src/components/EbizPageHeader.vue +96 -0
- package/src/components/EbizPagination.vue +163 -0
- package/src/components/EbizRadio.vue +87 -0
- package/src/components/EbizRadioGroup.vue +84 -0
- package/src/components/EbizRemoteSelect.vue +118 -40
- package/src/components/EbizSpace.vue +101 -0
- package/src/components/EbizStatistic.vue +150 -0
- package/src/components/EbizSwiper.vue +114 -0
- package/src/components/EbizSwiperItem.vue +14 -0
- package/src/components/EbizSwitch.vue +86 -0
- package/src/components/EbizTabHeader.vue +145 -0
- package/src/components/EbizTabPanel.vue +23 -0
- package/src/components/EbizTable.vue +466 -0
- package/src/components/EbizTableColumn.vue +117 -0
- package/src/components/EbizTableSort.vue +181 -0
- package/src/components/EbizTabs.vue +133 -91
- package/src/components/EbizTimePicker.vue +144 -0
- package/src/components/EbizTitle.vue +3 -10
- package/src/components/EbizTree.vue +153 -0
- package/src/components/EbizTreeSelector.vue +423 -0
- package/src/components/Home.vue +8 -0
- package/src/components/TdesignAlert.vue +116 -0
- package/src/components/TdesignButton.vue +130 -0
- package/src/components/TdesignCalendar/index.vue +146 -0
- package/src/components/TdesignCard.vue +196 -0
- package/src/components/TdesignCol.vue +102 -0
- package/src/components/TdesignCollapse.vue +143 -0
- package/src/components/TdesignCollapsePanel.vue +80 -0
- package/src/components/TdesignDatePicker.vue +125 -0
- package/src/components/TdesignDialog.vue +226 -0
- package/src/components/TdesignForm.vue +134 -0
- package/src/components/TdesignFormItem.vue +106 -0
- package/src/components/TdesignGrid.vue +56 -0
- package/src/components/TdesignIcon.vue +68 -0
- package/src/components/TdesignImage.vue +163 -0
- package/src/components/TdesignImageViewer.vue +201 -0
- package/src/components/TdesignInput.vue +243 -0
- package/src/components/TdesignSelect.vue +445 -0
- package/src/components/TdesignTag.vue +118 -0
- package/src/components/TdesignTextarea.vue +143 -0
- package/src/components/TdesignTimeline.vue +58 -0
- package/src/components/TdesignTimelineItem.vue +72 -0
- package/src/components/TdesignUpload.vue +757 -0
- package/src/components/TdesignWatermark.vue +108 -0
- package/src/index.js +130 -0
- package/src/main.js +20 -4
- package/src/router/index.js +244 -5
- package/src/views/Button.vue +7 -3
- package/src/views/CheckboxDemo.vue +105 -0
- package/src/views/DialogDemo.vue +126 -0
- package/src/views/EbizAvatar.vue +224 -0
- package/src/views/EbizDetailBlockDemo.vue +31 -0
- package/src/views/EbizEmployeeInfo.vue +250 -0
- package/src/views/EbizRadioDemo.vue +152 -0
- package/src/views/EbizSpace.vue +186 -0
- package/src/views/EbizSwiper.vue +158 -0
- package/src/views/GridDemo.vue +239 -0
- package/src/views/Home.vue +63 -2
- package/src/views/PageHeaderDemo.vue +105 -0
- package/src/views/PaginationDemo.vue +97 -0
- package/src/views/RemoteSelect.vue +336 -5
- package/src/views/StatisticDemo.vue +191 -0
- package/src/views/SwitchDemo.vue +80 -0
- package/src/views/TableDemo.vue +335 -0
- package/src/views/TableSortDemo.vue +144 -0
- package/src/views/TableView.vue +69 -0
- package/src/views/TabsDemo.vue +283 -0
- package/src/views/TagDemo.vue +102 -0
- package/src/views/TdesignAlert.vue +99 -0
- package/src/views/TdesignButton.vue +191 -0
- package/src/views/TdesignCalendar.vue +95 -0
- package/src/views/TdesignCard.vue +297 -0
- package/src/views/TdesignCollapse.vue +294 -0
- package/src/views/TdesignDatePicker.vue +188 -0
- package/src/views/TdesignForm.vue +249 -0
- package/src/views/TdesignIcon.vue +204 -0
- package/src/views/TdesignImage.vue +216 -0
- package/src/views/TdesignImageViewer.vue +199 -0
- package/src/views/TdesignInput.vue +253 -0
- package/src/views/TdesignSelect.vue +474 -0
- package/src/views/TdesignSwiper.vue +158 -0
- package/src/views/TextareaDemo.vue +94 -0
- package/src/views/TimePickerDemo.vue +147 -0
- package/src/views/TimelineDemo.vue +161 -0
- package/src/views/TreeDemo.vue +255 -0
- package/src/views/TreeSelectorDemo.vue +246 -0
- package/src/views/UploadDemo.vue +122 -0
- package/src/views/WatermarkDemo.vue +86 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
<template>
|
2
|
+
<t-radio-group
|
3
|
+
:allowUncheck="allowUncheck"
|
4
|
+
:disabled="disabled"
|
5
|
+
:name="name"
|
6
|
+
:options="options"
|
7
|
+
:size="size"
|
8
|
+
:value="modelValue"
|
9
|
+
:defaultValue="defaultValue"
|
10
|
+
:variant="variant"
|
11
|
+
@change="handleChange"
|
12
|
+
>
|
13
|
+
<!-- 默认插槽 -->
|
14
|
+
<slot></slot>
|
15
|
+
</t-radio-group>
|
16
|
+
</template>
|
17
|
+
|
18
|
+
<script>
|
19
|
+
export default {
|
20
|
+
name: "EbizRadioGroup"
|
21
|
+
}
|
22
|
+
</script>
|
23
|
+
|
24
|
+
<script setup>
|
25
|
+
import { defineProps, defineEmits } from 'vue';
|
26
|
+
import { RadioGroup as TRadioGroup } from 'tdesign-vue-next';
|
27
|
+
|
28
|
+
const props = defineProps({
|
29
|
+
// 是否允许取消选中
|
30
|
+
allowUncheck: {
|
31
|
+
type: Boolean,
|
32
|
+
default: false
|
33
|
+
},
|
34
|
+
// 是否禁用组件
|
35
|
+
disabled: {
|
36
|
+
type: Boolean,
|
37
|
+
default: undefined
|
38
|
+
},
|
39
|
+
// HTML 元素原生属性
|
40
|
+
name: {
|
41
|
+
type: String,
|
42
|
+
default: ''
|
43
|
+
},
|
44
|
+
// 以配置形式设置子元素
|
45
|
+
options: {
|
46
|
+
type: Array,
|
47
|
+
default: () => []
|
48
|
+
},
|
49
|
+
// 组件尺寸
|
50
|
+
size: {
|
51
|
+
type: String,
|
52
|
+
default: 'medium',
|
53
|
+
validator: (val) => ['small', 'medium', 'large'].includes(val)
|
54
|
+
},
|
55
|
+
// 选中值 (v-model)
|
56
|
+
modelValue: {
|
57
|
+
type: [String, Number, Boolean],
|
58
|
+
default: undefined
|
59
|
+
},
|
60
|
+
// 默认选中值
|
61
|
+
defaultValue: {
|
62
|
+
type: [String, Number, Boolean],
|
63
|
+
default: undefined
|
64
|
+
},
|
65
|
+
// 单选组件按钮形式
|
66
|
+
variant: {
|
67
|
+
type: String,
|
68
|
+
default: 'outline',
|
69
|
+
validator: (val) => ['outline', 'primary-filled', 'default-filled'].includes(val)
|
70
|
+
}
|
71
|
+
});
|
72
|
+
|
73
|
+
const emit = defineEmits(['change', 'update:modelValue']);
|
74
|
+
|
75
|
+
// 选中值变化事件
|
76
|
+
const handleChange = (value, context) => {
|
77
|
+
emit('update:modelValue', value);
|
78
|
+
emit('change', value, context);
|
79
|
+
};
|
80
|
+
</script>
|
81
|
+
|
82
|
+
<style lang="less" scoped>
|
83
|
+
/* 自定义样式 */
|
84
|
+
</style>
|
@@ -1,14 +1,15 @@
|
|
1
1
|
<template>
|
2
|
-
<
|
3
|
-
|
4
|
-
:disabled="disabled"
|
5
|
-
|
2
|
+
<t-select ref="selectRef" v-model="selectedValue" :options="options" :loading="loading" :filterable="true"
|
3
|
+
@search="handleRemoteSearch" :multiple="multiple" :placeholder="placeholder" :clearable="clearable"
|
4
|
+
:disabled="disabled" :size="size" :empty="emptyText" :popupProps="popupProps" @change="handleChange"
|
5
|
+
@focus="handleFocus" @blur="handleBlur">
|
6
|
+
<template #prefixIcon v-if="$slots.prefix">
|
6
7
|
<slot name="prefix"></slot>
|
7
8
|
</template>
|
8
|
-
<template #suffix>
|
9
|
+
<template #suffixIcon v-if="$slots.suffix">
|
9
10
|
<slot name="suffix"></slot>
|
10
11
|
</template>
|
11
|
-
</
|
12
|
+
</t-select>
|
12
13
|
</template>
|
13
14
|
|
14
15
|
<script>
|
@@ -19,8 +20,8 @@ export default {
|
|
19
20
|
|
20
21
|
<script setup>
|
21
22
|
import { ref, onMounted, toRefs, computed } from 'vue';
|
22
|
-
import { Select as
|
23
|
-
import dataService from
|
23
|
+
import { Select as TSelect } from 'tdesign-vue-next';
|
24
|
+
import dataService from '../apiService/simpleDataService';
|
24
25
|
|
25
26
|
const props = defineProps({
|
26
27
|
/**
|
@@ -30,6 +31,7 @@ const props = defineProps({
|
|
30
31
|
type: Object,
|
31
32
|
required: true,
|
32
33
|
default: () => ({
|
34
|
+
key: null,
|
33
35
|
apiId: null,
|
34
36
|
apiType: ''
|
35
37
|
})
|
@@ -39,7 +41,9 @@ const props = defineProps({
|
|
39
41
|
*/
|
40
42
|
queryParams: {
|
41
43
|
type: Object,
|
42
|
-
default: {
|
44
|
+
default: () => ({
|
45
|
+
name: ''
|
46
|
+
})
|
43
47
|
},
|
44
48
|
/**
|
45
49
|
* 是否多选
|
@@ -73,21 +77,54 @@ const props = defineProps({
|
|
73
77
|
* 默认值
|
74
78
|
*/
|
75
79
|
modelValue: {
|
76
|
-
type: [String, Number],
|
80
|
+
type: [String, Number, Array],
|
77
81
|
default: ''
|
78
82
|
},
|
83
|
+
/**
|
84
|
+
* 选项配置
|
85
|
+
*/
|
79
86
|
optionsConfig: {
|
80
|
-
|
81
|
-
|
87
|
+
type: Object,
|
88
|
+
default: () => ({
|
89
|
+
labelField: '',
|
90
|
+
valueField: ''
|
91
|
+
})
|
92
|
+
},
|
93
|
+
/**
|
94
|
+
* 组件尺寸
|
95
|
+
*/
|
96
|
+
size: {
|
97
|
+
type: String,
|
98
|
+
default: 'medium',
|
99
|
+
validator: (val) => ['small', 'medium', 'large'].includes(val)
|
100
|
+
},
|
101
|
+
/**
|
102
|
+
* 空数据文本
|
103
|
+
*/
|
104
|
+
emptyText: {
|
105
|
+
type: String,
|
106
|
+
default: '暂无数据'
|
107
|
+
},
|
108
|
+
/**
|
109
|
+
* 弹出层配置
|
110
|
+
*/
|
111
|
+
popupProps: {
|
112
|
+
type: Object,
|
113
|
+
default: () => ({})
|
82
114
|
}
|
83
115
|
});
|
84
116
|
|
85
117
|
const { modelValue, apiConfig, queryParams } = toRefs(props)
|
86
118
|
|
87
|
-
const emit = defineEmits(['update:modelValue', 'change']);
|
119
|
+
const emit = defineEmits(['update:modelValue', 'change', 'focus', 'blur']);
|
88
120
|
|
89
121
|
// 选中的值
|
90
|
-
const selectedValue = computed(
|
122
|
+
const selectedValue = computed({
|
123
|
+
get: () => modelValue.value,
|
124
|
+
set: (val) => {
|
125
|
+
emit('update:modelValue', val);
|
126
|
+
}
|
127
|
+
});
|
91
128
|
|
92
129
|
// 选项列表
|
93
130
|
const options = ref([]);
|
@@ -95,34 +132,69 @@ const options = ref([]);
|
|
95
132
|
// 加载状态
|
96
133
|
const loading = ref(false);
|
97
134
|
|
98
|
-
//
|
99
|
-
const
|
100
|
-
|
135
|
+
// 获取select组件实例
|
136
|
+
const selectRef = ref(null);
|
137
|
+
|
138
|
+
// 暴露focus方法
|
139
|
+
const focus = () => {
|
140
|
+
selectRef.value?.focus();
|
141
|
+
};
|
101
142
|
|
143
|
+
defineExpose({
|
144
|
+
focus,
|
145
|
+
selectRef,
|
146
|
+
options
|
147
|
+
});
|
148
|
+
|
149
|
+
// 远程搜索处理函数
|
150
|
+
const handleRemoteSearch = async (keyword) => {
|
102
151
|
loading.value = true;
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
queryParams
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
152
|
+
try {
|
153
|
+
const params = {
|
154
|
+
queryParams: {
|
155
|
+
...queryParams.value,
|
156
|
+
name: keyword
|
157
|
+
}
|
158
|
+
};
|
159
|
+
const res = await dataService.fetch(params, {
|
160
|
+
key: props.apiConfig.key,
|
161
|
+
apiId: props.apiConfig.apiId,
|
162
|
+
apiType: 'MULTIPLE_DATA_SEARCH'
|
163
|
+
});
|
164
|
+
const { labelField, valueField } = props.optionsConfig;
|
165
|
+
|
166
|
+
options.value = res.data.map(item => ({
|
167
|
+
...item,
|
168
|
+
label: labelField ? item[labelField] : (item.label || item.name),
|
169
|
+
value: valueField ? item[valueField] : (item.value || item.id)
|
170
|
+
}));
|
171
|
+
} catch (error) {
|
172
|
+
console.error('远程搜索失败:', error);
|
173
|
+
options.value = [];
|
174
|
+
} finally {
|
175
|
+
loading.value = false;
|
119
176
|
}
|
177
|
+
|
178
|
+
};
|
179
|
+
|
180
|
+
// 处理获取焦点事件
|
181
|
+
const handleFocus = (value, context) => {
|
182
|
+
emit('focus', value, context);
|
183
|
+
// 当选项为空时,初始加载数据
|
184
|
+
if (options.value.length === 0) {
|
185
|
+
handleRemoteSearch('');
|
186
|
+
}
|
187
|
+
};
|
188
|
+
|
189
|
+
// 处理失去焦点事件
|
190
|
+
const handleBlur = (value, context) => {
|
191
|
+
emit('blur', value, context);
|
120
192
|
};
|
121
193
|
|
122
194
|
// 值变化处理函数
|
123
|
-
const handleChange = (value) => {
|
195
|
+
const handleChange = (value, context) => {
|
124
196
|
emit('update:modelValue', value);
|
125
|
-
emit('change', value);
|
197
|
+
emit('change', value, context);
|
126
198
|
};
|
127
199
|
|
128
200
|
// 组件挂载时,如果有默认值则加载对应的选项
|
@@ -133,10 +205,17 @@ onMounted(async () => {
|
|
133
205
|
const params = {
|
134
206
|
queryParams: queryParams.value
|
135
207
|
};
|
136
|
-
const res = await dataService.fetch(params, {
|
208
|
+
const res = await dataService.fetch(params, {
|
209
|
+
key: props.apiConfig.key,
|
210
|
+
apiId: props.apiConfig.apiId,
|
211
|
+
apiType: 'MULTIPLE_DATA_SEARCH'
|
212
|
+
});
|
213
|
+
const { labelField, valueField } = props.optionsConfig;
|
214
|
+
|
137
215
|
options.value = res.data.map(item => ({
|
138
|
-
|
139
|
-
|
216
|
+
...item,
|
217
|
+
label: labelField ? item[labelField] : (item.label || item.name),
|
218
|
+
value: valueField ? item[valueField] : (item.value || item.id)
|
140
219
|
}));
|
141
220
|
} catch (error) {
|
142
221
|
console.error('加载默认选项失败:', error);
|
@@ -144,12 +223,11 @@ onMounted(async () => {
|
|
144
223
|
loading.value = false;
|
145
224
|
}
|
146
225
|
}
|
147
|
-
|
148
226
|
});
|
149
227
|
</script>
|
150
228
|
|
151
229
|
<style scoped>
|
152
|
-
.
|
230
|
+
.t-select {
|
153
231
|
width: 100%;
|
154
232
|
}
|
155
233
|
</style>
|
@@ -0,0 +1,101 @@
|
|
1
|
+
<script setup>
|
2
|
+
import { ref, computed } from 'vue';
|
3
|
+
import { Space } from 'tdesign-vue-next';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* EbizSpace 间距组件
|
7
|
+
* 基于 TDesign Space 组件封装
|
8
|
+
* 用于控制相邻组件之间的间距
|
9
|
+
*/
|
10
|
+
|
11
|
+
const props = defineProps({
|
12
|
+
/**
|
13
|
+
* 对齐方式
|
14
|
+
* @values start/end/center/baseline
|
15
|
+
*/
|
16
|
+
align: {
|
17
|
+
type: String,
|
18
|
+
default: '',
|
19
|
+
validator: (val) => ['', 'start', 'end', 'center', 'baseline'].includes(val)
|
20
|
+
},
|
21
|
+
/**
|
22
|
+
* 是否自动换行,仅在 horizontal 时有效
|
23
|
+
*/
|
24
|
+
breakLine: {
|
25
|
+
type: Boolean,
|
26
|
+
default: false
|
27
|
+
},
|
28
|
+
/**
|
29
|
+
* 间距方向
|
30
|
+
* @values vertical/horizontal
|
31
|
+
*/
|
32
|
+
direction: {
|
33
|
+
type: String,
|
34
|
+
default: 'horizontal',
|
35
|
+
validator: (val) => ['vertical', 'horizontal'].includes(val)
|
36
|
+
},
|
37
|
+
/**
|
38
|
+
* 分隔符
|
39
|
+
*/
|
40
|
+
separator: {
|
41
|
+
type: [String, Object, Function],
|
42
|
+
default: ''
|
43
|
+
},
|
44
|
+
/**
|
45
|
+
* 间距大小
|
46
|
+
* @values small/medium/large 或具体数值
|
47
|
+
*/
|
48
|
+
size: {
|
49
|
+
type: [String, Number, Array],
|
50
|
+
default: 'medium',
|
51
|
+
validator: (val) => {
|
52
|
+
if (typeof val === 'string') {
|
53
|
+
return ['small', 'medium', 'large'].includes(val);
|
54
|
+
}
|
55
|
+
return true;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
});
|
59
|
+
|
60
|
+
defineEmits([]);
|
61
|
+
|
62
|
+
const slots = defineSlots();
|
63
|
+
|
64
|
+
/**
|
65
|
+
* 计算尺寸大小
|
66
|
+
*/
|
67
|
+
const sizeMap = {
|
68
|
+
small: '8px',
|
69
|
+
medium: '16px',
|
70
|
+
large: '24px'
|
71
|
+
};
|
72
|
+
|
73
|
+
const computedSize = computed(() => {
|
74
|
+
if (Array.isArray(props.size)) {
|
75
|
+
return props.size.map(item => {
|
76
|
+
if (typeof item === 'string' && sizeMap[item]) {
|
77
|
+
return sizeMap[item];
|
78
|
+
}
|
79
|
+
return item;
|
80
|
+
});
|
81
|
+
}
|
82
|
+
|
83
|
+
if (typeof props.size === 'string' && sizeMap[props.size]) {
|
84
|
+
return sizeMap[props.size];
|
85
|
+
}
|
86
|
+
|
87
|
+
return props.size;
|
88
|
+
});
|
89
|
+
</script>
|
90
|
+
|
91
|
+
<template>
|
92
|
+
<Space
|
93
|
+
:align="align"
|
94
|
+
:breakLine="breakLine"
|
95
|
+
:direction="direction"
|
96
|
+
:separator="separator"
|
97
|
+
:size="computedSize"
|
98
|
+
>
|
99
|
+
<slot></slot>
|
100
|
+
</Space>
|
101
|
+
</template>
|
@@ -0,0 +1,150 @@
|
|
1
|
+
<template>
|
2
|
+
<t-statistic
|
3
|
+
ref="statisticRef"
|
4
|
+
:animation="animation"
|
5
|
+
:animation-start="animationStart"
|
6
|
+
:color="color"
|
7
|
+
:decimalPlaces="decimalPlaces"
|
8
|
+
:loading="loading"
|
9
|
+
:prefix="prefix"
|
10
|
+
:suffix="suffix"
|
11
|
+
:title="title"
|
12
|
+
:trend="trend"
|
13
|
+
:trend-placement="trendPlacement"
|
14
|
+
:unit="unit"
|
15
|
+
:value="value"
|
16
|
+
@click="handleClick"
|
17
|
+
>
|
18
|
+
<!-- 加载中状态插槽 -->
|
19
|
+
<template v-if="$slots.loading" #loading>
|
20
|
+
<slot name="loading"></slot>
|
21
|
+
</template>
|
22
|
+
|
23
|
+
<!-- 前缀插槽 -->
|
24
|
+
<template v-if="$slots.prefix" #prefix>
|
25
|
+
<slot name="prefix"></slot>
|
26
|
+
</template>
|
27
|
+
|
28
|
+
<!-- 后缀插槽 -->
|
29
|
+
<template v-if="$slots.suffix" #suffix>
|
30
|
+
<slot name="suffix"></slot>
|
31
|
+
</template>
|
32
|
+
|
33
|
+
<!-- 标题插槽 -->
|
34
|
+
<template v-if="$slots.title" #title>
|
35
|
+
<slot name="title"></slot>
|
36
|
+
</template>
|
37
|
+
|
38
|
+
<!-- 趋势插槽 -->
|
39
|
+
<template v-if="$slots.trend" #trend>
|
40
|
+
<slot name="trend"></slot>
|
41
|
+
</template>
|
42
|
+
|
43
|
+
<!-- 单位插槽 -->
|
44
|
+
<template v-if="$slots.unit" #unit>
|
45
|
+
<slot name="unit"></slot>
|
46
|
+
</template>
|
47
|
+
|
48
|
+
<!-- 默认插槽 -->
|
49
|
+
<slot></slot>
|
50
|
+
</t-statistic>
|
51
|
+
</template>
|
52
|
+
|
53
|
+
<script>
|
54
|
+
export default {
|
55
|
+
name: "EbizStatistic"
|
56
|
+
}
|
57
|
+
</script>
|
58
|
+
|
59
|
+
<script setup>
|
60
|
+
import { defineProps, defineEmits, ref, onMounted } from 'vue';
|
61
|
+
import { Statistic as TStatistic } from 'tdesign-vue-next';
|
62
|
+
|
63
|
+
const props = defineProps({
|
64
|
+
// 数值动画配置
|
65
|
+
animation: {
|
66
|
+
type: Object,
|
67
|
+
default: () => ({}),
|
68
|
+
},
|
69
|
+
// 数值动画开始时间,单位:毫秒
|
70
|
+
animationStart: {
|
71
|
+
type: Boolean,
|
72
|
+
default: false,
|
73
|
+
},
|
74
|
+
// 颜色
|
75
|
+
color: {
|
76
|
+
type: String,
|
77
|
+
default: '',
|
78
|
+
},
|
79
|
+
// 小数位数
|
80
|
+
decimalPlaces: {
|
81
|
+
type: Number,
|
82
|
+
default: 0,
|
83
|
+
},
|
84
|
+
// 加载中状态
|
85
|
+
loading: {
|
86
|
+
type: Boolean,
|
87
|
+
default: false,
|
88
|
+
},
|
89
|
+
// 前缀内容
|
90
|
+
prefix: {
|
91
|
+
type: [String, Function],
|
92
|
+
default: '',
|
93
|
+
},
|
94
|
+
// 后缀内容
|
95
|
+
suffix: {
|
96
|
+
type: [String, Function],
|
97
|
+
default: '',
|
98
|
+
},
|
99
|
+
// 数值显示的标题
|
100
|
+
title: {
|
101
|
+
type: [String, Function],
|
102
|
+
default: '',
|
103
|
+
},
|
104
|
+
// 趋势
|
105
|
+
trend: {
|
106
|
+
type: String,
|
107
|
+
default: '',
|
108
|
+
validator: (val) => ['', 'increase', 'decrease'].includes(val)
|
109
|
+
},
|
110
|
+
// 趋势展示位置
|
111
|
+
trendPlacement: {
|
112
|
+
type: String,
|
113
|
+
default: 'left',
|
114
|
+
validator: (val) => ['left', 'right'].includes(val)
|
115
|
+
},
|
116
|
+
// 单位内容
|
117
|
+
unit: {
|
118
|
+
type: [String, Function],
|
119
|
+
default: '',
|
120
|
+
},
|
121
|
+
// 数值
|
122
|
+
value: {
|
123
|
+
type: Number,
|
124
|
+
default: 0,
|
125
|
+
},
|
126
|
+
});
|
127
|
+
|
128
|
+
const emit = defineEmits(['click']);
|
129
|
+
|
130
|
+
// 引用实例,用于调用组件的start方法
|
131
|
+
const statisticRef = ref(null);
|
132
|
+
|
133
|
+
// 点击事件
|
134
|
+
const handleClick = (e) => {
|
135
|
+
emit('click', e);
|
136
|
+
};
|
137
|
+
|
138
|
+
// 暴露start方法,用于手动开始动画
|
139
|
+
defineExpose({
|
140
|
+
start: () => {
|
141
|
+
if (statisticRef.value) {
|
142
|
+
statisticRef.value.start();
|
143
|
+
}
|
144
|
+
}
|
145
|
+
});
|
146
|
+
</script>
|
147
|
+
|
148
|
+
<style lang="less" scoped>
|
149
|
+
/* 自定义样式 */
|
150
|
+
</style>
|
@@ -0,0 +1,114 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
<swiper v-model="innerCurrent" :animation="animation" :autoplay="autoplay" :direction="direction"
|
4
|
+
:duration="duration" :height="height" :interval="interval" :loop="loop" :navigation="navigationConfig"
|
5
|
+
:stop-on-hover="stopOnHover" :theme="theme" @change="handleChange">
|
6
|
+
<slot></slot>
|
7
|
+
<template v-if="$slots.navigation" #navigation>
|
8
|
+
<slot name="navigation"></slot>
|
9
|
+
</template>
|
10
|
+
</swiper>
|
11
|
+
</div>
|
12
|
+
</template>
|
13
|
+
|
14
|
+
<script setup>
|
15
|
+
import { ref, computed, watch } from 'vue';
|
16
|
+
import { Swiper } from 'tdesign-vue-next';
|
17
|
+
|
18
|
+
const props = defineProps({
|
19
|
+
// 轮播切换动画效果类型
|
20
|
+
animation: {
|
21
|
+
type: String,
|
22
|
+
default: 'slide',
|
23
|
+
validator: (val) => ['slide', 'fade'].includes(val)
|
24
|
+
},
|
25
|
+
// 是否自动播放
|
26
|
+
autoplay: {
|
27
|
+
type: Boolean,
|
28
|
+
default: true
|
29
|
+
},
|
30
|
+
// 当前轮播在哪一项(下标)
|
31
|
+
current: {
|
32
|
+
type: Number,
|
33
|
+
default: 0
|
34
|
+
},
|
35
|
+
// 默认当前轮播在哪一项(下标)
|
36
|
+
defaultCurrent: {
|
37
|
+
type: Number,
|
38
|
+
default: 0
|
39
|
+
},
|
40
|
+
// 轮播滑动方向
|
41
|
+
direction: {
|
42
|
+
type: String,
|
43
|
+
default: 'horizontal',
|
44
|
+
validator: (val) => ['horizontal', 'vertical'].includes(val)
|
45
|
+
},
|
46
|
+
// 滑动动画时长
|
47
|
+
duration: {
|
48
|
+
type: Number,
|
49
|
+
default: 300
|
50
|
+
},
|
51
|
+
// 当使用垂直方向滚动时的高度
|
52
|
+
height: {
|
53
|
+
type: Number,
|
54
|
+
default: undefined
|
55
|
+
},
|
56
|
+
// 轮播间隔时间
|
57
|
+
interval: {
|
58
|
+
type: Number,
|
59
|
+
default: 5000
|
60
|
+
},
|
61
|
+
// 是否循环播放
|
62
|
+
loop: {
|
63
|
+
type: Boolean,
|
64
|
+
default: true
|
65
|
+
},
|
66
|
+
// 导航器配置
|
67
|
+
navigation: {
|
68
|
+
type: Object,
|
69
|
+
default: () => ({})
|
70
|
+
},
|
71
|
+
// 是否悬浮时停止轮播
|
72
|
+
stopOnHover: {
|
73
|
+
type: Boolean,
|
74
|
+
default: true
|
75
|
+
},
|
76
|
+
// 深色模式和浅色模式
|
77
|
+
theme: {
|
78
|
+
type: String,
|
79
|
+
default: 'light',
|
80
|
+
validator: (val) => ['light', 'dark'].includes(val)
|
81
|
+
}
|
82
|
+
});
|
83
|
+
|
84
|
+
const emit = defineEmits(['update:current', 'change']);
|
85
|
+
|
86
|
+
// 内部current值,支持双向绑定
|
87
|
+
const innerCurrent = ref(props.current || props.defaultCurrent);
|
88
|
+
|
89
|
+
// 监听props.current的变化
|
90
|
+
watch(() => props.current, (newVal) => {
|
91
|
+
if (newVal !== undefined && newVal !== innerCurrent.value) {
|
92
|
+
innerCurrent.value = newVal;
|
93
|
+
}
|
94
|
+
});
|
95
|
+
|
96
|
+
// 计算导航器配置
|
97
|
+
const navigationConfig = computed(() => {
|
98
|
+
if (!props.navigation) return undefined;
|
99
|
+
return props.navigation;
|
100
|
+
});
|
101
|
+
|
102
|
+
// 变更事件处理
|
103
|
+
const handleChange = (index) => {
|
104
|
+
innerCurrent.value = index;
|
105
|
+
emit('update:current', index);
|
106
|
+
emit('change', index);
|
107
|
+
};
|
108
|
+
</script>
|
109
|
+
|
110
|
+
<style scoped>
|
111
|
+
.ebiz-swiper-wrapper {
|
112
|
+
width: 100%;
|
113
|
+
}
|
114
|
+
</style>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<template>
|
2
|
+
<t-swiper-item>
|
3
|
+
<slot></slot>
|
4
|
+
</t-swiper-item>
|
5
|
+
</template>
|
6
|
+
|
7
|
+
<script setup>
|
8
|
+
import { SwiperItem as TSwiperItem } from 'tdesign-vue-next';
|
9
|
+
// 没有需要单独处理的props,直接透传slot到t-swiper-item
|
10
|
+
</script>
|
11
|
+
|
12
|
+
<style scoped>
|
13
|
+
/* 自定义样式可以在这里添加 */
|
14
|
+
</style>
|