gi-component 0.0.1
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/LICENSE +21 -0
- package/README.md +36 -0
- package/dist/dist/index.es.js +2241 -0
- package/dist/dist/index.es.js.map +1 -0
- package/dist/dist/index.umd.js +2 -0
- package/dist/dist/index.umd.js.map +1 -0
- package/dist/gi.css +1 -0
- package/dist/index.d.ts +1 -0
- package/package.json +56 -0
- package/packages/components/button/index.ts +5 -0
- package/packages/components/button/src/button.vue +59 -0
- package/packages/components/button/src/type.ts +15 -0
- package/packages/components/card/index.ts +5 -0
- package/packages/components/card/src/card.vue +166 -0
- package/packages/components/card/src/type.ts +12 -0
- package/packages/components/dialog/index.ts +6 -0
- package/packages/components/dialog/src/dialog.ts +87 -0
- package/packages/components/dialog/src/dialog.vue +122 -0
- package/packages/components/dialog/src/type.ts +16 -0
- package/packages/components/edit-table/index.ts +5 -0
- package/packages/components/edit-table/src/edit-table.vue +207 -0
- package/packages/components/edit-table/src/type.ts +69 -0
- package/packages/components/form/index.ts +5 -0
- package/packages/components/form/src/form.vue +465 -0
- package/packages/components/form/src/type.ts +98 -0
- package/packages/components/grid/index.ts +8 -0
- package/packages/components/grid/src/context.ts +30 -0
- package/packages/components/grid/src/grid-item.vue +143 -0
- package/packages/components/grid/src/grid.vue +151 -0
- package/packages/components/grid/src/hook/use-index.ts +63 -0
- package/packages/components/grid/src/hook/use-responsive-state.ts +66 -0
- package/packages/components/grid/src/hook/use-responsive-value.ts +36 -0
- package/packages/components/grid/src/interface.ts +74 -0
- package/packages/components/grid/src/type.ts +0 -0
- package/packages/components/grid/src/utils/global-config.ts +6 -0
- package/packages/components/grid/src/utils/index.ts +73 -0
- package/packages/components/grid/src/utils/is.ts +9 -0
- package/packages/components/grid/src/utils/responsive-observe.ts +135 -0
- package/packages/components/input-group/index.ts +5 -0
- package/packages/components/input-group/src/input-group.vue +92 -0
- package/packages/components/input-group/src/type.ts +1 -0
- package/packages/components/input-search/index.ts +5 -0
- package/packages/components/input-search/src/input-search.vue +62 -0
- package/packages/components/input-search/src/type.ts +6 -0
- package/packages/components/page-layout/index.ts +5 -0
- package/packages/components/page-layout/src/page-layout.vue +180 -0
- package/packages/components/page-layout/src/split-button.vue +106 -0
- package/packages/components/page-layout/src/type.ts +12 -0
- package/packages/components/table/index.ts +5 -0
- package/packages/components/table/src/TableColumn.vue +49 -0
- package/packages/components/table/src/table.vue +85 -0
- package/packages/components/table/src/type.ts +22 -0
- package/packages/components/tabs/index.ts +5 -0
- package/packages/components/tabs/src/tabs.vue +148 -0
- package/packages/components/tabs/src/type.ts +15 -0
- package/packages/components.d.ts +26 -0
- package/packages/hooks/index.ts +1 -0
- package/packages/hooks/useBemClass.ts +11 -0
- package/packages/index.ts +78 -0
- package/packages/styles/index.scss +176 -0
- package/packages/styles/var.scss +1 -0
- package/packages/utils/createSelectDialog.ts +67 -0
- package/packages/utils/index.ts +1 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<el-table v-bind="tableProps" :data="props.data as any[]">
|
|
4
|
+
<TableColumn
|
|
5
|
+
v-for="item in props.columns"
|
|
6
|
+
:key="item.prop || item.label"
|
|
7
|
+
:column="item"
|
|
8
|
+
>
|
|
9
|
+
<!-- 将所有插槽传递给子组件 -->
|
|
10
|
+
<template
|
|
11
|
+
v-for="(_, slotName) in $slots"
|
|
12
|
+
:key="slotName"
|
|
13
|
+
#[slotName]="scope"
|
|
14
|
+
>
|
|
15
|
+
<slot :name="slotName" v-bind="scope" />
|
|
16
|
+
</template>
|
|
17
|
+
</TableColumn>
|
|
18
|
+
</el-table>
|
|
19
|
+
|
|
20
|
+
<el-row justify="end" :class="b('table-pagination')">
|
|
21
|
+
<el-pagination
|
|
22
|
+
v-bind="paginationProps"
|
|
23
|
+
v-model:current-page="paginationProps.currentPage"
|
|
24
|
+
v-model:page-size="paginationProps.pageSize"
|
|
25
|
+
@size-change="handleSizeChange"
|
|
26
|
+
@current-change="handleCurrentChange"
|
|
27
|
+
/>
|
|
28
|
+
</el-row>
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script lang="ts" setup>
|
|
33
|
+
import type { TableProps } from './type';
|
|
34
|
+
import { computed, useAttrs } from 'vue';
|
|
35
|
+
import { useBemClass } from '../../../hooks';
|
|
36
|
+
import TableColumn from './TableColumn.vue';
|
|
37
|
+
|
|
38
|
+
const props = withDefaults(defineProps<TableProps>(), {
|
|
39
|
+
columns: () => [],
|
|
40
|
+
pagination: () => ({})
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const attrs = useAttrs();
|
|
44
|
+
const { b } = useBemClass();
|
|
45
|
+
|
|
46
|
+
const tableProps = computed(() => {
|
|
47
|
+
return {
|
|
48
|
+
...attrs,
|
|
49
|
+
...props,
|
|
50
|
+
columns: undefined,
|
|
51
|
+
pagination: undefined
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const paginationProps = computed(() => {
|
|
56
|
+
return {
|
|
57
|
+
background: true,
|
|
58
|
+
layout: 'prev, pager, next, sizes, total',
|
|
59
|
+
pageSizes: [10, 20, 50, 100],
|
|
60
|
+
...props.pagination
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
function handleSizeChange(size: number) {
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
props.pagination.pageSize = size;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function handleCurrentChange(page: number) {
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
props.pagination.currentPage = page;
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<style lang="scss" scoped>
|
|
76
|
+
@use '../../../styles/var.scss' as a;
|
|
77
|
+
|
|
78
|
+
:deep(.el-pagination__rightwrapper) {
|
|
79
|
+
flex: auto;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.#{a.$prefix}-table-pagination {
|
|
83
|
+
margin-top: 10px;
|
|
84
|
+
}
|
|
85
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TableProps as ElTableProps,
|
|
3
|
+
PaginationProps,
|
|
4
|
+
TableColumnCtx,
|
|
5
|
+
TableColumnInstance
|
|
6
|
+
} from 'element-plus';
|
|
7
|
+
import type { ExtractPropTypes, VNode } from 'vue';
|
|
8
|
+
|
|
9
|
+
export interface TableColumnItem
|
|
10
|
+
extends Omit<TableColumnInstance['$props'], never> {
|
|
11
|
+
slotName?: string;
|
|
12
|
+
children?: TableColumnItem[];
|
|
13
|
+
render?: (scope: TableColumnCtx<any>) => VNode | VNode[] | string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TableProps
|
|
17
|
+
extends ExtractPropTypes<
|
|
18
|
+
ElTableProps<Record<string | number | symbol, any>>
|
|
19
|
+
> {
|
|
20
|
+
columns?: TableColumnItem[];
|
|
21
|
+
pagination?: Partial<PaginationProps>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="getClass">
|
|
3
|
+
<div :class="b('tabs__default')">
|
|
4
|
+
<slot>
|
|
5
|
+
<el-tabs
|
|
6
|
+
v-model="model"
|
|
7
|
+
:type="props.type"
|
|
8
|
+
:stretch="props.stretch"
|
|
9
|
+
@tab-click="(p, e) => emits('tabClick', p, e)"
|
|
10
|
+
@tab-change="emits('tabChange', $event)"
|
|
11
|
+
>
|
|
12
|
+
<el-tab-pane
|
|
13
|
+
v-for="item in props.options"
|
|
14
|
+
:key="item.name"
|
|
15
|
+
:name="item.name"
|
|
16
|
+
:disabled="item?.disabled"
|
|
17
|
+
>
|
|
18
|
+
<template #label>
|
|
19
|
+
<slot name="label" :data="item">{{ item.label }}</slot>
|
|
20
|
+
</template>
|
|
21
|
+
</el-tab-pane>
|
|
22
|
+
</el-tabs>
|
|
23
|
+
</slot>
|
|
24
|
+
</div>
|
|
25
|
+
<div v-if="slots.extra" :class="b('tabs__extra')">
|
|
26
|
+
<slot name="extra"></slot>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup lang="ts">
|
|
32
|
+
import type { TabsProps as ElTabsProps, TabsPaneContext } from 'element-plus';
|
|
33
|
+
import type { TabsOptionItem, TabsProps } from './type.ts';
|
|
34
|
+
import { computed, useSlots } from 'vue';
|
|
35
|
+
import { useBemClass } from '../../../hooks';
|
|
36
|
+
|
|
37
|
+
const model = defineModel<ElTabsProps['modelValue']>();
|
|
38
|
+
|
|
39
|
+
const props = withDefaults(defineProps<TabsProps>(), {
|
|
40
|
+
type: '',
|
|
41
|
+
options: () => [],
|
|
42
|
+
size: 'medium',
|
|
43
|
+
inner: false
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const emits = defineEmits<{
|
|
47
|
+
(e: 'tabClick', pane: TabsPaneContext, ev: Event): void;
|
|
48
|
+
(e: 'tabChange', value: string): void;
|
|
49
|
+
}>();
|
|
50
|
+
|
|
51
|
+
defineSlots<{
|
|
52
|
+
default: () => void;
|
|
53
|
+
extra: () => void;
|
|
54
|
+
label: (e: { data: TabsOptionItem }) => void;
|
|
55
|
+
}>();
|
|
56
|
+
|
|
57
|
+
const slots = useSlots();
|
|
58
|
+
const { b } = useBemClass();
|
|
59
|
+
|
|
60
|
+
const getClass = computed(() => {
|
|
61
|
+
const arr: string[] = [b('tabs')];
|
|
62
|
+
arr.push(b(`tabs--${props.size}`));
|
|
63
|
+
if (props.inner) {
|
|
64
|
+
arr.push(b('tabs--inner'));
|
|
65
|
+
}
|
|
66
|
+
return arr.join(' ');
|
|
67
|
+
});
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<style lang="scss" scoped>
|
|
71
|
+
@use '../../../styles/var.scss' as a;
|
|
72
|
+
|
|
73
|
+
:deep(.el-tabs__nav-prev),
|
|
74
|
+
:deep(.el-tabs__nav-next) {
|
|
75
|
+
height: 100%;
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
justify-content: center;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.#{a.$prefix}-tabs {
|
|
82
|
+
width: 100%;
|
|
83
|
+
padding: 0 var(--padding-x);
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
border-bottom: 1px solid var(--el-border-color);
|
|
87
|
+
box-sizing: border-box;
|
|
88
|
+
background-color: var(--el-bg-color);
|
|
89
|
+
|
|
90
|
+
&__default {
|
|
91
|
+
flex: 1;
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
|
|
94
|
+
:deep(.el-tabs__header) {
|
|
95
|
+
margin-bottom: 0;
|
|
96
|
+
|
|
97
|
+
.el-tabs__nav-wrap {
|
|
98
|
+
&::after {
|
|
99
|
+
display: none;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
:deep(.el-tabs__active-bar) {
|
|
105
|
+
bottom: 1px;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&__extra {
|
|
110
|
+
margin-left: 10px;
|
|
111
|
+
align-self: flex-start;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
:deep(.el-tabs--card) {
|
|
116
|
+
> .el-tabs__header {
|
|
117
|
+
border-bottom: none;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
:deep(.el-tabs--border-card) {
|
|
122
|
+
border-bottom: none;
|
|
123
|
+
|
|
124
|
+
> .el-tabs__content {
|
|
125
|
+
display: none;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
> .el-tabs__header {
|
|
129
|
+
border-bottom: none;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.#{a.$prefix}-tabs--small {
|
|
134
|
+
padding: 0 var(--padding-x-small);
|
|
135
|
+
|
|
136
|
+
:deep(.el-tabs) {
|
|
137
|
+
--el-tabs-header-height: 32px;
|
|
138
|
+
|
|
139
|
+
.el-tabs__item {
|
|
140
|
+
font-size: 12px;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.#{a.$prefix}-tabs--inner {
|
|
146
|
+
padding: 0;
|
|
147
|
+
}
|
|
148
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TabsProps as ElTabsProps } from 'element-plus';
|
|
2
|
+
|
|
3
|
+
export type TabsOptionItem = {
|
|
4
|
+
label: string;
|
|
5
|
+
name: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export interface TabsProps
|
|
10
|
+
extends Partial<Pick<ElTabsProps, 'type' | 'stretch'>> {
|
|
11
|
+
type?: ElTabsProps['type'];
|
|
12
|
+
options?: TabsOptionItem[];
|
|
13
|
+
size?: 'small' | 'medium';
|
|
14
|
+
inner?: boolean; // 内嵌模式
|
|
15
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
// Generated by unplugin-vue-components
|
|
4
|
+
// Read more: https://github.com/vuejs/core/pull/3399
|
|
5
|
+
// biome-ignore lint: disable
|
|
6
|
+
export {}
|
|
7
|
+
|
|
8
|
+
/* prettier-ignore */
|
|
9
|
+
declare module 'vue' {
|
|
10
|
+
export interface GlobalComponents {
|
|
11
|
+
GiButton: typeof import('./components/button/src/button.vue')['default']
|
|
12
|
+
GiCard: typeof import('./components/card/src/card.vue')['default']
|
|
13
|
+
GiDialog: typeof import('./components/dialog/src/dialog.vue')['default']
|
|
14
|
+
GiEditTable: typeof import('./components/edit-table/src/edit-table.vue')['default']
|
|
15
|
+
GiForm: typeof import('./components/form/src/form.vue')['default']
|
|
16
|
+
GiGrid: typeof import('./components/grid/src/grid.vue')['default']
|
|
17
|
+
GiGridItem: typeof import('./components/grid/src/grid-item.vue')['default']
|
|
18
|
+
GiInputGroup: typeof import('./components/input-group/src/input-group.vue')['default']
|
|
19
|
+
GiInputSearch: typeof import('./components/input-search/src/input-search.vue')['default']
|
|
20
|
+
GiPageLayout: typeof import('./components/page-layout/src/page-layout.vue')['default']
|
|
21
|
+
GiSplitButton: typeof import('./components/page-layout/src/split-button.vue')['default']
|
|
22
|
+
GiTable: typeof import('./components/table/src/table.vue')['default']
|
|
23
|
+
GiTableColumn: typeof import('./components/table/src/TableColumn.vue')['default']
|
|
24
|
+
GiTabs: typeof import('./components/tabs/src/tabs.vue')['default']
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useBemClass';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { getCurrentInstance } from 'vue';
|
|
2
|
+
|
|
3
|
+
export function useBemClass() {
|
|
4
|
+
const instance = getCurrentInstance();
|
|
5
|
+
const configPrefix =
|
|
6
|
+
instance?.appContext.config.globalProperties.$config?.prefix || 'gi';
|
|
7
|
+
const prefix = configPrefix.toLowerCase();
|
|
8
|
+
const b = (name: string = '') => `${prefix}-${name ? `${name}` : ''}`;
|
|
9
|
+
|
|
10
|
+
return { b };
|
|
11
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { App } from 'vue';
|
|
2
|
+
|
|
3
|
+
import Button from './components/button';
|
|
4
|
+
import Card from './components/card';
|
|
5
|
+
import Dialog from './components/dialog';
|
|
6
|
+
import EditTable from './components/edit-table';
|
|
7
|
+
import Form from './components/form';
|
|
8
|
+
import GridItem from './components/grid/src/grid-item.vue';
|
|
9
|
+
import Grid from './components/grid/src/grid.vue';
|
|
10
|
+
import InputGroup from './components/input-group';
|
|
11
|
+
import InputSearch from './components/input-search';
|
|
12
|
+
import PageLayout from './components/page-layout';
|
|
13
|
+
import Table from './components/table';
|
|
14
|
+
import Tabs from './components/tabs';
|
|
15
|
+
import './styles/index.scss';
|
|
16
|
+
|
|
17
|
+
export * from './components/dialog';
|
|
18
|
+
export * from './components/edit-table';
|
|
19
|
+
export * from './components/form';
|
|
20
|
+
export * from './components/table';
|
|
21
|
+
export * from './hooks';
|
|
22
|
+
export * from './utils';
|
|
23
|
+
|
|
24
|
+
const components = {
|
|
25
|
+
Button,
|
|
26
|
+
Card,
|
|
27
|
+
Tabs,
|
|
28
|
+
InputGroup,
|
|
29
|
+
InputSearch,
|
|
30
|
+
Grid,
|
|
31
|
+
GridItem,
|
|
32
|
+
Form,
|
|
33
|
+
PageLayout,
|
|
34
|
+
Dialog,
|
|
35
|
+
EditTable,
|
|
36
|
+
Table
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// 导出Gi前缀的组件并添加明确类型注解
|
|
40
|
+
export const GiButton: typeof Button = Button;
|
|
41
|
+
export const GiCard: typeof Card = Card;
|
|
42
|
+
export const GiTabs: typeof Tabs = Tabs;
|
|
43
|
+
export const GiInputGroup: typeof InputGroup = InputGroup;
|
|
44
|
+
export const GiInputSearch: typeof InputSearch = InputSearch;
|
|
45
|
+
export const GiGrid: typeof Grid = Grid;
|
|
46
|
+
export const GiGridItem: typeof GridItem = GridItem;
|
|
47
|
+
export const GiForm: typeof Form = Form;
|
|
48
|
+
export const GiPageLayout: typeof PageLayout = PageLayout;
|
|
49
|
+
export const GiDialog: typeof Dialog = Dialog;
|
|
50
|
+
export const GiEditTable: typeof EditTable = EditTable;
|
|
51
|
+
export const GiTable: typeof Table = Table;
|
|
52
|
+
|
|
53
|
+
function capitalizeWord(word: string) {
|
|
54
|
+
// 检查输入是否为字符串且不为空
|
|
55
|
+
if (typeof word !== 'string' || word.length === 0) {
|
|
56
|
+
return word;
|
|
57
|
+
}
|
|
58
|
+
// 首字母大写,其余字母小写
|
|
59
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 全局默认配置
|
|
63
|
+
export interface Config {
|
|
64
|
+
prefix?: string; // 组件前缀
|
|
65
|
+
clearable?: boolean; // 输入框是否可清除
|
|
66
|
+
dictRequest?: () => Promise<any>; // 字典请求方法
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export default {
|
|
70
|
+
install(app: App, options?: Config) {
|
|
71
|
+
const prefix = options?.prefix || 'Gi';
|
|
72
|
+
Object.entries(components).forEach(([name, component]) => {
|
|
73
|
+
app.component(`${capitalizeWord(prefix)}${name}`, component);
|
|
74
|
+
});
|
|
75
|
+
// 将配置保存到全局属性
|
|
76
|
+
app.config.globalProperties.$config = options;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
@use './var.scss' as a;
|
|
2
|
+
|
|
3
|
+
body {
|
|
4
|
+
--padding: 14px;
|
|
5
|
+
--margin: 14px;
|
|
6
|
+
--padding-x: 14px;
|
|
7
|
+
--padding-x-small: 10px;
|
|
8
|
+
--padding-y: 10px;
|
|
9
|
+
--padding-y-small: 6px;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.gi-card-title {
|
|
13
|
+
.gi-card-header__title {
|
|
14
|
+
padding-left: 8px;
|
|
15
|
+
position: relative;
|
|
16
|
+
|
|
17
|
+
&::before {
|
|
18
|
+
content: '';
|
|
19
|
+
width: 4px;
|
|
20
|
+
height: 20px;
|
|
21
|
+
position: absolute;
|
|
22
|
+
left: 0;
|
|
23
|
+
top: 50%;
|
|
24
|
+
transform: translateY(-50%);
|
|
25
|
+
background-color: var(--el-color-primary);
|
|
26
|
+
border-radius: 0 4px 4px 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.gi-w-full {
|
|
32
|
+
width: 100%;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.gi-h-full {
|
|
36
|
+
height: 100%;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.gi-line-1 {
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
white-space: nowrap;
|
|
42
|
+
text-overflow: ellipsis;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.gi-line-2 {
|
|
46
|
+
line-clamp: 2;
|
|
47
|
+
-webkit-line-clamp: 2;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.gi-line-3 {
|
|
51
|
+
line-clamp: 3;
|
|
52
|
+
-webkit-line-clamp: 3;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.gi-line-4 {
|
|
56
|
+
line-clamp: 4;
|
|
57
|
+
-webkit-line-clamp: 4;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.gi-line-5 {
|
|
61
|
+
line-clamp: 5;
|
|
62
|
+
-webkit-line-clamp: 5;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.gi-line-2,
|
|
66
|
+
.gi-line-3,
|
|
67
|
+
.gi-line-4,
|
|
68
|
+
.gi-line-5 {
|
|
69
|
+
overflow: hidden;
|
|
70
|
+
word-break: break-all;
|
|
71
|
+
text-overflow: ellipsis;
|
|
72
|
+
display: -webkit-box; // 弹性伸缩盒
|
|
73
|
+
-webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.gi-mt {
|
|
77
|
+
margin-top: var(--margin);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.gi-mb {
|
|
81
|
+
margin-bottom: var(--margin);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.gi-ml {
|
|
85
|
+
margin-left: var(--margin);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.gi-mr {
|
|
89
|
+
margin-right: var(--margin);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.gi-mx {
|
|
93
|
+
margin-left: var(--margin);
|
|
94
|
+
margin-right: var(--margin);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.gi-my {
|
|
98
|
+
margin-top: var(--margin);
|
|
99
|
+
margin-bottom: var(--margin);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.gi-m0 {
|
|
103
|
+
margin: 0 !important;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.gi-pt {
|
|
107
|
+
padding-top: var(--padding);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.gi-pb {
|
|
111
|
+
padding-bottom: var(--padding);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.gi-pl {
|
|
115
|
+
padding-left: var(--padding);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.gi-pr {
|
|
119
|
+
padding-right: var(--padding);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.gi-px {
|
|
123
|
+
padding-left: var(--padding);
|
|
124
|
+
padding-right: var(--padding);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.gi-py {
|
|
128
|
+
padding-top: var(--padding);
|
|
129
|
+
padding-bottom: var(--padding);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.gi-p0 {
|
|
133
|
+
padding: 0 !important;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.el-dialog {
|
|
137
|
+
padding: 0 !important;
|
|
138
|
+
|
|
139
|
+
&.is-fullscreen {
|
|
140
|
+
overflow: hidden;
|
|
141
|
+
display: inline-flex;
|
|
142
|
+
flex-direction: column;
|
|
143
|
+
|
|
144
|
+
.el-dialog__body {
|
|
145
|
+
flex: 1;
|
|
146
|
+
overflow-y: auto;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.el-dialog__header {
|
|
151
|
+
height: 48px;
|
|
152
|
+
padding-left: var(--el-dialog-padding-primary);
|
|
153
|
+
padding-bottom: 0;
|
|
154
|
+
display: flex;
|
|
155
|
+
align-items: center;
|
|
156
|
+
border-bottom: 1px solid var(--el-border-color);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.el-dialog__body {
|
|
160
|
+
padding: var(--el-dialog-padding-primary);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.el-dialog__footer {
|
|
164
|
+
padding: 12px var(--el-dialog-padding-primary);
|
|
165
|
+
border-top: 1px solid var(--el-border-color);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.el-dialog.#{a.$prefix}-dialog--simple {
|
|
170
|
+
.el-dialog__header {
|
|
171
|
+
border-bottom: none;
|
|
172
|
+
}
|
|
173
|
+
.el-dialog__footer {
|
|
174
|
+
border-top: none;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$prefix: 'gi' !default;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Component } from 'vue';
|
|
2
|
+
import { ElMessage } from 'element-plus';
|
|
3
|
+
import { h, ref } from 'vue';
|
|
4
|
+
import { Dialog } from '../index';
|
|
5
|
+
|
|
6
|
+
type CreateSelectDialogParams = {
|
|
7
|
+
title: string;
|
|
8
|
+
component: Component;
|
|
9
|
+
componentProps?: Record<string, any>;
|
|
10
|
+
tip?: string;
|
|
11
|
+
bodyClass?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
interface DefOption {
|
|
15
|
+
queryParams: Record<string, any>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type DialogOption<T, Q extends DefOption = DefOption> = {
|
|
19
|
+
title?: string;
|
|
20
|
+
multiple?: boolean;
|
|
21
|
+
queryParams?: Q['queryParams'];
|
|
22
|
+
onOk?: (data: T) => void;
|
|
23
|
+
onBeforeOk?: (data: T) => Promise<boolean>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 创建选择弹窗
|
|
28
|
+
* @description component组件必须暴露一个getSelectedData方法
|
|
29
|
+
*/
|
|
30
|
+
export const createSelectDialog = <T, Q extends DefOption = DefOption>(
|
|
31
|
+
params: CreateSelectDialogParams
|
|
32
|
+
) => {
|
|
33
|
+
return function (options: DialogOption<T, Q>) {
|
|
34
|
+
const { multiple = false, onOk, onBeforeOk, queryParams } = options;
|
|
35
|
+
const DialogTableRef = ref<any>();
|
|
36
|
+
|
|
37
|
+
Dialog.open({
|
|
38
|
+
title: params.title || options.title,
|
|
39
|
+
content: () =>
|
|
40
|
+
h(params.component, {
|
|
41
|
+
ref: (e: any) => (DialogTableRef.value = e),
|
|
42
|
+
multiple,
|
|
43
|
+
queryParams,
|
|
44
|
+
...params.componentProps
|
|
45
|
+
}),
|
|
46
|
+
style: { maxWidth: '960px' },
|
|
47
|
+
bodyClass: params.bodyClass,
|
|
48
|
+
onBeforeOk: async () => {
|
|
49
|
+
if (!DialogTableRef.value.getSelectedData) {
|
|
50
|
+
ElMessage.error('组件必须暴露getSelectedData方法');
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const data = DialogTableRef.value?.getSelectedData();
|
|
54
|
+
if (!data.length) {
|
|
55
|
+
ElMessage.warning(params.tip || '请选择数据');
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
if (onBeforeOk) {
|
|
59
|
+
return await onBeforeOk(data);
|
|
60
|
+
} else {
|
|
61
|
+
onOk?.(data);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createSelectDialog';
|