@vue-ui-kit/ant 2.0.6 → 2.0.8
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/cjs/index.js +3 -3
- package/dist/declarations/antProxy.d.ts +3 -0
- package/dist/es/index.js +2296 -2183
- package/dist/packages/components/CollapseCard.vue.d.ts +33 -0
- package/dist/packages/components/PFormGroup.vue.d.ts +2 -0
- package/dist/packages/utils/core.d.ts +2 -0
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/declarations/antProxy.ts +4 -0
- package/src/packages/components/CollapseCard.vue +74 -0
- package/src/packages/components/PCanvasTable.vue +2 -1
- package/src/packages/components/PFormCol.vue +61 -43
- package/src/packages/components/PFormGroup.vue +11 -4
- package/src/packages/utils/core.ts +22 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/** 是否默认折叠 */
|
|
3
|
+
defaultCollapsed?: boolean;
|
|
4
|
+
title?: string;
|
|
5
|
+
/** 是否可以折叠 */
|
|
6
|
+
collapsible?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare function __VLS_template(): {
|
|
9
|
+
attrs: Partial<{}>;
|
|
10
|
+
slots: Readonly<{
|
|
11
|
+
title: () => any;
|
|
12
|
+
}> & {
|
|
13
|
+
title: () => any;
|
|
14
|
+
};
|
|
15
|
+
refs: {};
|
|
16
|
+
rootEl: any;
|
|
17
|
+
};
|
|
18
|
+
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
19
|
+
declare const __VLS_component: import('vue').DefineComponent<Props, {
|
|
20
|
+
collapse: () => void;
|
|
21
|
+
expand: () => void;
|
|
22
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
23
|
+
title: string;
|
|
24
|
+
defaultCollapsed: boolean;
|
|
25
|
+
collapsible: boolean;
|
|
26
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
27
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
28
|
+
export default _default;
|
|
29
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
30
|
+
new (): {
|
|
31
|
+
$slots: S;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
@@ -10,6 +10,8 @@ declare const _default: <F extends Recordable = Recordable>(__VLS_props: NonNull
|
|
|
10
10
|
}>[];
|
|
11
11
|
} & PFormGroupProps<F>) & Partial<{}>> & import('vue').PublicProps;
|
|
12
12
|
expose(exposed: import('vue').ShallowUnwrapRef<{
|
|
13
|
+
collapse: () => void;
|
|
14
|
+
expand: () => void;
|
|
13
15
|
activeKey: import('vue').ComputedRef<number>;
|
|
14
16
|
setActiveKey: (key: number) => void;
|
|
15
17
|
validateAll: () => Promise<PromiseSettledResult<any>[]>;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ColumnProps, Responsive } from '../../declarations/antProxy';
|
|
2
2
|
import { TableColumnGroupType, TableColumnType } from 'ant-design-vue';
|
|
3
|
+
import { WatchOptions, WatchSource } from 'vue';
|
|
3
4
|
export declare const cleanCol: (col: ColumnProps) => TableColumnType | TableColumnGroupType<Recordable>;
|
|
4
5
|
export declare const defaultItemResponsive: Responsive;
|
|
5
6
|
export declare const defaultLabelCol: Responsive;
|
|
6
7
|
export declare const labelColDict: Record<number, Responsive>;
|
|
7
8
|
export declare const get24rest: (exist: number[]) => number;
|
|
8
9
|
export declare const getButtonResponsive: (itemResponsive: number | Responsive[]) => any;
|
|
10
|
+
export declare function watchPreviousDeep<T extends object>(source: WatchSource<T>, cb: (value: T, oldValue: T, onCleanup: () => void) => void, options?: WatchOptions): import('vue').WatchHandle;
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8"
|
|
1
|
+
@charset "UTF-8";.collapsible-card[data-v-e5901b25]{background-color:#fff;border-color:#f0f0f0}.collapsible-card[data-v-e5901b25] .ant-collapse-header{padding:0 12px;min-height:38px;display:flex;align-items:center;font-weight:600}.collapsible-card[data-v-e5901b25] .ant-collapse-content{border-color:#f0f0f0}.collapsible-card[data-v-e5901b25] .ant-collapse-content .ant-collapse-content-box{padding:var(--collapsible-card-body-padding, 12px)}.collapsible-card[data-v-e5901b25] .ant-collapse-item{border-color:#f0f0f0}:root{--p-theme-bg: #fff}.p-pane{background-color:var(--p-theme-bg);padding:16px;border-radius:4px}.text-slate-5{color:#64748b}.w-full{width:100%}.cursor-pointer{cursor:pointer}.py-4x{padding-top:4px;padding-bottom:4px}.px-2x{padding-left:2px;padding-right:2px}.pl-4x{padding-left:1em}.pl-8{padding-left:2em}.h-0{height:0}.h-full{height:100%}.flex{display:flex}.flex-col{flex-direction:column}.flex-1{flex:1}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-4px{gap:4px}.gap-8px{gap:8px}.pt-8px{padding-top:8px}.px-16px{padding-left:16px;padding-right:16px}.mt-4px{margin-top:4px}.text-right{text-align:right}.overflow-y-auto{overflow-y:auto}.p-theme-bg{background-color:var(--p-theme-bg)}.p-wrapper .p-form-wrapper{z-index:4}.p-wrapper .p-canvas-pagination.ant-pagination{padding:16px 0}.p-wrapper .p-error-hang-out .ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper{border-color:#d9d9d9!important}.p-wrapper .p-error-hang-out .ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper:focus{border-color:#4096ff!important}.p-wrapper .p-error-hang-out .ant-form-item-explain-error{opacity:0!important;transform:translateY(-10px)!important;max-height:0!important;overflow:hidden!important;transition:none!important}.p-wrapper .ant-form-item-explain-error{opacity:0;transform:translateY(-10px);max-height:0;overflow:hidden;transition:opacity .3s ease-out .3s,transform .3s ease-out .3s,max-height .3s ease-out .3s}.p-wrapper .ant-form-item-has-error .ant-form-item-explain-error{opacity:1;transform:translateY(0);max-height:100px}.p-wrapper .p-toolbar-wrapper{box-shadow:0 8px #fff;border-radius:.5em .5em 0 0;margin-bottom:-.5em}.p-wrapper .p-canvas-toolbar-wrapper{box-shadow:0 8px #fff;border-radius:.5em .5em 0 0}.p-wrapper .ant-form .ant-form-item{margin-bottom:0}.p-wrapper .ant-form .ant-form-item.p-required .ant-form-item-label>label:before{display:inline-block;margin-inline-end:4px;color:#ff4d4f;font-size:14px;font-family:SimSun,sans-serif;line-height:1;content:"*"}.p-wrapper .ant-form .ant-form-item .ant-form-item-label{display:flex;align-items:start;justify-content:flex-end}.p-wrapper .ant-form .ant-form-item .ant-form-item-label>label{white-space:break-spaces;align-items:flex-start;height:fit-content;padding-top:.36em}.p-wrapper .ant-form .ant-form-item .ant-form-item-label>label:after{padding-left:4px;margin-inline-start:unset}.p-wrapper .ant-form.ant-form-vertical .ant-form-item .ant-form-item-label{justify-content:flex-start;font-weight:600}.p-wrapper .ant-table-sticky-scroll{visibility:hidden}.p-wrapper .ant-table-header.ant-table-sticky-holder:before{content:"";width:100%;position:absolute;height:22px;display:block;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);top:-16px}.p-wrapper .ant-table-wrapper .ant-table-pagination.ant-pagination{margin:unset;padding:16px 0}.p-wrapper .h-lack .ant-table-wrapper .ant-table-pagination.ant-pagination{padding:unset;margin-top:8px}.p-wrapper .p-inner-scroll>.ant-table-wrapper{height:100%}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading{height:100%}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container{height:100%;display:flex;flex-direction:column}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table{flex:1;height:0;overflow-y:hidden;border-radius:unset}.p-wrapper .p-inner-scroll>.ant-table-wrapper>.ant-spin-nested-loading>.ant-spin-container>.ant-table>.ant-table-container>.ant-table-body{position:relative}.p-wrapper .ant-pagination-options .ant-select{width:100px}.p-wrapper .ant-table-cell:not(.normal-break){word-break:break-all}.p-error-group-tab{position:relative;overflow:visible;color:#f5222d!important}.p-error-group-tab:after{content:"🏷️";position:absolute;top:-1em;right:0;width:1em;height:1em;font-size:.8em;animation:heartbeat 2s infinite}.ant-picker-dropdown .ant-picker-footer{padding-left:4px}.p-error-hang-out .ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper{border-color:#d9d9d9!important}.p-error-hang-out .ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper:focus{border-color:#4096ff!important}.p-error-hang-out .ant-form-item-explain-error{display:none}.no-error-border{border-color:#d9d9d9!important}.no-error-border:focus{border-color:#4096ff!important}@media (max-width: 575px){.p-wrapper .ant-form .ant-form-item .ant-form-item-label{justify-content:flex-start}}.p-content-align-right.ant-form-item .ant-form-item-control-input-content{display:flex;justify-content:flex-end;align-items:center;text-align:right}.p-content-align-center.ant-form-item .ant-form-item-control-input-content{display:flex;justify-content:center;align-items:center;text-align:center}@keyframes heartbeat{0%{transform:scale(1)}6%{transform:scale(1.22)}12%{transform:scale(1)}18%{transform:scale(1.18)}24%{transform:scale(1)}48%{transform:scale(1)}54%{transform:scale(1.22)}60%{transform:scale(1)}66%{transform:scale(1.18)}72%{transform:scale(1)}to{transform:scale(1)}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue-ui-kit/ant",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": "Vue3 UI Kit based on Ant Design",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"email": "adoin@qq.com"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"e-virt-table": "^1.2.
|
|
49
|
+
"e-virt-table": "^1.2.27",
|
|
50
50
|
"uuid": "^10.0.0",
|
|
51
51
|
"xe-utils": "^3.7.6"
|
|
52
52
|
},
|
|
@@ -120,6 +120,10 @@ export interface PFormGroupProps<F extends Recordable = Recordable> {
|
|
|
120
120
|
tabLabel?: string;
|
|
121
121
|
editAble?: boolean;
|
|
122
122
|
showAdd?: boolean;
|
|
123
|
+
/* 是否启用折叠 */
|
|
124
|
+
collapsible?: boolean;
|
|
125
|
+
/** 是否默认折叠 */
|
|
126
|
+
defaultCollapsed?: boolean
|
|
123
127
|
lazyErrorMark?: boolean;
|
|
124
128
|
forceRender?: boolean;
|
|
125
129
|
/* 是否保持连续编号 */
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
/** 是否默认折叠 */
|
|
6
|
+
defaultCollapsed?: boolean
|
|
7
|
+
title?: string
|
|
8
|
+
/** 是否可以折叠 */
|
|
9
|
+
collapsible?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
13
|
+
title: undefined,
|
|
14
|
+
defaultCollapsed: false,
|
|
15
|
+
collapsible: false,
|
|
16
|
+
})
|
|
17
|
+
const slots = defineSlots<{
|
|
18
|
+
title: () => any
|
|
19
|
+
}>()
|
|
20
|
+
const activeKey = ref(props.defaultCollapsed ? [] : ['content'])
|
|
21
|
+
defineExpose({
|
|
22
|
+
collapse: () => {
|
|
23
|
+
activeKey.value = []
|
|
24
|
+
},
|
|
25
|
+
expand: () => {
|
|
26
|
+
activeKey.value = ['content']
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<a-collapse
|
|
33
|
+
v-if="collapsible"
|
|
34
|
+
v-model:active-key="activeKey"
|
|
35
|
+
class="collapsible-card"
|
|
36
|
+
>
|
|
37
|
+
<a-collapse-panel key="content" force-render :header="title">
|
|
38
|
+
<template v-if="slots.title" #header>
|
|
39
|
+
<slot name="title" />
|
|
40
|
+
</template>
|
|
41
|
+
<slot />
|
|
42
|
+
</a-collapse-panel>
|
|
43
|
+
</a-collapse>
|
|
44
|
+
<a-card v-else size="small" :title="title">
|
|
45
|
+
<template v-if="slots.title" #title>
|
|
46
|
+
<slot name="title" />
|
|
47
|
+
</template>
|
|
48
|
+
<slot />
|
|
49
|
+
</a-card>
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<style scoped lang="scss">
|
|
53
|
+
//样式改成card样式
|
|
54
|
+
.collapsible-card {
|
|
55
|
+
background-color: #fff;
|
|
56
|
+
border-color: #f0f0f0;
|
|
57
|
+
:deep(.ant-collapse-header) {
|
|
58
|
+
padding: 0 12px;
|
|
59
|
+
min-height: 38px;
|
|
60
|
+
display: flex;
|
|
61
|
+
align-items: center;
|
|
62
|
+
font-weight: 600;
|
|
63
|
+
}
|
|
64
|
+
:deep(.ant-collapse-content) {
|
|
65
|
+
border-color: #f0f0f0;
|
|
66
|
+
.ant-collapse-content-box {
|
|
67
|
+
padding: var(--collapsible-card-body-padding, 12px);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
:deep(.ant-collapse-item) {
|
|
71
|
+
border-color: #f0f0f0;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
</style>
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import { v4 as uuidv4 } from 'uuid';
|
|
22
22
|
import { antFormatters } from '@/utils/AFormatters';
|
|
23
23
|
import { getCanvasTableDefaults } from '@/utils/config';
|
|
24
|
+
import { watchPreviousDeep } from '@/utils/core';
|
|
24
25
|
|
|
25
26
|
const emit = defineEmits<{
|
|
26
27
|
(e: 'change', value: any[]): void; // 需要默认实现change,不能动态绑定
|
|
@@ -197,7 +198,7 @@
|
|
|
197
198
|
},
|
|
198
199
|
{ deep: true },
|
|
199
200
|
);
|
|
200
|
-
|
|
201
|
+
watchPreviousDeep(
|
|
201
202
|
() => props.columns,
|
|
202
203
|
(newValue, oldValue) => {
|
|
203
204
|
if (!isEqual(newValue, oldValue)) {
|
|
@@ -1,46 +1,50 @@
|
|
|
1
1
|
<script setup lang="ts" generic="T extends Recordable = Recordable">
|
|
2
|
-
import type { PFormItemProps } from '#/antProxy'
|
|
3
|
-
import { defaultItemResponsive } from '@/utils/core';
|
|
4
|
-
import RenderAntItem from '@/components/RenderAntItem';
|
|
5
|
-
import RenderItemSlots from '@/components/RenderItemSlots';
|
|
6
|
-
import { InfoCircleOutlined } from '@ant-design/icons-vue'
|
|
7
|
-
import { v4 as uuid_v4 } from 'uuid'
|
|
8
|
-
import { ref
|
|
9
|
-
import { isEqual,debounce, isFunction, omit } from 'xe-utils'
|
|
2
|
+
import type { PFormItemProps } from '#/antProxy';
|
|
3
|
+
import { defaultItemResponsive, watchPreviousDeep } from '@/utils/core';
|
|
4
|
+
import RenderAntItem from '@/components/RenderAntItem';
|
|
5
|
+
import RenderItemSlots from '@/components/RenderItemSlots';
|
|
6
|
+
import { InfoCircleOutlined } from '@ant-design/icons-vue';
|
|
7
|
+
import { v4 as uuid_v4 } from 'uuid';
|
|
8
|
+
import { ref } from 'vue';
|
|
9
|
+
import { isEqual, debounce, isFunction, omit } from 'xe-utils';
|
|
10
10
|
|
|
11
|
-
const props = defineProps<{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}>()
|
|
15
|
-
const emit = defineEmits<{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}>()
|
|
19
|
-
const hangOut = ref(false)
|
|
20
|
-
const renderFormKey = ref(uuid_v4())
|
|
21
|
-
const handleDelayTrigger = (cusFields?: string | string[], time?: number) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
const handleTrigger = (cusFields?: string | string[]) => {
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
const resetFormData = () => {
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
const refreshCol = () => {
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
const debounceRefreshCol = debounce(refreshCol, 100)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
11
|
+
const props = defineProps<{
|
|
12
|
+
item: PFormItemProps<T>;
|
|
13
|
+
formData: T;
|
|
14
|
+
}>();
|
|
15
|
+
const emit = defineEmits<{
|
|
16
|
+
(e: 'trigger', cusFields?: string | string[]): void;
|
|
17
|
+
(e: 'reset'): void;
|
|
18
|
+
}>();
|
|
19
|
+
const hangOut = ref(false);
|
|
20
|
+
const renderFormKey = ref(uuid_v4());
|
|
21
|
+
const handleDelayTrigger = (cusFields?: string | string[], time?: number) => {
|
|
22
|
+
const delayTime = time ?? 222;
|
|
23
|
+
hangOut.value = true;
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
hangOut.value = false;
|
|
26
|
+
emit('trigger', cusFields);
|
|
27
|
+
}, delayTime);
|
|
28
|
+
};
|
|
29
|
+
const handleTrigger = (cusFields?: string | string[]) => {
|
|
30
|
+
emit('trigger', cusFields);
|
|
31
|
+
};
|
|
32
|
+
const resetFormData = () => {
|
|
33
|
+
emit('reset');
|
|
34
|
+
};
|
|
35
|
+
const refreshCol = () => {
|
|
36
|
+
renderFormKey.value = uuid_v4();
|
|
37
|
+
};
|
|
38
|
+
const debounceRefreshCol = debounce(refreshCol, 100);
|
|
39
|
+
watchPreviousDeep(
|
|
40
|
+
() => props.item,
|
|
41
|
+
(cur, old) => {
|
|
42
|
+
if (!isEqual(cur, old)) {
|
|
43
|
+
debounceRefreshCol();
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{ deep: true },
|
|
47
|
+
);
|
|
44
48
|
</script>
|
|
45
49
|
|
|
46
50
|
<template>
|
|
@@ -58,7 +62,18 @@ watch(() => props.item, (cur, old) => {
|
|
|
58
62
|
:label="item.title"
|
|
59
63
|
:name="item.field"
|
|
60
64
|
:wrapper-col="item.wrapperCol ?? (item.title ? undefined : { span: 24 })"
|
|
61
|
-
v-bind="
|
|
65
|
+
v-bind="
|
|
66
|
+
omit(item, [
|
|
67
|
+
'field',
|
|
68
|
+
'title',
|
|
69
|
+
'span',
|
|
70
|
+
'col',
|
|
71
|
+
'wrapperCol',
|
|
72
|
+
'itemRender',
|
|
73
|
+
'forceRequired',
|
|
74
|
+
'tooltip',
|
|
75
|
+
])
|
|
76
|
+
"
|
|
62
77
|
>
|
|
63
78
|
<template v-if="item.slots?.title" #label>
|
|
64
79
|
<component :is="item.slots.title" />
|
|
@@ -82,7 +97,10 @@ watch(() => props.item, (cur, old) => {
|
|
|
82
97
|
/>
|
|
83
98
|
<span v-else />
|
|
84
99
|
<template v-if="item.tooltipConfig" #tooltip>
|
|
85
|
-
<a-tooltip
|
|
100
|
+
<a-tooltip
|
|
101
|
+
v-if="isFunction(item.tooltipConfig.title)"
|
|
102
|
+
v-bind="omit(item.tooltipConfig, ['title'])"
|
|
103
|
+
>
|
|
86
104
|
<info-circle-outlined class="cursor-pointer py-4 px-2" />
|
|
87
105
|
<template #title>
|
|
88
106
|
<div v-html="item.tooltipConfig.title()" />
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
import { valued } from '@/utils/is';
|
|
20
20
|
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
|
|
21
21
|
import { $warning } from '@/hooks/useMessage';
|
|
22
|
+
import CollapseCard from './CollapseCard.vue';
|
|
22
23
|
|
|
23
24
|
const useForm = Form.useForm;
|
|
24
25
|
const tabsRef = ref<InstanceType<typeof Tabs>>();
|
|
25
26
|
const props = defineProps<PFormGroupProps<F>>();
|
|
26
|
-
const rootRef = ref<InstanceType<typeof
|
|
27
|
+
const rootRef = ref<InstanceType<typeof CollapseCard>>();
|
|
27
28
|
const model = defineModel({
|
|
28
29
|
type: Array as PropType<Partial<F & { __index: number }>[]>,
|
|
29
30
|
default: () => [],
|
|
@@ -52,7 +53,7 @@
|
|
|
52
53
|
{ content: '复制', code: 'copy' },
|
|
53
54
|
{ content: '删除', code: 'delete' },
|
|
54
55
|
];
|
|
55
|
-
const getPopupContainer = (el) =>
|
|
56
|
+
const getPopupContainer = (el: HTMLElement) =>
|
|
56
57
|
el?.parentElement?.parentElement?.parentElement?.parentElement?.parentElement?.parentElement ??
|
|
57
58
|
rootRef.value?.$el ??
|
|
58
59
|
document.body;
|
|
@@ -146,6 +147,12 @@
|
|
|
146
147
|
}
|
|
147
148
|
});
|
|
148
149
|
defineExpose({
|
|
150
|
+
collapse: () => {
|
|
151
|
+
rootRef.value?.collapse?.();
|
|
152
|
+
},
|
|
153
|
+
expand: () => {
|
|
154
|
+
rootRef.value?.expand?.();
|
|
155
|
+
},
|
|
149
156
|
activeKey: computed(() => activeKey.value),
|
|
150
157
|
setActiveKey,
|
|
151
158
|
validateAll: () => {
|
|
@@ -227,7 +234,7 @@
|
|
|
227
234
|
});
|
|
228
235
|
</script>
|
|
229
236
|
<template>
|
|
230
|
-
<
|
|
237
|
+
<collapse-card ref="rootRef" :title="title" size="small" :collapsible="collapsible" :default-collapsed="defaultCollapsed">
|
|
231
238
|
<a-spin v-if="loading" class="w-full" />
|
|
232
239
|
<a-tabs
|
|
233
240
|
v-else
|
|
@@ -281,5 +288,5 @@
|
|
|
281
288
|
/>
|
|
282
289
|
</a-tab-pane>
|
|
283
290
|
</a-tabs>
|
|
284
|
-
</
|
|
291
|
+
</collapse-card>
|
|
285
292
|
</template>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ColumnProps, Responsive } from '#/antProxy';
|
|
2
2
|
import { TableColumnGroupType, TableColumnType } from 'ant-design-vue';
|
|
3
|
-
import { isArray, isNumber, omit, zipObject } from 'xe-utils';
|
|
3
|
+
import { clone, isArray, isNumber, omit, zipObject } from 'xe-utils';
|
|
4
4
|
import { valued } from '@/utils/is';
|
|
5
|
+
import { toValue, watch, WatchCallback, WatchOptions, WatchSource } from 'vue';
|
|
5
6
|
|
|
6
7
|
export const cleanCol = (col: ColumnProps): TableColumnType | TableColumnGroupType<Recordable> => {
|
|
7
8
|
return {
|
|
@@ -50,3 +51,23 @@ export const getButtonResponsive = (itemResponsive: number | Responsive[]) => {
|
|
|
50
51
|
),
|
|
51
52
|
);
|
|
52
53
|
};
|
|
54
|
+
|
|
55
|
+
export function watchPreviousDeep<T extends object>(
|
|
56
|
+
source: WatchSource<T>,
|
|
57
|
+
cb: (value: T, oldValue: T, onCleanup: () => void) => void,
|
|
58
|
+
options?: WatchOptions,
|
|
59
|
+
) {
|
|
60
|
+
const val = toValue(source);
|
|
61
|
+
if (typeof val !== 'object' || val === null) {
|
|
62
|
+
return watch(source, cb as WatchCallback<T>, options);
|
|
63
|
+
}
|
|
64
|
+
let previousValue = clone(val) as T;
|
|
65
|
+
return watch(
|
|
66
|
+
source,
|
|
67
|
+
(crtValue, _, onCleanup) => {
|
|
68
|
+
cb(crtValue as T, previousValue, onCleanup as () => void);
|
|
69
|
+
previousValue = clone(crtValue) as T;
|
|
70
|
+
},
|
|
71
|
+
options,
|
|
72
|
+
);
|
|
73
|
+
}
|