@ebiz/designer-components 0.0.19 → 0.0.21

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.
@@ -0,0 +1,341 @@
1
+ <template>
2
+ <div class="ebiz-descriptions">
3
+ <div v-if="title || $slots.title" class="ebiz-descriptions__header">
4
+ <slot name="title">{{ title }}</slot>
5
+ </div>
6
+ <table
7
+ class="ebiz-descriptions__body"
8
+ :class="[
9
+ `ebiz-descriptions--${size}`,
10
+ { 'ebiz-descriptions__body--fixed': tableLayout === 'fixed' },
11
+ { 'ebiz-descriptions__body--border': border }
12
+ ]"
13
+ :style="border && tableBorderColor ? {'--td-descriptions-border-color': tableBorderColor} : {}"
14
+ >
15
+ <tbody>
16
+ <template v-if="rows.length > 0">
17
+ <template v-if="layout === 'horizontal'">
18
+ <tr v-for="(row, rowIndex) in rows" :key="`row-${rowIndex}`">
19
+ <template v-for="(item, colIndex) in row" :key="`${rowIndex}-${colIndex}`">
20
+ <template v-if="itemLayout === 'horizontal'">
21
+ <th
22
+ class="ebiz-descriptions__label"
23
+ :class="[item.labelClassName]"
24
+ >
25
+ <slot :name="`${item.slotName}-label`">
26
+ {{ item.label }}
27
+ </slot>
28
+ <span v-if="colon" class="ebiz-descriptions__colon">:</span>
29
+ </th>
30
+ <td
31
+ :colspan="item.span * 2 - 1"
32
+ class="ebiz-descriptions__content"
33
+ :class="[item.contentClassName]"
34
+ >
35
+ <slot :name="item.slotName">
36
+ {{ item.content }}
37
+ </slot>
38
+ </td>
39
+ </template>
40
+ </template>
41
+ </tr>
42
+ </template>
43
+ <template v-else>
44
+ <template v-for="(row, rowIndex) in rows" :key="`${rowIndex}`">
45
+ <template v-if="itemLayout === 'horizontal'">
46
+ <tr>
47
+ <template v-for="(item, colIndex) in row" :key="`label-${rowIndex}-${colIndex}`">
48
+ <th
49
+ class="ebiz-descriptions__label"
50
+ :class="[item.labelClassName]"
51
+ >
52
+ <slot :name="`${item.slotName}-label`">
53
+ {{ item.label }}
54
+ </slot>
55
+ <span v-if="colon" class="ebiz-descriptions__colon">:</span>
56
+ </th>
57
+ <td
58
+ :colspan="item.span"
59
+ class="ebiz-descriptions__content"
60
+ :class="[item.contentClassName]"
61
+ >
62
+ <slot :name="item.slotName">
63
+ {{ item.content }}
64
+ </slot>
65
+ </td>
66
+ </template>
67
+ </tr>
68
+ </template>
69
+ <template v-else>
70
+ <tr>
71
+ <template v-for="(item, colIndex) in row" :key="`label-${rowIndex}-${colIndex}`">
72
+ <th
73
+ :colspan="item.span"
74
+ class="ebiz-descriptions__label"
75
+ :class="[item.labelClassName]"
76
+ >
77
+ <slot :name="`${item.slotName}-label`">
78
+ {{ item.label }}
79
+ </slot>
80
+ <span v-if="colon" class="ebiz-descriptions__colon">:</span>
81
+ </th>
82
+ </template>
83
+ </tr>
84
+ <tr>
85
+ <template v-for="(item, colIndex) in row" :key="`content-${rowIndex}-${colIndex}`">
86
+ <td
87
+ :colspan="item.span"
88
+ class="ebiz-descriptions__content"
89
+ :class="[item.contentClassName]"
90
+ >
91
+ <slot :name="item.slotName">
92
+ {{ item.content }}
93
+ </slot>
94
+ </td>
95
+ </template>
96
+ </tr>
97
+ </template>
98
+ </template>
99
+ </template>
100
+ </template>
101
+ <template v-else>
102
+ <slot></slot>
103
+ </template>
104
+ </tbody>
105
+ </table>
106
+ </div>
107
+ </template>
108
+
109
+ <script setup>
110
+ import { defineProps, defineEmits, computed, useSlots, ref } from 'vue';
111
+ import { isArray, isNil } from 'lodash-es';
112
+
113
+ const props = defineProps({
114
+ border: {
115
+ type: Boolean,
116
+ default: false
117
+ },
118
+ colon: {
119
+ type: Boolean,
120
+ default: false
121
+ },
122
+ column: {
123
+ type: Number,
124
+ default: 2
125
+ },
126
+ layout: {
127
+ type: String,
128
+ default: 'horizontal',
129
+ validator(val) {
130
+ return ['horizontal', 'vertical'].includes(val);
131
+ }
132
+ },
133
+ itemLayout: {
134
+ type: String,
135
+ default: 'horizontal',
136
+ validator(val) {
137
+ return ['horizontal', 'vertical'].includes(val);
138
+ }
139
+ },
140
+ size: {
141
+ type: String,
142
+ default: 'medium',
143
+ validator(val) {
144
+ return ['small', 'medium', 'large'].includes(val);
145
+ }
146
+ },
147
+ title: {
148
+ type: String,
149
+ default: ''
150
+ },
151
+ tableLayout: {
152
+ type: String,
153
+ default: 'fixed',
154
+ validator(val) {
155
+ return ['auto', 'fixed'].includes(val);
156
+ }
157
+ },
158
+ tableBorderColor: {
159
+ type: String,
160
+ default: ''
161
+ },
162
+ items: {
163
+ type: Array,
164
+ default: () => []
165
+ }
166
+ });
167
+
168
+ defineEmits([]);
169
+
170
+ const slots = useSlots();
171
+ const itemsType = ref('slots');
172
+
173
+ // 计算行数据
174
+ const rows = computed(() => {
175
+ // 1. 获取要渲染的 items
176
+ let items = [];
177
+
178
+ if (isArray(props.items) && props.items.length > 0) {
179
+ // 从 props.items 获取数据
180
+ items = props.items.map(item => ({
181
+ label: item.label,
182
+ content: item.content,
183
+ span: item.span || 1,
184
+ labelClassName: item.labelClassName || '',
185
+ contentClassName: item.contentClassName || '',
186
+ slotName: item.name || `item-${items.length}`
187
+ }));
188
+ itemsType.value = 'props';
189
+ } else {
190
+ // 从 slots 获取数据
191
+ const defaultSlot = slots.default?.();
192
+ if (defaultSlot) {
193
+ items = defaultSlot
194
+ .filter(vnode => vnode.type &&
195
+ (vnode.type.name === 'EbizDescriptionsItem' ||
196
+ vnode.type.__name === 'EbizDescriptionsItem'))
197
+ .map((vnode, index) => {
198
+ const props = vnode.props || {};
199
+ const span = isNil(props.span) ? 1 : Number(props.span);
200
+ return {
201
+ label: props.label || '',
202
+ content: '',
203
+ span: span > props.column ? props.column : span,
204
+ labelClassName: props.labelClassName || '',
205
+ contentClassName: props.contentClassName || '',
206
+ slotName: props.name || `item-${index}`,
207
+ children: vnode.children
208
+ };
209
+ });
210
+ itemsType.value = 'slots';
211
+ }
212
+ }
213
+
214
+ // 2. 判断布局,如果是垂直布局则直接返回
215
+ if (props.layout === 'vertical') {
216
+ return [items];
217
+ }
218
+
219
+ // 3. 水平布局时,计算每一行的item
220
+ const rows = [];
221
+ let currentRow = [];
222
+ let currentRowSpan = 0;
223
+ const { column } = props;
224
+
225
+ items.forEach((item, index) => {
226
+ const span = item.span || 1;
227
+
228
+ // 如果当前行放不下了,创建新行
229
+ if (currentRowSpan + span > column) {
230
+ rows.push(currentRow);
231
+ currentRow = [];
232
+ currentRowSpan = 0;
233
+ }
234
+
235
+ // 添加到当前行
236
+ currentRow.push({
237
+ ...item,
238
+ span: span
239
+ });
240
+
241
+ currentRowSpan += span;
242
+
243
+ // 处理最后一个元素
244
+ if (index === items.length - 1) {
245
+ // 最后一个元素填充剩余空间
246
+ if (currentRowSpan < column) {
247
+ currentRow[currentRow.length - 1].span += (column - currentRowSpan);
248
+ }
249
+ rows.push(currentRow);
250
+ }
251
+ });
252
+
253
+ return rows;
254
+ });
255
+ </script>
256
+
257
+ <style scoped>
258
+ .ebiz-descriptions {
259
+ font-size: 14px;
260
+ color: rgba(0, 0, 0, 0.9);
261
+ line-height: 22px;
262
+ }
263
+
264
+ .ebiz-descriptions__header {
265
+ margin-bottom: 16px;
266
+ }
267
+
268
+ .ebiz-descriptions__header > * {
269
+ font-size: 16px;
270
+ font-weight: 700;
271
+ color: rgba(0, 0, 0, 0.9);
272
+ line-height: 24px;
273
+ }
274
+
275
+ .ebiz-descriptions__body {
276
+ width: 100%;
277
+ border-collapse: collapse;
278
+ table-layout: fixed;
279
+ }
280
+
281
+ .ebiz-descriptions__body--fixed {
282
+ table-layout: fixed;
283
+ }
284
+
285
+ .ebiz-descriptions__body--border {
286
+ border-collapse: separate;
287
+ border-spacing: 0;
288
+ border-top: 1px solid var(--td-descriptions-border-color, #dcdcdc);
289
+ border-left: 1px solid var(--td-descriptions-border-color, #dcdcdc);
290
+ }
291
+
292
+ .ebiz-descriptions__body--border .ebiz-descriptions__label,
293
+ .ebiz-descriptions__body--border .ebiz-descriptions__content {
294
+ border-right: 1px solid var(--td-descriptions-border-color, #dcdcdc);
295
+ border-bottom: 1px solid var(--td-descriptions-border-color, #dcdcdc);
296
+ }
297
+
298
+ .ebiz-descriptions__label {
299
+ font-weight: normal;
300
+ color: rgba(0, 0, 0, 0.6);
301
+ background-color: #fafafa;
302
+ text-align: left;
303
+ padding: 12px 24px 12px 12px;
304
+ vertical-align: top;
305
+ }
306
+
307
+ .ebiz-descriptions__colon {
308
+ margin: 0 8px 0 2px;
309
+ }
310
+
311
+ .ebiz-descriptions__content {
312
+ padding: 12px;
313
+ text-align: left;
314
+ vertical-align: top;
315
+ }
316
+
317
+ /* 尺寸相关样式 */
318
+ .ebiz-descriptions--small .ebiz-descriptions__label,
319
+ .ebiz-descriptions--small .ebiz-descriptions__content {
320
+ padding: 8px;
321
+ }
322
+
323
+ .ebiz-descriptions--medium .ebiz-descriptions__label,
324
+ .ebiz-descriptions--medium .ebiz-descriptions__content {
325
+ padding: 12px;
326
+ }
327
+
328
+ .ebiz-descriptions--large .ebiz-descriptions__label,
329
+ .ebiz-descriptions--large .ebiz-descriptions__content {
330
+ padding: 16px;
331
+ }
332
+
333
+ /* 不同布局的padding调整 */
334
+ .ebiz-descriptions__body:not(.ebiz-descriptions__body--border) .ebiz-descriptions__label {
335
+ padding-left: 0;
336
+ }
337
+
338
+ .ebiz-descriptions__body:not(.ebiz-descriptions__body--border) .ebiz-descriptions__content {
339
+ padding-right: 0;
340
+ }
341
+ </style>
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <div>
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { defineProps } from 'vue';
9
+
10
+ defineProps({
11
+ label: {
12
+ type: String,
13
+ default: ''
14
+ },
15
+ span: {
16
+ type: Number,
17
+ default: 1
18
+ },
19
+ className: {
20
+ type: String,
21
+ default: ''
22
+ },
23
+ labelClassName: {
24
+ type: String,
25
+ default: ''
26
+ },
27
+ contentClassName: {
28
+ type: String,
29
+ default: ''
30
+ },
31
+ layout: {
32
+ type: String,
33
+ default: '',
34
+ validator(val) {
35
+ if (!val) return true;
36
+ return ['horizontal', 'vertical'].includes(val);
37
+ }
38
+ }
39
+ });
40
+ </script>
41
+
42
+ <style scoped>
43
+ .ebiz-descriptions-item {
44
+ box-sizing: border-box;
45
+ padding: 0;
46
+ margin: 0;
47
+ }
48
+ </style>
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <t-popconfirm
3
+ :content="content"
4
+ @cancel="handleCancel"
5
+ @confirm="handleConfirm"
6
+ >
7
+ <slot></slot>
8
+ </t-popconfirm>
9
+ </template>
10
+
11
+ <script>
12
+ export default {
13
+ name: "EbizPopconfirm"
14
+ }
15
+ </script>
16
+
17
+ <script setup>
18
+ import { Popconfirm as TPopconfirm } from 'tdesign-vue-next';
19
+
20
+ // 定义属性
21
+ const props = defineProps({
22
+ // 确认框内容
23
+ content: {
24
+ type: [String, Function],
25
+ default: ''
26
+ }
27
+ });
28
+
29
+ // 定义事件
30
+ const emit = defineEmits([
31
+ 'cancel',
32
+ 'confirm'
33
+ ]);
34
+
35
+ // 取消按钮点击事件
36
+ const handleCancel = ({ e }) => {
37
+ emit('cancel', { e });
38
+ };
39
+
40
+ // 确认按钮点击事件
41
+ const handleConfirm = ({ e }) => {
42
+ emit('confirm', { e });
43
+ };
44
+ </script>
45
+
46
+ <style lang="less" scoped>
47
+ /* 自定义样式可在此处添加 */
48
+ </style>
@@ -1,95 +1,95 @@
1
- <template>
2
- <div>
3
- <tiny-select
4
- v-model="value3"
5
- filterable
6
- remote
7
- :remote-config="{ autoSearch: true }"
8
- :remote-method="remoteMethod3"
9
- :loading="loading3"
10
- loading-text="Loading..."
11
- @change="onChange"
12
- >
13
- <tiny-option v-for="item in options3" :key="item.value" :label="item.label" :value="item.value"> </tiny-option>
14
- </tiny-select>
15
-
16
- </div>
17
- </template>
18
-
19
- <script setup>
20
- import { onMounted, ref, toRefs} from 'vue'
21
- import { TinySelect, TinyOption } from '@opentiny/vue'
22
- import request from '@/apiService/simpleDataService';
23
- const props = defineProps({
24
- apiConfig: {
25
- type: Object,
26
- default: {
27
- apiId: null,
28
- apiType: ''
29
- }
30
- }
31
- })
32
- const emit = defineEmits(['formSubmitted'])
33
-
34
- onMounted(() => {
35
- remoteMethod3('')
36
- })
37
-
38
- const loading3 = ref(false)
39
- const value3 = ref('')
40
- const options3 = ref([])
41
- const list = ref([])
42
-
43
- {/* const url = ('http://192.168.0.247:9002/api/appdata/select') */}
44
-
45
- const { apiConfig } = toRefs(props);
46
-
47
- const remoteMethod3 = (query) => {
48
- request.fetch({
49
- "queryParams":{"name": query}
50
- },{
51
- apiId: apiConfig.value.apiId,
52
- },'/appdata/select',).then((val) => {
53
- console.log("val.data11111", val.data)
54
- options3.value = val.data.map((item) => {
55
- return { value: item.name, label: item.name }
56
- })
57
- console.log("options3.value", options3.value)
58
-
59
- }).catch((err) => {
60
- console.log("err111111", err)
61
- })
62
- }
63
- const onChange = () => {
64
- emit('formSubmitted', value3.value);
65
- }
66
-
67
-
68
- {/* const url = ('http://localhost:3000/admin/product/getHomeProList') */}
69
-
70
-
71
- {/* onMounted(async() => {
72
- // await axios.get(url).then((val) => {
73
- // console.log('val', val.data.data)
74
- // list.value = val.data.data.map((item) => {
75
- // return { value: item.name, label: item.name }
76
- // })
77
- // })
78
-
79
-
80
- // post请求 参数: apiId: 372, queryParams: {"type": 1}
81
- await axios.post(url, { apiId: params.apiId, queryParams: { type: 1 } }).then((val) => {
82
- list.value = val.data.data.map((item) => {
83
- return { value: item.name, label: item.name }
84
- })
85
- })
86
-
87
- }) */}
88
-
89
- </script>
90
-
91
- <style lang="less" scoped>
92
- .tiny-select {
93
- width: 280px;
94
- }
95
- </style>
1
+ <template>
2
+ <div>
3
+ <tiny-select
4
+ v-model="value3"
5
+ filterable
6
+ remote
7
+ :remote-config="{ autoSearch: true }"
8
+ :remote-method="remoteMethod3"
9
+ :loading="loading3"
10
+ loading-text="Loading..."
11
+ @change="onChange"
12
+ >
13
+ <tiny-option v-for="item in options3" :key="item.value" :label="item.label" :value="item.value"> </tiny-option>
14
+ </tiny-select>
15
+
16
+ </div>
17
+ </template>
18
+
19
+ <script setup>
20
+ import { onMounted, ref, toRefs} from 'vue'
21
+ import { TinySelect, TinyOption } from '@opentiny/vue'
22
+ import request from '@/apiService/simpleDataService';
23
+ const props = defineProps({
24
+ apiConfig: {
25
+ type: Object,
26
+ default: {
27
+ apiId: null,
28
+ apiType: ''
29
+ }
30
+ }
31
+ })
32
+ const emit = defineEmits(['formSubmitted'])
33
+
34
+ onMounted(() => {
35
+ remoteMethod3('')
36
+ })
37
+
38
+ const loading3 = ref(false)
39
+ const value3 = ref('')
40
+ const options3 = ref([])
41
+ const list = ref([])
42
+
43
+ {/* const url = ('http://192.168.0.247:9002/api/appdata/select') */}
44
+
45
+ const { apiConfig } = toRefs(props);
46
+
47
+ const remoteMethod3 = (query) => {
48
+ request.fetch({
49
+ "queryParams":{"name": query}
50
+ },{
51
+ apiId: apiConfig.value.apiId,
52
+ },'/appdata/select',).then((val) => {
53
+ console.log("val.data11111", val.data)
54
+ options3.value = val.data.map((item) => {
55
+ return { value: item.name, label: item.name }
56
+ })
57
+ console.log("options3.value", options3.value)
58
+
59
+ }).catch((err) => {
60
+ console.log("err111111", err)
61
+ })
62
+ }
63
+ const onChange = () => {
64
+ emit('formSubmitted', value3.value);
65
+ }
66
+
67
+
68
+ {/* const url = ('http://localhost:3000/admin/product/getHomeProList') */}
69
+
70
+
71
+ {/* onMounted(async() => {
72
+ // await axios.get(url).then((val) => {
73
+ // console.log('val', val.data.data)
74
+ // list.value = val.data.data.map((item) => {
75
+ // return { value: item.name, label: item.name }
76
+ // })
77
+ // })
78
+
79
+
80
+ // post请求 参数: apiId: 372, queryParams: {"type": 1}
81
+ await axios.post(url, { apiId: params.apiId, queryParams: { type: 1 } }).then((val) => {
82
+ list.value = val.data.data.map((item) => {
83
+ return { value: item.name, label: item.name }
84
+ })
85
+ })
86
+
87
+ }) */}
88
+
89
+ </script>
90
+
91
+ <style lang="less" scoped>
92
+ .tiny-select {
93
+ width: 280px;
94
+ }
95
+ </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div>
3
- <t-table :data="data" :columns="mergedColumns" :row-key="rowKey" :vertical-align="verticalAlign"
3
+ <t-table ref="tableRef" :data="data" :columns="mergedColumns" :row-key="rowKey" :vertical-align="verticalAlign"
4
4
  :horizontal-align="horizontalAlign" :size="size" :bordered="bordered" :stripe="stripe" :hover="hover"
5
5
  :height="height" :max-height="maxHeight" :loading="loading" :loading-props="loadingProps" :load-more="loadMore"
6
6
  :empty="empty" :table-layout="tableLayout" :cell-empty-content="cellEmptyContent" :pagination="pagination"
@@ -459,6 +459,10 @@ const handleDragSort = (params) => {
459
459
  const handleValidate = (context) => {
460
460
  emit('validate', context);
461
461
  };
462
+ const tableRef = ref();
463
+ defineExpose({
464
+ tableRef
465
+ })
462
466
  </script>
463
467
 
464
468
  <style lang="less" scoped>