@ebiz/designer-components 0.0.25 → 0.0.27
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/dist/designer-components.css +1 -1
- package/dist/index.mjs +41661 -37304
- package/package.json +1 -1
- package/src/apiService/simpleDataService.js +1 -1
- package/src/components/Button.vue +1 -1
- package/src/components/EbizSForm.vue +398 -0
- package/src/components/EbizSFormItem.vue +587 -0
- package/src/components/EbizTdesignButtonDialog.vue +360 -0
- package/src/index.js +9 -1
- package/src/router/index.js +12 -0
- package/src/views/EbizSFormDemo.vue +327 -0
- package/src/views/EbizTdesignButtonDialogExample.vue +438 -0
- package/src/views/Home.vue +3 -1
@@ -0,0 +1,360 @@
|
|
1
|
+
<template>
|
2
|
+
<div class="ebiz-tdesign-button-dialog">
|
3
|
+
<t-button
|
4
|
+
:theme="buttonTheme"
|
5
|
+
:variant="buttonVariant"
|
6
|
+
:size="buttonSize"
|
7
|
+
:block="buttonBlock"
|
8
|
+
:shape="buttonShape"
|
9
|
+
:disabled="buttonDisabled"
|
10
|
+
:loading="buttonLoading"
|
11
|
+
:icon="buttonIcon"
|
12
|
+
@click="handleButtonClick"
|
13
|
+
>
|
14
|
+
<template v-if="$slots.buttonContent">
|
15
|
+
<slot name="buttonContent"></slot>
|
16
|
+
</template>
|
17
|
+
<template v-else>
|
18
|
+
{{ buttonText }}
|
19
|
+
</template>
|
20
|
+
</t-button>
|
21
|
+
|
22
|
+
<t-dialog
|
23
|
+
v-model:visible="dialogVisible"
|
24
|
+
:header="title || computedTitle"
|
25
|
+
:width="dialogWidth"
|
26
|
+
:top="dialogTop"
|
27
|
+
:attach="dialogAttach"
|
28
|
+
:destroy-on-close="dialogDestroyOnClose"
|
29
|
+
:mode="dialogMode"
|
30
|
+
:placement="dialogPlacement"
|
31
|
+
:show-overlay="dialogShowOverlay"
|
32
|
+
:close-on-esc-keydown="dialogCloseOnEscKeydown"
|
33
|
+
:close-on-overlay-click="dialogCloseOnOverlayClick"
|
34
|
+
:show-footer="dialogShowFooter"
|
35
|
+
@close="handleDialogClose"
|
36
|
+
@confirm="handleDialogConfirm"
|
37
|
+
@cancel="handleDialogCancel"
|
38
|
+
>
|
39
|
+
<template #header>
|
40
|
+
<slot name="header">
|
41
|
+
<div :class="['dialog-header', dialogType === 'delete' ? 'dialog-header-delete' : '']">
|
42
|
+
{{ title || computedTitle }}
|
43
|
+
</div>
|
44
|
+
</slot>
|
45
|
+
</template>
|
46
|
+
|
47
|
+
<template #body>
|
48
|
+
<slot name="body">
|
49
|
+
<div v-if="dialogType === 'delete'" class="delete-confirm-content">
|
50
|
+
<t-icon name="error-circle" size="large" class="delete-icon" />
|
51
|
+
<p class="delete-message">{{ deleteConfirmMessage }}</p>
|
52
|
+
</div>
|
53
|
+
</slot>
|
54
|
+
</template>
|
55
|
+
|
56
|
+
<template #footer>
|
57
|
+
<slot name="footer">
|
58
|
+
<t-space>
|
59
|
+
<t-button v-if="cancelText" theme="default" @click="handleDialogCancel">{{ cancelText }}</t-button>
|
60
|
+
<t-button v-if="confirmText" theme="primary" :loading="apiLoading" @click="handleDialogConfirm">{{ confirmText }}</t-button>
|
61
|
+
</t-space>
|
62
|
+
</slot>
|
63
|
+
</template>
|
64
|
+
</t-dialog>
|
65
|
+
</div>
|
66
|
+
</template>
|
67
|
+
|
68
|
+
<script setup>
|
69
|
+
import { ref, computed, watch } from 'vue'
|
70
|
+
import { Button as TButton, Dialog as TDialog, Space as TSpace, MessagePlugin, Icon as TIcon } from 'tdesign-vue-next'
|
71
|
+
import dataService from '../apiService/simpleDataService'
|
72
|
+
|
73
|
+
const props = defineProps({
|
74
|
+
// 弹窗类型
|
75
|
+
dialogType: {
|
76
|
+
type: String,
|
77
|
+
default: 'normal', // 'normal', 'add', 'delete'
|
78
|
+
validator: (value) => ['normal', 'add', 'delete'].includes(value)
|
79
|
+
},
|
80
|
+
|
81
|
+
// 删除确认消息
|
82
|
+
deleteConfirmMessage: {
|
83
|
+
type: String,
|
84
|
+
default: '确定要删除该数据吗?此操作不可逆,请谨慎操作。'
|
85
|
+
},
|
86
|
+
|
87
|
+
// 按钮基础属性
|
88
|
+
buttonText: {
|
89
|
+
type: String,
|
90
|
+
default: ''
|
91
|
+
},
|
92
|
+
// 按钮样式属性
|
93
|
+
buttonTheme: {
|
94
|
+
type: String,
|
95
|
+
default: ''
|
96
|
+
},
|
97
|
+
buttonVariant: {
|
98
|
+
type: String,
|
99
|
+
default: 'base'
|
100
|
+
},
|
101
|
+
buttonSize: {
|
102
|
+
type: String,
|
103
|
+
default: 'medium'
|
104
|
+
},
|
105
|
+
buttonBlock: {
|
106
|
+
type: Boolean,
|
107
|
+
default: false
|
108
|
+
},
|
109
|
+
buttonShape: {
|
110
|
+
type: String,
|
111
|
+
default: 'rectangle'
|
112
|
+
},
|
113
|
+
buttonDisabled: {
|
114
|
+
type: Boolean,
|
115
|
+
default: false
|
116
|
+
},
|
117
|
+
buttonLoading: {
|
118
|
+
type: Boolean,
|
119
|
+
default: false
|
120
|
+
},
|
121
|
+
buttonIcon: {
|
122
|
+
type: String,
|
123
|
+
default: ''
|
124
|
+
},
|
125
|
+
|
126
|
+
// 弹窗基础属性
|
127
|
+
title: {
|
128
|
+
type: String,
|
129
|
+
default: ''
|
130
|
+
},
|
131
|
+
visible: {
|
132
|
+
type: Boolean,
|
133
|
+
default: false
|
134
|
+
},
|
135
|
+
confirmText: {
|
136
|
+
type: String,
|
137
|
+
default: undefined
|
138
|
+
},
|
139
|
+
cancelText: {
|
140
|
+
type: String,
|
141
|
+
default: undefined
|
142
|
+
},
|
143
|
+
|
144
|
+
// 弹窗样式和行为属性
|
145
|
+
dialogWidth: {
|
146
|
+
type: [String, Number],
|
147
|
+
default: '500px'
|
148
|
+
},
|
149
|
+
dialogTop: {
|
150
|
+
type: [String, Number],
|
151
|
+
default: '15vh'
|
152
|
+
},
|
153
|
+
dialogAttach: {
|
154
|
+
type: [String, Function],
|
155
|
+
default: 'body'
|
156
|
+
},
|
157
|
+
dialogDestroyOnClose: {
|
158
|
+
type: Boolean,
|
159
|
+
default: false
|
160
|
+
},
|
161
|
+
dialogMode: {
|
162
|
+
type: String,
|
163
|
+
default: 'modal'
|
164
|
+
},
|
165
|
+
dialogPlacement: {
|
166
|
+
type: String,
|
167
|
+
default: 'top'
|
168
|
+
},
|
169
|
+
dialogShowOverlay: {
|
170
|
+
type: Boolean,
|
171
|
+
default: true
|
172
|
+
},
|
173
|
+
dialogCloseOnEscKeydown: {
|
174
|
+
type: Boolean,
|
175
|
+
default: true
|
176
|
+
},
|
177
|
+
dialogCloseOnOverlayClick: {
|
178
|
+
type: Boolean,
|
179
|
+
default: true
|
180
|
+
},
|
181
|
+
dialogShowFooter: {
|
182
|
+
type: Boolean,
|
183
|
+
default: true
|
184
|
+
},
|
185
|
+
|
186
|
+
// API配置
|
187
|
+
apiConfig: {
|
188
|
+
type: Object,
|
189
|
+
default: () => null
|
190
|
+
},
|
191
|
+
// 是否在API调用成功后自动关闭弹窗
|
192
|
+
closeOnSuccess: {
|
193
|
+
type: Boolean,
|
194
|
+
default: true
|
195
|
+
},
|
196
|
+
// 是否显示API调用的结果消息
|
197
|
+
showResultMessage: {
|
198
|
+
type: Boolean,
|
199
|
+
default: true
|
200
|
+
}
|
201
|
+
})
|
202
|
+
|
203
|
+
const emit = defineEmits([
|
204
|
+
'update:modelValue',
|
205
|
+
'button-click',
|
206
|
+
'dialog-close',
|
207
|
+
'dialog-confirm',
|
208
|
+
'dialog-cancel',
|
209
|
+
'api-success',
|
210
|
+
'api-error'
|
211
|
+
])
|
212
|
+
|
213
|
+
const computedTitle = computed(() => {
|
214
|
+
switch (props.dialogType) {
|
215
|
+
case 'add': return '添加数据';
|
216
|
+
case 'delete': return '删除确认';
|
217
|
+
default: return '标题';
|
218
|
+
}
|
219
|
+
})
|
220
|
+
|
221
|
+
// 初始化dialogVisible
|
222
|
+
const dialogVisible = ref(props.visible)
|
223
|
+
const apiLoading = ref(false)
|
224
|
+
|
225
|
+
// 监听props的visible变化
|
226
|
+
watch(() => props.visible, (newVal) => {
|
227
|
+
dialogVisible.value = newVal
|
228
|
+
})
|
229
|
+
|
230
|
+
// 监听dialogVisible变化,同步更新modelValue
|
231
|
+
watch(dialogVisible, (newVal) => {
|
232
|
+
emit('update:modelValue', newVal)
|
233
|
+
})
|
234
|
+
|
235
|
+
// 按钮点击事件
|
236
|
+
const handleButtonClick = (e) => {
|
237
|
+
dialogVisible.value = true
|
238
|
+
emit('button-click', e)
|
239
|
+
}
|
240
|
+
|
241
|
+
// 弹窗关闭事件
|
242
|
+
const handleDialogClose = (e) => {
|
243
|
+
dialogVisible.value = false
|
244
|
+
emit('dialog-close', e)
|
245
|
+
}
|
246
|
+
|
247
|
+
// API调用方法
|
248
|
+
const callApi = async () => {
|
249
|
+
if (!props.apiConfig) return null
|
250
|
+
|
251
|
+
try {
|
252
|
+
apiLoading.value = true
|
253
|
+
const { url, method, data, params, headers } = props.apiConfig
|
254
|
+
|
255
|
+
// 构建请求配置
|
256
|
+
const requestConfig = {
|
257
|
+
url,
|
258
|
+
method: method || (props.dialogType === 'delete' ? 'delete' : props.dialogType === 'add' ? 'post' : 'get'),
|
259
|
+
data,
|
260
|
+
params,
|
261
|
+
headers
|
262
|
+
}
|
263
|
+
|
264
|
+
// 调用dataService进行API请求
|
265
|
+
const response = await dataService.request(requestConfig)
|
266
|
+
|
267
|
+
// 显示成功消息
|
268
|
+
if (props.showResultMessage) {
|
269
|
+
const successMessage = props.dialogType === 'delete'
|
270
|
+
? '删除成功'
|
271
|
+
: props.dialogType === 'add'
|
272
|
+
? '添加成功'
|
273
|
+
: '操作成功'
|
274
|
+
MessagePlugin.success(successMessage)
|
275
|
+
}
|
276
|
+
|
277
|
+
// 触发成功事件
|
278
|
+
emit('api-success', response)
|
279
|
+
|
280
|
+
// 如果设置了成功后关闭,则关闭弹窗
|
281
|
+
if (props.closeOnSuccess) {
|
282
|
+
dialogVisible.value = false
|
283
|
+
}
|
284
|
+
|
285
|
+
return response
|
286
|
+
} catch (error) {
|
287
|
+
// 显示错误消息
|
288
|
+
if (props.showResultMessage) {
|
289
|
+
const errorPrefix = props.dialogType === 'delete'
|
290
|
+
? '删除失败'
|
291
|
+
: props.dialogType === 'add'
|
292
|
+
? '添加失败'
|
293
|
+
: '操作失败'
|
294
|
+
MessagePlugin.error(`${errorPrefix}: ${error.message || '未知错误'}`)
|
295
|
+
}
|
296
|
+
|
297
|
+
// 触发错误事件
|
298
|
+
emit('api-error', error)
|
299
|
+
return null
|
300
|
+
} finally {
|
301
|
+
apiLoading.value = false
|
302
|
+
}
|
303
|
+
}
|
304
|
+
|
305
|
+
// 弹窗确认事件
|
306
|
+
const handleDialogConfirm = async (e) => {
|
307
|
+
emit('dialog-confirm', e)
|
308
|
+
|
309
|
+
// 对于非普通类型的弹窗,总是尝试调用API
|
310
|
+
if (props.dialogType !== 'normal') {
|
311
|
+
if (props.apiConfig) {
|
312
|
+
await callApi()
|
313
|
+
} else {
|
314
|
+
console.warn(`${props.dialogType} 类型的弹窗没有配置 apiConfig`)
|
315
|
+
dialogVisible.value = false
|
316
|
+
}
|
317
|
+
} else {
|
318
|
+
// 普通弹窗的行为
|
319
|
+
if (props.apiConfig) {
|
320
|
+
await callApi()
|
321
|
+
} else {
|
322
|
+
dialogVisible.value = false
|
323
|
+
}
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
// 弹窗取消事件
|
328
|
+
const handleDialogCancel = (e) => {
|
329
|
+
dialogVisible.value = false
|
330
|
+
emit('dialog-cancel', e)
|
331
|
+
}
|
332
|
+
</script>
|
333
|
+
|
334
|
+
<style scoped>
|
335
|
+
.ebiz-tdesign-button-dialog {
|
336
|
+
display: inline-block;
|
337
|
+
}
|
338
|
+
|
339
|
+
.dialog-header-delete {
|
340
|
+
color: var(--td-error-color, #e34d59);
|
341
|
+
}
|
342
|
+
|
343
|
+
.delete-confirm-content {
|
344
|
+
display: flex;
|
345
|
+
align-items: center;
|
346
|
+
padding: 16px;
|
347
|
+
}
|
348
|
+
|
349
|
+
.delete-icon {
|
350
|
+
font-size: 24px;
|
351
|
+
color: var(--td-error-color, #e34d59);
|
352
|
+
margin-right: 12px;
|
353
|
+
}
|
354
|
+
|
355
|
+
.delete-message {
|
356
|
+
margin: 0;
|
357
|
+
font-size: 14px;
|
358
|
+
line-height: 22px;
|
359
|
+
}
|
360
|
+
</style>
|
package/src/index.js
CHANGED
@@ -60,6 +60,9 @@ import EbizTreeMergeTable from './components/EbizTreeMergeTable.vue';
|
|
60
60
|
import EbizTdesignLoading from './components/EbizTdesignLoading.vue';
|
61
61
|
import EbizAutoForm from './components/EbizAutoForm.vue';
|
62
62
|
import EbizDepartmentSelector from './components/EbizDepartmentSelector.vue';
|
63
|
+
import EbizTdesignButtonDialog from './components/EbizTdesignButtonDialog.vue';
|
64
|
+
import EbizSForm from './components/EbizSForm.vue';
|
65
|
+
import EbizSFormItem from './components/EbizSFormItem.vue';
|
63
66
|
import { MessagePlugin as EbizMessage } from 'tdesign-vue-next';
|
64
67
|
|
65
68
|
// import EbizDescriptions from './components/EbizDescriptions.vue';
|
@@ -191,5 +194,10 @@ export {
|
|
191
194
|
EbizDescriptionsItem,
|
192
195
|
TDescriptionsItem,
|
193
196
|
EbizTdesignLoading,
|
194
|
-
EbizLoading
|
197
|
+
EbizLoading,
|
198
|
+
// 弹窗按钮组件
|
199
|
+
EbizTdesignButtonDialog,
|
200
|
+
// PC端表单组件
|
201
|
+
EbizSForm,
|
202
|
+
EbizSFormItem
|
195
203
|
};
|
package/src/router/index.js
CHANGED
@@ -310,6 +310,18 @@ const routes = [
|
|
310
310
|
name: 'EbizDepartmentSelector',
|
311
311
|
component: () => import('../views/EbizDepartmentSelectorDemo.vue'),
|
312
312
|
meta: { title: 'Ebiz部门选择器组件示例' }
|
313
|
+
},
|
314
|
+
{
|
315
|
+
path: '/ebiz-tdesign-button-dialog',
|
316
|
+
name: 'EbizTdesignButtonDialog',
|
317
|
+
component: () => import('../views/EbizTdesignButtonDialogExample.vue'),
|
318
|
+
meta: { title: '弹窗按钮组件示例' }
|
319
|
+
},
|
320
|
+
{
|
321
|
+
path: '/ebiz-s-form',
|
322
|
+
name: 'EbizSForm',
|
323
|
+
component: () => import('../views/EbizSFormDemo.vue'),
|
324
|
+
meta: { title: 'PC端表单组件示例' }
|
313
325
|
}
|
314
326
|
]
|
315
327
|
|