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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gi-component",
3
3
  "type": "module",
4
- "version": "0.0.4",
4
+ "version": "0.0.6",
5
5
  "description": "Vue3中基于Element Plus二次封装基础组件库",
6
6
  "author": "lin",
7
7
  "license": "MIT",
@@ -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
- ref="formRef"
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
- :title="typeof item.label === 'string' ? item.label : ''"
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
- v-if="!isHide(item)"
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
- <el-form-item
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
- :is="CompMap[item.type] || item.type"
58
- :disabled="isDisabled(item)"
59
- class="w-full"
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
- }}</el-text>
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
- v-if="!props.hideFoldBtn"
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]?.edit === false) return true;
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, { edit: boolean; hidden?: boolean; required?: boolean }>; // 表单控制
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
- <component :is="column.render(scope)" />
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
- export interface TableColumnItem
10
- extends Omit<TableColumnInstance['$props'], never> {
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: TableColumnCtx<any>) => VNode | VNode[] | string;
13
+ render?: (scope: { $index: number; cellIndex: number; column: TableColumnItem<T>; row: T }) => VNode | VNode[] | string;
14
14
  }
15
15
 
16
16
  export interface TableProps
@@ -1 +1,2 @@
1
1
  export * from './useBemClass';
2
+ export * from './useTable';
@@ -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
- clearable?: boolean; // 输入框是否可清除
66
- dictRequest?: () => Promise<any>; // 字典请求方法
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: 10px;
9
- --padding-y-small: 6px;
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
  }