@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.
Files changed (99) hide show
  1. package/package.json +3 -2
  2. package/src/apiService/mockDataService.js +116 -0
  3. package/src/apiService/simpleDataService.js +186 -80
  4. package/src/components/Button.vue +72 -22
  5. package/src/components/EbizAvatar.vue +116 -0
  6. package/src/components/EbizCheckbox.vue +94 -0
  7. package/src/components/EbizCheckboxGroup.vue +70 -0
  8. package/src/components/EbizDetailBlock.vue +82 -0
  9. package/src/components/EbizDialog.vue +244 -56
  10. package/src/components/EbizEmployeeInfo.vue +139 -0
  11. package/src/components/EbizFileUpload.vue +202 -0
  12. package/src/components/EbizPageHeader.vue +96 -0
  13. package/src/components/EbizPagination.vue +163 -0
  14. package/src/components/EbizRadio.vue +87 -0
  15. package/src/components/EbizRadioGroup.vue +84 -0
  16. package/src/components/EbizRemoteSelect.vue +118 -40
  17. package/src/components/EbizSpace.vue +101 -0
  18. package/src/components/EbizStatistic.vue +150 -0
  19. package/src/components/EbizSwiper.vue +114 -0
  20. package/src/components/EbizSwiperItem.vue +14 -0
  21. package/src/components/EbizSwitch.vue +86 -0
  22. package/src/components/EbizTabHeader.vue +145 -0
  23. package/src/components/EbizTabPanel.vue +23 -0
  24. package/src/components/EbizTable.vue +466 -0
  25. package/src/components/EbizTableColumn.vue +117 -0
  26. package/src/components/EbizTableSort.vue +181 -0
  27. package/src/components/EbizTabs.vue +133 -91
  28. package/src/components/EbizTimePicker.vue +144 -0
  29. package/src/components/EbizTitle.vue +3 -10
  30. package/src/components/EbizTree.vue +153 -0
  31. package/src/components/EbizTreeSelector.vue +423 -0
  32. package/src/components/Home.vue +8 -0
  33. package/src/components/TdesignAlert.vue +116 -0
  34. package/src/components/TdesignButton.vue +130 -0
  35. package/src/components/TdesignCalendar/index.vue +146 -0
  36. package/src/components/TdesignCard.vue +196 -0
  37. package/src/components/TdesignCol.vue +102 -0
  38. package/src/components/TdesignCollapse.vue +143 -0
  39. package/src/components/TdesignCollapsePanel.vue +80 -0
  40. package/src/components/TdesignDatePicker.vue +125 -0
  41. package/src/components/TdesignDialog.vue +226 -0
  42. package/src/components/TdesignForm.vue +134 -0
  43. package/src/components/TdesignFormItem.vue +106 -0
  44. package/src/components/TdesignGrid.vue +56 -0
  45. package/src/components/TdesignIcon.vue +68 -0
  46. package/src/components/TdesignImage.vue +163 -0
  47. package/src/components/TdesignImageViewer.vue +201 -0
  48. package/src/components/TdesignInput.vue +243 -0
  49. package/src/components/TdesignSelect.vue +445 -0
  50. package/src/components/TdesignTag.vue +118 -0
  51. package/src/components/TdesignTextarea.vue +143 -0
  52. package/src/components/TdesignTimeline.vue +58 -0
  53. package/src/components/TdesignTimelineItem.vue +72 -0
  54. package/src/components/TdesignUpload.vue +757 -0
  55. package/src/components/TdesignWatermark.vue +108 -0
  56. package/src/index.js +130 -0
  57. package/src/main.js +20 -4
  58. package/src/router/index.js +244 -5
  59. package/src/views/Button.vue +7 -3
  60. package/src/views/CheckboxDemo.vue +105 -0
  61. package/src/views/DialogDemo.vue +126 -0
  62. package/src/views/EbizAvatar.vue +224 -0
  63. package/src/views/EbizDetailBlockDemo.vue +31 -0
  64. package/src/views/EbizEmployeeInfo.vue +250 -0
  65. package/src/views/EbizRadioDemo.vue +152 -0
  66. package/src/views/EbizSpace.vue +186 -0
  67. package/src/views/EbizSwiper.vue +158 -0
  68. package/src/views/GridDemo.vue +239 -0
  69. package/src/views/Home.vue +63 -2
  70. package/src/views/PageHeaderDemo.vue +105 -0
  71. package/src/views/PaginationDemo.vue +97 -0
  72. package/src/views/RemoteSelect.vue +336 -5
  73. package/src/views/StatisticDemo.vue +191 -0
  74. package/src/views/SwitchDemo.vue +80 -0
  75. package/src/views/TableDemo.vue +335 -0
  76. package/src/views/TableSortDemo.vue +144 -0
  77. package/src/views/TableView.vue +69 -0
  78. package/src/views/TabsDemo.vue +283 -0
  79. package/src/views/TagDemo.vue +102 -0
  80. package/src/views/TdesignAlert.vue +99 -0
  81. package/src/views/TdesignButton.vue +191 -0
  82. package/src/views/TdesignCalendar.vue +95 -0
  83. package/src/views/TdesignCard.vue +297 -0
  84. package/src/views/TdesignCollapse.vue +294 -0
  85. package/src/views/TdesignDatePicker.vue +188 -0
  86. package/src/views/TdesignForm.vue +249 -0
  87. package/src/views/TdesignIcon.vue +204 -0
  88. package/src/views/TdesignImage.vue +216 -0
  89. package/src/views/TdesignImageViewer.vue +199 -0
  90. package/src/views/TdesignInput.vue +253 -0
  91. package/src/views/TdesignSelect.vue +474 -0
  92. package/src/views/TdesignSwiper.vue +158 -0
  93. package/src/views/TextareaDemo.vue +94 -0
  94. package/src/views/TimePickerDemo.vue +147 -0
  95. package/src/views/TimelineDemo.vue +161 -0
  96. package/src/views/TreeDemo.vue +255 -0
  97. package/src/views/TreeSelectorDemo.vue +246 -0
  98. package/src/views/UploadDemo.vue +122 -0
  99. package/src/views/WatermarkDemo.vue +86 -0
@@ -0,0 +1,139 @@
1
+ <template>
2
+ <div class="ebiz-employee-info" :style="customStyle">
3
+ <div class="employee-avatar">
4
+ <ebiz-avatar
5
+ :image="employeeInfo.avatar"
6
+ :content="avatarContent"
7
+ :size="avatarSize"
8
+ :shape="avatarShape"
9
+ :alt="employeeInfo.name"
10
+ @error="handleAvatarError"
11
+ />
12
+ </div>
13
+ <div class="employee-details">
14
+ <div class="employee-name">{{ employeeInfo.name }}</div>
15
+ <div class="employee-id" v-if="employeeInfo.id">ID: {{ employeeInfo.id }}</div>
16
+ <div class="employee-department" v-if="employeeInfo.department">{{ employeeInfo.department }}</div>
17
+ </div>
18
+ </div>
19
+ </template>
20
+
21
+ <script>
22
+ export default {
23
+ name: "EbizEmployeeInfo"
24
+ }
25
+ </script>
26
+
27
+ <script setup>
28
+ import { computed, defineProps, defineEmits } from 'vue';
29
+ import EbizAvatar from './EbizAvatar.vue';
30
+
31
+ const props = defineProps({
32
+ // 员工信息对象,包含头像、名称、工号、部门
33
+ info: {
34
+ type: Object,
35
+ required: true,
36
+ default: () => ({
37
+ avatar: '',
38
+ name: '',
39
+ id: '',
40
+ department: ''
41
+ })
42
+ },
43
+ // 头像尺寸
44
+ avatarSize: {
45
+ type: String,
46
+ default: 'medium',
47
+ validator: (val) => ['small', 'medium', 'large'].includes(val) || /^(\d+px|\d+em|\d+rem|\d+%)$/.test(val)
48
+ },
49
+ // 头像形状
50
+ avatarShape: {
51
+ type: String,
52
+ default: 'circle',
53
+ validator: (val) => ['circle', 'round'].includes(val)
54
+ },
55
+ // 自定义宽度
56
+ width: {
57
+ type: [String, Number],
58
+ default: ''
59
+ },
60
+ // 自定义高度
61
+ height: {
62
+ type: [String, Number],
63
+ default: ''
64
+ }
65
+ });
66
+
67
+ const emit = defineEmits(['avatar-error']);
68
+
69
+ // 从props获取员工信息,提供默认值
70
+ const employeeInfo = computed(() => {
71
+ return {
72
+ avatar: props.info.avatar || '',
73
+ name: props.info.name || '未知',
74
+ id: props.info.id || '',
75
+ department: props.info.department || ''
76
+ };
77
+ });
78
+
79
+ // 生成头像内容(当没有提供头像图片时使用员工姓名首字母)
80
+ const avatarContent = computed(() => {
81
+ if (employeeInfo.value.name) {
82
+ return employeeInfo.value.name.charAt(0);
83
+ }
84
+ return '';
85
+ });
86
+
87
+ // 处理头像加载错误
88
+ const handleAvatarError = (context) => {
89
+ emit('avatar-error', context);
90
+ };
91
+
92
+ // 计算自定义样式
93
+ const customStyle = computed(() => {
94
+ const style = {};
95
+ if (props.width) {
96
+ style.width = typeof props.width === 'number' ? `${props.width}px` : props.width;
97
+ }
98
+ if (props.height) {
99
+ style.height = typeof props.height === 'number' ? `${props.height}px` : props.height;
100
+ }
101
+ return style;
102
+ });
103
+ </script>
104
+
105
+ <style lang="less" scoped>
106
+ .ebiz-employee-info {
107
+ display: flex;
108
+ align-items: center;
109
+
110
+ .employee-avatar {
111
+ margin-right: 16px;
112
+ }
113
+
114
+ .employee-details {
115
+ flex: 1;
116
+ display: flex;
117
+ flex-direction: column;
118
+ justify-content: center;
119
+ }
120
+
121
+ .employee-name {
122
+ font-size: 16px;
123
+ font-weight: 600;
124
+ color: #333;
125
+ margin-bottom: 4px;
126
+ }
127
+
128
+ .employee-id {
129
+ font-size: 13px;
130
+ color: #666;
131
+ margin-bottom: 2px;
132
+ }
133
+
134
+ .employee-department {
135
+ font-size: 13px;
136
+ color: #666;
137
+ }
138
+ }
139
+ </style>
@@ -0,0 +1,202 @@
1
+ <template>
2
+ <div class="ebiz-file-upload">
3
+ <tiny-pop-upload
4
+ ref="uploadRef"
5
+ v-model="fileList"
6
+ :action="uploadUrl"
7
+ :headers="headers"
8
+ :multiple="multiple"
9
+ :accept="accept"
10
+ :size-limit="sizeLimit"
11
+ :disabled="disabled"
12
+ :draggable="draggable"
13
+ :theme="theme"
14
+ :tips="tips"
15
+ :show-upload-progress="showUploadProgress"
16
+ :before-upload="handleBeforeUpload"
17
+ :on-success="handleSuccess"
18
+ :on-error="handleError"
19
+ :button-text="buttonText"
20
+ :button-size="buttonSize"
21
+ :button-type="buttonType"
22
+ :button-plain="buttonPlain"
23
+ @change="handleChange"
24
+ >
25
+ <template #default v-if="customTrigger">
26
+ <slot name="trigger"></slot>
27
+ </template>
28
+ </tiny-pop-upload>
29
+ </div>
30
+ </template>
31
+
32
+ <script setup>
33
+ import { ref, computed, watch, defineProps, defineEmits } from 'vue';
34
+ import { PopUpload as TinyPopUpload } from '@opentiny/vue';
35
+
36
+ /**
37
+ * EbizFileUpload 组件 - 基于 OpenTiny PopUpload 的文件上传组件
38
+ * 支持自定义上传地址、文件类型限制、大小限制、多文件上传等
39
+ * 提供成功和失败的回调处理
40
+ */
41
+ const props = defineProps({
42
+ /**
43
+ * 上传地址
44
+ */
45
+ action: {
46
+ type: String,
47
+ default: '/api/file/upload'
48
+ },
49
+ /**
50
+ * 上传请求头信息
51
+ */
52
+ headers: {
53
+ type: Object,
54
+ default: () => ({})
55
+ },
56
+ /**
57
+ * 是否允许多文件上传
58
+ */
59
+ multiple: {
60
+ type: Boolean,
61
+ default: false
62
+ },
63
+ /**
64
+ * 接受上传的文件类型
65
+ */
66
+ accept: {
67
+ type: String,
68
+ default: '*'
69
+ },
70
+ /**
71
+ * 文件大小限制,单位 KB
72
+ */
73
+ sizeLimit: {
74
+ type: Number,
75
+ default: 5 * 1024 // 默认5MB
76
+ },
77
+ /**
78
+ * 是否禁用上传
79
+ */
80
+ disabled: {
81
+ type: Boolean,
82
+ default: false
83
+ },
84
+ /**
85
+ * 是否支持拖拽上传
86
+ */
87
+ draggable: {
88
+ type: Boolean,
89
+ default: false
90
+ },
91
+ /**
92
+ * 上传组件主题
93
+ */
94
+ theme: {
95
+ type: String,
96
+ default: 'text',
97
+ validator: (val) => ['text', 'button', 'both'].includes(val)
98
+ },
99
+ /**
100
+ * 上传按钮文本
101
+ */
102
+ buttonText: {
103
+ type: String,
104
+ default: '上传文件'
105
+ },
106
+ /**
107
+ * 上传提示文本
108
+ */
109
+ tips: {
110
+ type: String,
111
+ default: ''
112
+ },
113
+ /**
114
+ * 是否显示上传进度
115
+ */
116
+ showUploadProgress: {
117
+ type: Boolean,
118
+ default: true
119
+ },
120
+ /**
121
+ * 初始文件列表
122
+ */
123
+ initialFiles: {
124
+ type: Array,
125
+ default: () => []
126
+ },
127
+ /**
128
+ * 按钮大小
129
+ */
130
+ buttonSize: {
131
+ type: String,
132
+ default: 'medium',
133
+ validator: (val) => ['medium', 'small', 'mini'].includes(val)
134
+ },
135
+ /**
136
+ * 按钮类型
137
+ */
138
+ buttonType: {
139
+ type: String,
140
+ default: 'primary',
141
+ validator: (val) => ['default', 'primary', 'success', 'warning', 'danger', 'info', 'text'].includes(val)
142
+ },
143
+ /**
144
+ * 按钮是否为朴素按钮
145
+ */
146
+ buttonPlain: {
147
+ type: Boolean,
148
+ default: false
149
+ },
150
+ /**
151
+ * 是否使用自定义触发器
152
+ */
153
+ customTrigger: {
154
+ type: Boolean,
155
+ default: false
156
+ }
157
+ });
158
+
159
+ const emit = defineEmits(['update:files', 'success', 'error', 'change']);
160
+
161
+ // 文件列表状态
162
+ const fileList = ref(props.initialFiles || []);
163
+
164
+ // 计算上传地址
165
+ const uploadUrl = computed(() => props.action);
166
+
167
+ // 上传前处理
168
+ const handleBeforeUpload = (_file) => {
169
+ // 可以在这里添加文件校验逻辑
170
+ return true;
171
+ };
172
+
173
+ // 上传成功处理
174
+ const handleSuccess = (response, file, fileList) => {
175
+ emit('success', { file, response, fileList });
176
+ };
177
+
178
+ // 上传失败处理
179
+ const handleError = (error, file, fileList) => {
180
+ emit('error', { file, error, fileList });
181
+ };
182
+
183
+ // 文件变更处理
184
+ const handleChange = (file, fileList) => {
185
+ emit('update:files', fileList);
186
+ emit('change', { file, fileList });
187
+ };
188
+
189
+ // 监听initialFiles变化更新文件列表
190
+ watch(() => props.initialFiles, (newFiles) => {
191
+ if (newFiles && newFiles.length > 0) {
192
+ fileList.value = [...newFiles];
193
+ }
194
+ });
195
+ </script>
196
+
197
+ <style scoped>
198
+ .ebiz-file-upload {
199
+ width: 100%;
200
+ margin: 16px 0;
201
+ }
202
+ </style>
@@ -0,0 +1,96 @@
1
+ <template>
2
+ <div class="ebiz-page-header">
3
+ <div>
4
+ <div style="display: flex; align-items: center;">
5
+ <t-breadcrumb>
6
+ <t-breadcrumb-item :to="{ path: '/' }">
7
+ <template #icon><t-icon name="home" /></template>首页
8
+ </t-breadcrumb-item>
9
+ <t-breadcrumb-item v-for="(item, index) in breadcrumbList" :key="index">
10
+ <template #icon v-if="item.icon">
11
+ <t-icon :name="item.icon" />
12
+ </template>
13
+ {{ item.title }}
14
+ </t-breadcrumb-item>
15
+ </t-breadcrumb>
16
+ </div>
17
+ <slot></slot>
18
+ </div>
19
+ <div style="display: flex; align-items: center;">
20
+ <slot name="right"></slot>
21
+ <div class="help-doc" @click="goToHelp">
22
+ <t-icon name="chat-bubble-help-filled"></t-icon>
23
+ <span>帮助文档</span>
24
+ </div>
25
+ </div>
26
+
27
+ </div>
28
+ </template>
29
+
30
+ <script setup>
31
+ import { ref, onMounted, watch } from 'vue'
32
+ import { useRouter, useRoute } from 'vue-router'
33
+ import { Breadcrumb as TBreadcrumb, BreadcrumbItem as TBreadcrumbItem, Icon as TIcon } from "tdesign-vue-next"
34
+
35
+ const router = useRouter()
36
+ const route = useRoute()
37
+
38
+ const breadcrumbList = ref([])
39
+
40
+ // 计算面包屑导航列表
41
+ const generateBreadcrumb = () => {
42
+ const matched = route.matched
43
+ if (!matched.length) return
44
+
45
+ const result = []
46
+ matched.forEach(route => {
47
+ if (route.meta && route.meta.title) {
48
+ result.push({
49
+ title: route.meta.title,
50
+ icon: route.meta.icon || '',
51
+ path: route.path
52
+ })
53
+ }
54
+ })
55
+
56
+ breadcrumbList.value = result
57
+ }
58
+
59
+ // 跳转到帮助文档页面
60
+ const goToHelp = () => {
61
+ router.push(`/help?route=${route.path}`)
62
+ }
63
+
64
+ // 监听路由变化
65
+ watch(() => route.path, () => {
66
+ generateBreadcrumb()
67
+ }, { immediate: true })
68
+
69
+ onMounted(() => {
70
+ generateBreadcrumb()
71
+ })
72
+ </script>
73
+
74
+ <style scoped>
75
+ .ebiz-page-header {
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: space-between;
79
+ }
80
+
81
+ .help-doc {
82
+ display: flex;
83
+ align-items: center;
84
+ color: var(--td-brand-color);
85
+ cursor: pointer;
86
+ transition: opacity 0.2s;
87
+ }
88
+
89
+ .help-doc:hover {
90
+ opacity: 0.8;
91
+ }
92
+
93
+ .help-doc span {
94
+ margin-left: 4px;
95
+ }
96
+ </style>
@@ -0,0 +1,163 @@
1
+ <template>
2
+ <t-pagination
3
+ :current="current"
4
+ :defaultCurrent="defaultCurrent"
5
+ :defaultPageSize="defaultPageSize"
6
+ :disabled="disabled"
7
+ :foldedMaxPageBtn="foldedMaxPageBtn"
8
+ :hideOnSinglePage="hideOnSinglePage"
9
+ :maxPageBtn="maxPageBtn"
10
+ :pageEllipsisMode="pageEllipsisMode"
11
+ :pageSize="pageSize"
12
+ :pageSizeOptions="pageSizeOptions"
13
+ :selectProps="selectProps"
14
+ :showFirstAndLastPageBtn="showFirstAndLastPageBtn"
15
+ :showJumper="showJumper"
16
+ :showPageNumber="showPageNumber"
17
+ :showPageSize="showPageSize"
18
+ :showPreviousAndNextBtn="showPreviousAndNextBtn"
19
+ :size="size"
20
+ :theme="theme"
21
+ :total="total"
22
+ :totalContent="totalContent"
23
+ @change="handleChange"
24
+ >
25
+ <!-- 如果有totalContent插槽,使用插槽内容 -->
26
+ <template v-if="$slots.totalContent" #totalContent>
27
+ <slot name="totalContent"></slot>
28
+ </template>
29
+
30
+ <!-- 如果有pageNumber插槽,使用插槽内容 -->
31
+ <template v-if="$slots.pageNumber" #pageNumber>
32
+ <slot name="pageNumber"></slot>
33
+ </template>
34
+ </t-pagination>
35
+ </template>
36
+
37
+ <script>
38
+ export default {
39
+ name: "EbizPagination"
40
+ }
41
+ </script>
42
+
43
+ <script setup>
44
+ import { defineProps, defineEmits } from 'vue';
45
+ import { Pagination as TPagination } from 'tdesign-vue-next';
46
+
47
+ defineProps({
48
+ // 当前页
49
+ current: {
50
+ type: Number,
51
+ default: undefined
52
+ },
53
+ // 默认当前页
54
+ defaultCurrent: {
55
+ type: Number,
56
+ default: 1
57
+ },
58
+ // 默认每页显示条数
59
+ defaultPageSize: {
60
+ type: Number,
61
+ default: 10
62
+ },
63
+ // 是否禁用分页
64
+ disabled: {
65
+ type: Boolean,
66
+ default: false
67
+ },
68
+ // 折叠时最多显示的页码按钮数
69
+ foldedMaxPageBtn: {
70
+ type: Number,
71
+ default: 5
72
+ },
73
+ // 当只有一页时是否隐藏分页
74
+ hideOnSinglePage: {
75
+ type: Boolean,
76
+ default: false
77
+ },
78
+ // 最多显示的页码按钮数
79
+ maxPageBtn: {
80
+ type: Number,
81
+ default: 10
82
+ },
83
+ // 页码数量超出时的省略模式
84
+ pageEllipsisMode: {
85
+ type: String,
86
+ default: 'mid',
87
+ validator: (val) => ['mid', 'both-ends'].includes(val)
88
+ },
89
+ // 每页显示条数
90
+ pageSize: {
91
+ type: Number,
92
+ default: 10
93
+ },
94
+ // 分页大小控制器选项
95
+ pageSizeOptions: {
96
+ type: Array,
97
+ default: () => [5, 10, 20, 50]
98
+ },
99
+ // 透传Select组件属性
100
+ selectProps: {
101
+ type: Object,
102
+ default: () => ({})
103
+ },
104
+ // 是否显示跳转首页尾页页码控制器
105
+ showFirstAndLastPageBtn: {
106
+ type: Boolean,
107
+ default: false
108
+ },
109
+ // 是否显示跳转页码控制器
110
+ showJumper: {
111
+ type: Boolean,
112
+ default: false
113
+ },
114
+ // 是否显示页码控制器
115
+ showPageNumber: {
116
+ type: Boolean,
117
+ default: true
118
+ },
119
+ // 是否显示分页数量控制器
120
+ showPageSize: {
121
+ type: Boolean,
122
+ default: true
123
+ },
124
+ // 是否显示跳转前后页页码控制器
125
+ showPreviousAndNextBtn: {
126
+ type: Boolean,
127
+ default: true
128
+ },
129
+ // 分页组件尺寸
130
+ size: {
131
+ type: String,
132
+ default: 'medium',
133
+ validator: (val) => ['small', 'medium'].includes(val)
134
+ },
135
+ // 分页组件风格
136
+ theme: {
137
+ type: String,
138
+ default: 'default',
139
+ validator: (val) => ['default', 'simple'].includes(val)
140
+ },
141
+ // 数据总条数
142
+ total: {
143
+ type: Number,
144
+ default: 0
145
+ },
146
+ // 用于自定义总条数呈现内容
147
+ totalContent: {
148
+ type: [Boolean, Function],
149
+ default: true
150
+ }
151
+ });
152
+
153
+ const emit = defineEmits(['change']);
154
+
155
+ // 分页变化事件
156
+ const handleChange = (pageInfo) => {
157
+ emit('change', pageInfo);
158
+ };
159
+ </script>
160
+
161
+ <style lang="less" scoped>
162
+ /* 自定义样式 */
163
+ </style>
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <t-radio
3
+ :allowUncheck="allowUncheck"
4
+ :checked="modelValue"
5
+ :defaultChecked="defaultChecked"
6
+ :disabled="disabled"
7
+ :label="label"
8
+ :name="name"
9
+ :readonly="readonly"
10
+ :value="value"
11
+ @change="handleChange"
12
+ @click="handleClick"
13
+ >
14
+ <slot>{{ label }}</slot>
15
+ </t-radio>
16
+ </template>
17
+
18
+ <script>
19
+ export default {
20
+ name: "EbizRadio"
21
+ }
22
+ </script>
23
+
24
+ <script setup>
25
+ import { defineProps, defineEmits } from 'vue';
26
+ import { Radio as TRadio } from 'tdesign-vue-next';
27
+
28
+ const props = defineProps({
29
+ // 是否允许取消选中
30
+ allowUncheck: {
31
+ type: Boolean,
32
+ default: false
33
+ },
34
+ // 是否选中 (v-model)
35
+ modelValue: {
36
+ type: Boolean,
37
+ default: false
38
+ },
39
+ // 默认是否选中
40
+ defaultChecked: {
41
+ type: Boolean,
42
+ default: false
43
+ },
44
+ // 是否禁用组件
45
+ disabled: {
46
+ type: Boolean,
47
+ default: undefined
48
+ },
49
+ // 主文案
50
+ label: {
51
+ type: String,
52
+ default: ''
53
+ },
54
+ // HTML 元素原生属性
55
+ name: {
56
+ type: String,
57
+ default: ''
58
+ },
59
+ // 只读状态
60
+ readonly: {
61
+ type: Boolean,
62
+ default: false
63
+ },
64
+ // 单选按钮的值
65
+ value: {
66
+ type: [String, Number, Boolean],
67
+ default: undefined
68
+ }
69
+ });
70
+
71
+ const emit = defineEmits(['change', 'click', 'update:modelValue']);
72
+
73
+ // 选中状态变化事件
74
+ const handleChange = (checked, context) => {
75
+ emit('update:modelValue', checked);
76
+ emit('change', checked, context);
77
+ };
78
+
79
+ // 点击事件
80
+ const handleClick = (context) => {
81
+ emit('click', context);
82
+ };
83
+ </script>
84
+
85
+ <style lang="less" scoped>
86
+ /* 自定义样式 */
87
+ </style>