gi-component 0.0.4 → 0.0.6
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/gi.css +1 -1
- package/dist/index.d.ts +64 -6
- package/dist/index.es.js +69 -8
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/packages/components/edit-table/src/edit-table.vue +1 -0
- package/packages/components/form/src/form.vue +21 -74
- package/packages/components/form/src/type.ts +1 -1
- package/packages/components/table/src/TableColumn.vue +4 -11
- package/packages/components/table/src/type.ts +4 -4
- package/packages/hooks/index.ts +1 -0
- package/packages/hooks/useTable.ts +96 -1
- package/packages/index.ts +7 -2
- package/packages/styles/index.scss +3 -2
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
<template v-if="column.slotName">
|
|
11
11
|
<slot :name="column.slotName" v-bind="scope"></slot>
|
|
12
12
|
</template>
|
|
13
|
+
<template v-else-if="!column.type">{{ scope.row[column.prop] }}</template>
|
|
13
14
|
<component :is="COMP_MAP[column.type] || column.type" v-else v-bind="getComponentBindProps(column)"
|
|
14
15
|
v-model="scope.row[column.prop]" class="w-full" :disabled="isDisabled(scope)">
|
|
15
16
|
</component>
|
|
@@ -1,49 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<el-form
|
|
3
|
-
|
|
4
|
-
:class="getClass"
|
|
5
|
-
v-bind="formProps"
|
|
6
|
-
:model="props.modelValue"
|
|
7
|
-
>
|
|
8
|
-
<Grid
|
|
9
|
-
class="w-full"
|
|
10
|
-
:col-gap="12"
|
|
11
|
-
v-bind="props.gridProps"
|
|
12
|
-
:collapsed="collapsed"
|
|
13
|
-
>
|
|
2
|
+
<el-form ref="formRef" :class="getClass" v-bind="formProps" :model="props.modelValue">
|
|
3
|
+
<Grid class="w-full" :col-gap="12" v-bind="props.gridProps" :collapsed="collapsed">
|
|
14
4
|
<template v-for="(item, index) in props.columns">
|
|
15
|
-
<GridItem
|
|
16
|
-
v-if="item.type === 'title'"
|
|
17
|
-
:key="`title${index}`"
|
|
18
|
-
:span="100"
|
|
19
|
-
>
|
|
5
|
+
<GridItem v-if="item.type === 'title'" :key="`title${index}`" :span="100">
|
|
20
6
|
<el-form-item label-width="0">
|
|
21
|
-
<GiCard
|
|
22
|
-
:
|
|
23
|
-
:header-style="{ padding: 0 }"
|
|
24
|
-
:body-style="{ display: 'none' }"
|
|
25
|
-
></GiCard>
|
|
7
|
+
<GiCard :title="typeof item.label === 'string' ? item.label : ''" :header-style="{ padding: 0 }"
|
|
8
|
+
:body-style="{ display: 'none' }"></GiCard>
|
|
26
9
|
</el-form-item>
|
|
27
10
|
</GridItem>
|
|
28
11
|
|
|
29
12
|
<template v-else>
|
|
30
|
-
<GridItem
|
|
31
|
-
|
|
32
|
-
:key="item.field + index"
|
|
33
|
-
v-bind="item.gridItemProps || props.gridItemProps"
|
|
34
|
-
:span="
|
|
35
|
-
item.span ||
|
|
13
|
+
<GridItem v-if="!isHide(item)" :key="item.field + index" v-bind="item.gridItemProps || props.gridItemProps"
|
|
14
|
+
:span="item.span ||
|
|
36
15
|
item.gridItemProps?.span ||
|
|
37
16
|
props?.gridItemProps?.span
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
:key="item.field + index"
|
|
42
|
-
:prop="item.field"
|
|
43
|
-
:label="item.label"
|
|
44
|
-
:rules="getFormItemRules(item)"
|
|
45
|
-
v-bind="item.formItemProps"
|
|
46
|
-
>
|
|
17
|
+
">
|
|
18
|
+
<el-form-item :key="item.field + index" :prop="item.field" :label="item.label"
|
|
19
|
+
:rules="getFormItemRules(item)" v-bind="item.formItemProps">
|
|
47
20
|
<template v-if="item?.labelRender" #label>
|
|
48
21
|
<component :is="item.labelRender"></component>
|
|
49
22
|
</template>
|
|
@@ -53,21 +26,10 @@
|
|
|
53
26
|
<template v-else>
|
|
54
27
|
<div :class="b('form-item__content')">
|
|
55
28
|
<div :class="b('form-item__component')">
|
|
56
|
-
<component
|
|
57
|
-
:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
v-bind="getComponentBindProps(item)"
|
|
61
|
-
:model-value="
|
|
62
|
-
props.modelValue[item.fieldName || item.field]
|
|
63
|
-
"
|
|
64
|
-
@update:model-value="updateModelValue($event, item)"
|
|
65
|
-
>
|
|
66
|
-
<template
|
|
67
|
-
v-for="(slotValue, slotKey) in item?.slots || {}"
|
|
68
|
-
:key="slotKey"
|
|
69
|
-
#[slotKey]="scope"
|
|
70
|
-
>
|
|
29
|
+
<component :is="CompMap[item.type] || item.type" :disabled="isDisabled(item)" class="w-full"
|
|
30
|
+
v-bind="getComponentBindProps(item)" :model-value="props.modelValue[item.fieldName || item.field]
|
|
31
|
+
" @update:model-value="updateModelValue($event, item)">
|
|
32
|
+
<template v-for="(slotValue, slotKey) in item?.slots || {}" :key="slotKey" #[slotKey]="scope">
|
|
71
33
|
<template v-if="typeof slotValue === 'string'">
|
|
72
34
|
{{ slotValue }}
|
|
73
35
|
</template>
|
|
@@ -76,12 +38,7 @@
|
|
|
76
38
|
</template>
|
|
77
39
|
</template>
|
|
78
40
|
</component>
|
|
79
|
-
<el-text
|
|
80
|
-
v-if="item.tip"
|
|
81
|
-
:class="b('form-item__tip')"
|
|
82
|
-
type="info"
|
|
83
|
-
size="small"
|
|
84
|
-
>
|
|
41
|
+
<el-text v-if="item.tip" :class="b('form-item__tip')" type="info" size="small">
|
|
85
42
|
{{ item.tip }}
|
|
86
43
|
</el-text>
|
|
87
44
|
</div>
|
|
@@ -90,7 +47,7 @@
|
|
|
90
47
|
<template v-if="typeof item.extra === 'string'">
|
|
91
48
|
<el-text type="info" size="small">{{
|
|
92
49
|
item.extra
|
|
93
|
-
|
|
50
|
+
}}</el-text>
|
|
94
51
|
</template>
|
|
95
52
|
<template v-else-if="item.extra">
|
|
96
53
|
<component :is="item.extra"></component>
|
|
@@ -103,25 +60,14 @@
|
|
|
103
60
|
</template>
|
|
104
61
|
</template>
|
|
105
62
|
|
|
106
|
-
<GridItem
|
|
107
|
-
v-if="props.search"
|
|
108
|
-
:suffix="props.search"
|
|
109
|
-
:span="props?.gridItemProps?.span"
|
|
110
|
-
>
|
|
63
|
+
<GridItem v-if="props.search" :suffix="props.search" :span="props?.gridItemProps?.span">
|
|
111
64
|
<el-space :class="b('form__search-btns')">
|
|
112
65
|
<el-button type="primary" @click="emit('search')">
|
|
113
66
|
{{ searchText }}
|
|
114
67
|
</el-button>
|
|
115
68
|
<el-button @click="emit('reset')"> 重置 </el-button>
|
|
116
|
-
<el-button
|
|
117
|
-
|
|
118
|
-
class="form__fold-btn"
|
|
119
|
-
type="primary"
|
|
120
|
-
:icon="collapsed ? ArrowDown : ArrowUp"
|
|
121
|
-
text
|
|
122
|
-
size="small"
|
|
123
|
-
@click="collapsed = !collapsed"
|
|
124
|
-
>
|
|
69
|
+
<el-button v-if="!props.hideFoldBtn" class="form__fold-btn" type="primary"
|
|
70
|
+
:icon="collapsed ? ArrowDown : ArrowUp" text size="small" @click="collapsed = !collapsed">
|
|
125
71
|
{{ collapsed ? '展开' : '收起' }}
|
|
126
72
|
</el-button>
|
|
127
73
|
</el-space>
|
|
@@ -376,7 +322,7 @@ function isHide(item: FormColumnItem) {
|
|
|
376
322
|
/** 禁用表单项 */
|
|
377
323
|
function isDisabled(item: FormColumnItem) {
|
|
378
324
|
if (item?.props?.disabled !== undefined) return item?.props?.disabled;
|
|
379
|
-
if (props.fc?.[item.field]?.
|
|
325
|
+
if (props.fc?.[item.field]?.disabled === true) return true;
|
|
380
326
|
return false;
|
|
381
327
|
}
|
|
382
328
|
|
|
@@ -417,6 +363,7 @@ defineExpose({ formRef });
|
|
|
417
363
|
}
|
|
418
364
|
|
|
419
365
|
:deep(.hide-label) {
|
|
366
|
+
|
|
420
367
|
// 隐藏el-form-item__label才能完整占满插槽宽度
|
|
421
368
|
.el-form-item__label {
|
|
422
369
|
display: none;
|
|
@@ -88,7 +88,7 @@ export interface FormColumnItem<F = any> {
|
|
|
88
88
|
export interface FormProps extends Partial<ElFormProps> {
|
|
89
89
|
modelValue: any;
|
|
90
90
|
columns?: FormColumnItem[];
|
|
91
|
-
fc?: Record<string, {
|
|
91
|
+
fc?: Record<string, { disabled?: boolean; hidden?: boolean; required?: boolean }>; // 表单控制
|
|
92
92
|
gridProps?: GridProps; // grid默认配置
|
|
93
93
|
gridItemProps?: GridItemProps; // grid-item默认配置
|
|
94
94
|
search?: boolean;
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
<el-table-column v-bind="columnProps">
|
|
3
3
|
<!-- 处理render函数 -->
|
|
4
4
|
<template v-if="column.render" v-slot="scope">
|
|
5
|
-
<
|
|
5
|
+
<template v-if="typeof column.render(scope) === 'string'">{{ column.render(scope) }}</template>
|
|
6
|
+
<component v-else :is="column.render(scope)" />
|
|
6
7
|
</template>
|
|
7
8
|
|
|
8
9
|
<!-- 处理插槽内容 -->
|
|
@@ -12,17 +13,9 @@
|
|
|
12
13
|
|
|
13
14
|
<!-- 递归渲染子列 -->
|
|
14
15
|
<template v-if="column.children && column.children.length > 0">
|
|
15
|
-
<TableColumn
|
|
16
|
-
v-for="child in column.children"
|
|
17
|
-
:key="child.prop || child.label"
|
|
18
|
-
:column="child"
|
|
19
|
-
>
|
|
16
|
+
<TableColumn v-for="child in column.children" :key="child.prop || child.label" :column="child">
|
|
20
17
|
<!-- 将所有插槽传递给子组件 -->
|
|
21
|
-
<template
|
|
22
|
-
v-for="(_, slotName) in $slots"
|
|
23
|
-
:key="slotName"
|
|
24
|
-
#[slotName]="scope"
|
|
25
|
-
>
|
|
18
|
+
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="scope">
|
|
26
19
|
<slot :name="slotName" v-bind="scope" />
|
|
27
20
|
</template>
|
|
28
21
|
</TableColumn>
|
|
@@ -2,15 +2,15 @@ import type {
|
|
|
2
2
|
TableProps as ElTableProps,
|
|
3
3
|
PaginationProps,
|
|
4
4
|
TableColumnCtx,
|
|
5
|
-
TableColumnInstance
|
|
5
|
+
TableColumnInstance,
|
|
6
6
|
} from 'element-plus';
|
|
7
7
|
import type { ExtractPropTypes, VNode } from 'vue';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
type DefaultRow = Record<PropertyKey, any>
|
|
10
|
+
export interface TableColumnItem<T extends DefaultRow = DefaultRow> extends Omit<TableColumnInstance['$props'], never> {
|
|
11
11
|
slotName?: string;
|
|
12
12
|
children?: TableColumnItem[];
|
|
13
|
-
render?: (scope:
|
|
13
|
+
render?: (scope: { $index: number; cellIndex: number; column: TableColumnItem<T>; row: T }) => VNode | VNode[] | string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface TableProps
|
package/packages/hooks/index.ts
CHANGED
|
@@ -1,3 +1,98 @@
|
|
|
1
|
-
export function useTable() {
|
|
2
1
|
|
|
2
|
+
import { ElMessageBox } from 'element-plus'
|
|
3
|
+
import { reactive, ref, getCurrentInstance, type Ref } from 'vue'
|
|
4
|
+
|
|
5
|
+
interface Options<T, U> {
|
|
6
|
+
onSuccess?: () => void
|
|
7
|
+
immediate?: boolean
|
|
8
|
+
rowKey?: keyof T
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface ApiResult<T> {
|
|
12
|
+
code: number
|
|
13
|
+
data: T
|
|
14
|
+
message: string
|
|
15
|
+
success: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface PageResult<T> {
|
|
19
|
+
list: T[]
|
|
20
|
+
total: number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface UseTablePaginationParams { page: number; size: number; }
|
|
24
|
+
|
|
25
|
+
export interface UseTableApi<T> {
|
|
26
|
+
(params: UseTablePaginationParams): Promise<ApiResult<PageResult<T[]>>> | Promise<ApiResult<T[]>>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function useTable<T extends U, U = T>(api: UseTableApi<T>, options: Options<T, U>) {
|
|
30
|
+
const { onSuccess, immediate = true, rowKey = 'id' } = options || {}
|
|
31
|
+
|
|
32
|
+
// const instance = getCurrentInstance();
|
|
33
|
+
// const globalConfig = instance?.appContext.config.globalProperties?.$config || {};
|
|
34
|
+
|
|
35
|
+
const loading = ref(false)
|
|
36
|
+
const tableData: Ref<U[]> = ref([])
|
|
37
|
+
|
|
38
|
+
const pagination = reactive({
|
|
39
|
+
currentPage: 1,
|
|
40
|
+
pageSize: 20,
|
|
41
|
+
total: 0,
|
|
42
|
+
onCurrentChange: (size: number) => {
|
|
43
|
+
pagination.currentPage = size
|
|
44
|
+
getTableData()
|
|
45
|
+
},
|
|
46
|
+
onSizeChange: (size: number) => {
|
|
47
|
+
pagination.pageSize = size
|
|
48
|
+
getTableData()
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
function setTotal(total: number) {
|
|
53
|
+
pagination.total = total
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function getTableData() {
|
|
57
|
+
try {
|
|
58
|
+
loading.value = true
|
|
59
|
+
const res = await api({ page: pagination.currentPage, size: pagination.pageSize })
|
|
60
|
+
// 处理返回的数据结构可能是分页或数组的情况
|
|
61
|
+
const data = !Array.isArray(res.data) ? res.data.list : res.data
|
|
62
|
+
tableData.value = data as T[]
|
|
63
|
+
// 设置总数据量
|
|
64
|
+
const total = !Array.isArray(res.data) ? res.data.total : data.length
|
|
65
|
+
setTotal(total)
|
|
66
|
+
onSuccess?.()
|
|
67
|
+
} finally {
|
|
68
|
+
loading.value = false
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 是否立即触发请求
|
|
73
|
+
immediate && getTableData()
|
|
74
|
+
|
|
75
|
+
function search() {
|
|
76
|
+
pagination.currentPage = 1
|
|
77
|
+
getTableData()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function refresh() {
|
|
81
|
+
getTableData()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
/** 表格数据 */
|
|
86
|
+
tableData,
|
|
87
|
+
/** 获取表格数据 */
|
|
88
|
+
getTableData,
|
|
89
|
+
/** 分页数据 */
|
|
90
|
+
pagination,
|
|
91
|
+
/** 加载状态 */
|
|
92
|
+
loading,
|
|
93
|
+
/** 搜索 */
|
|
94
|
+
search,
|
|
95
|
+
/** 刷新 */
|
|
96
|
+
refresh,
|
|
97
|
+
}
|
|
3
98
|
}
|
package/packages/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from './components/dialog';
|
|
|
18
18
|
export * from './components/edit-table';
|
|
19
19
|
export * from './components/form';
|
|
20
20
|
export * from './components/table';
|
|
21
|
+
export * from './components/tabs';
|
|
21
22
|
export * from './hooks';
|
|
22
23
|
export * from './utils';
|
|
23
24
|
|
|
@@ -62,8 +63,12 @@ function capitalizeWord(word: string) {
|
|
|
62
63
|
// 全局默认配置
|
|
63
64
|
export interface Config {
|
|
64
65
|
prefix?: string; // 组件前缀
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
/** 输入框是否可清除 */
|
|
67
|
+
clearable?: boolean;
|
|
68
|
+
/** 字典请求方法 */
|
|
69
|
+
dictRequest?: () => Promise<any>;
|
|
70
|
+
/** 格式化响应数据, 用于useTable */
|
|
71
|
+
// formatResponse?: (data: any) => any;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
export default {
|
|
@@ -5,8 +5,8 @@ body {
|
|
|
5
5
|
--margin: 14px;
|
|
6
6
|
--padding-x: 14px;
|
|
7
7
|
--padding-x-small: 10px;
|
|
8
|
-
--padding-y:
|
|
9
|
-
--padding-y-small:
|
|
8
|
+
--padding-y: 12px;
|
|
9
|
+
--padding-y-small: 8px;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
.gi-card-title {
|
|
@@ -170,6 +170,7 @@ body {
|
|
|
170
170
|
.el-dialog__header {
|
|
171
171
|
border-bottom: none;
|
|
172
172
|
}
|
|
173
|
+
|
|
173
174
|
.el-dialog__footer {
|
|
174
175
|
border-top: none;
|
|
175
176
|
}
|