@peng_kai/kit 0.2.27 → 0.2.29
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/admin/components/filter/src/FilterDrawer.vue +153 -153
- package/admin/components/permission-tree/PermissionTree.vue +65 -78
- package/admin/components/permission-tree/index.ts +1 -1
- package/admin/components/scroll-nav/index.ts +1 -1
- package/admin/components/text/src/Duration.vue +26 -26
- package/admin/components/text/src/createTagGetter.ts +13 -13
- package/admin/route-guards/index.ts +3 -3
- package/admin/route-guards/pageProgress.ts +27 -27
- package/admin/styles/globalCover.scss +54 -54
- package/antd/directives/formLabelAlign.ts +36 -36
- package/package.json +95 -95
- package/stylelint.config.cjs +7 -7
- package/vue/components/infinite-query/index.ts +1 -1
- package/vue/components/infinite-query/src/useCreateTrigger.ts +39 -39
|
@@ -1,153 +1,153 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import { computed, ref } from 'vue';
|
|
3
|
-
import { Button as AButton, Drawer as ADrawer, Dropdown as ADropdown } from 'ant-design-vue';
|
|
4
|
-
|
|
5
|
-
defineOptions({
|
|
6
|
-
inheritAttrs: false,
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
const props = withDefaults(defineProps<{
|
|
10
|
-
loading?: boolean
|
|
11
|
-
filterQuery?: any
|
|
12
|
-
filterParams?: any
|
|
13
|
-
filterForm?: any
|
|
14
|
-
}>(), {
|
|
15
|
-
loading: undefined,
|
|
16
|
-
});
|
|
17
|
-
const emits = defineEmits<{
|
|
18
|
-
(e: 'filter'): void
|
|
19
|
-
(e: 'reset', value: number): void
|
|
20
|
-
}>();
|
|
21
|
-
|
|
22
|
-
const filterVisible = ref(false);
|
|
23
|
-
const loading = computed(() => {
|
|
24
|
-
const _loading1 = props.loading;
|
|
25
|
-
const _loading2: boolean = props.filterQuery?.isFetching.value;
|
|
26
|
-
|
|
27
|
-
if (_loading1 === undefined && _loading2 === undefined)
|
|
28
|
-
return false;
|
|
29
|
-
|
|
30
|
-
if (_loading1 !== undefined)
|
|
31
|
-
return _loading1;
|
|
32
|
-
|
|
33
|
-
return _loading2;
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
function filter() {
|
|
37
|
-
props.filterParams?.update?.();
|
|
38
|
-
emits('filter');
|
|
39
|
-
filterVisible.value = false;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function reset() {
|
|
43
|
-
props.filterForm?.$form.resetFields?.();
|
|
44
|
-
props.filterParams?.update?.();
|
|
45
|
-
emits('reset', 1);
|
|
46
|
-
filterVisible.value = false;
|
|
47
|
-
}
|
|
48
|
-
</script>
|
|
49
|
-
|
|
50
|
-
<template>
|
|
51
|
-
<div class="p-3 bg-$antd-colorBgContainer text-14px rounded-2" v-bind="$attrs">
|
|
52
|
-
<!-- .filter-params 为空时显示 .filter-params-tips -->
|
|
53
|
-
|
|
54
|
-
<div class="m--3 p-3" @click="filterVisible = true">
|
|
55
|
-
<div class="filter-params">
|
|
56
|
-
<slot name="params" />
|
|
57
|
-
</div>
|
|
58
|
-
<div class="filter-params-tips">
|
|
59
|
-
条件筛选,点击打开
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
<!-- 操作区 -->
|
|
64
|
-
<div v-if="$slots.actions || $slots.moreActions" class="actions">
|
|
65
|
-
<slot name="actions" />
|
|
66
|
-
|
|
67
|
-
<ADropdown v-if="$slots.moreActions" trigger="click" destroyPopupOnHide>
|
|
68
|
-
<AButton type="link" size="small">
|
|
69
|
-
更多
|
|
70
|
-
</AButton>
|
|
71
|
-
<template #overlay>
|
|
72
|
-
<slot name="moreActions" />
|
|
73
|
-
</template>
|
|
74
|
-
</ADropdown>
|
|
75
|
-
</div>
|
|
76
|
-
</div>
|
|
77
|
-
|
|
78
|
-
<ADrawer
|
|
79
|
-
v-model:open="filterVisible" class="filter-drawer" placement="bottom"
|
|
80
|
-
height="50vh"
|
|
81
|
-
>
|
|
82
|
-
<template #extra>
|
|
83
|
-
<AButton class="mr-3 my--3" :disabled="loading" @click="reset()">
|
|
84
|
-
重置
|
|
85
|
-
</AButton>
|
|
86
|
-
<AButton class="my--3" type="primary" :loading="loading" @click="filter()">
|
|
87
|
-
筛选
|
|
88
|
-
</AButton>
|
|
89
|
-
</template>
|
|
90
|
-
<template #default>
|
|
91
|
-
<slot />
|
|
92
|
-
</template>
|
|
93
|
-
</ADrawer>
|
|
94
|
-
</template>
|
|
95
|
-
|
|
96
|
-
<style scoped lang="scss">
|
|
97
|
-
.filter-params {
|
|
98
|
-
display: flex;
|
|
99
|
-
flex-wrap: wrap;
|
|
100
|
-
justify-content: flex-start;
|
|
101
|
-
gap: 5px 15px;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// .filter-params 为空时显示 .filter-params-tips
|
|
105
|
-
.filter-params-tips {
|
|
106
|
-
display: none;
|
|
107
|
-
color: theme('colors.gray.DEFAULT');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.filter-params:empty {
|
|
111
|
-
display: none;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.filter-params:empty + .filter-params-tips {
|
|
115
|
-
display: block;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.actions {
|
|
119
|
-
display: flex;
|
|
120
|
-
align-items: center;
|
|
121
|
-
justify-content: flex-end;
|
|
122
|
-
border-top: 1px solid var(--antd-colorBorderSecondary);
|
|
123
|
-
margin-top: 0.75rem;
|
|
124
|
-
padding-top: 0.75rem;
|
|
125
|
-
}
|
|
126
|
-
</style>
|
|
127
|
-
|
|
128
|
-
<style lang="scss">
|
|
129
|
-
.filter-drawer {
|
|
130
|
-
.ant-drawer-header {
|
|
131
|
-
padding: 16px;
|
|
132
|
-
|
|
133
|
-
.ant-drawer-close {
|
|
134
|
-
--expand: 5px;
|
|
135
|
-
|
|
136
|
-
padding: var(--expand);
|
|
137
|
-
margin: calc(var(--expand) * -1) var(--expand) calc(var(--expand) * -1) 0;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.ant-drawer-body {
|
|
142
|
-
padding: 16px;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.ant-form-item {
|
|
146
|
-
margin-bottom: 0;
|
|
147
|
-
|
|
148
|
-
.ant-form-item-label {
|
|
149
|
-
padding-bottom: 0;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
</style>
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed, ref } from 'vue';
|
|
3
|
+
import { Button as AButton, Drawer as ADrawer, Dropdown as ADropdown } from 'ant-design-vue';
|
|
4
|
+
|
|
5
|
+
defineOptions({
|
|
6
|
+
inheritAttrs: false,
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const props = withDefaults(defineProps<{
|
|
10
|
+
loading?: boolean
|
|
11
|
+
filterQuery?: any
|
|
12
|
+
filterParams?: any
|
|
13
|
+
filterForm?: any
|
|
14
|
+
}>(), {
|
|
15
|
+
loading: undefined,
|
|
16
|
+
});
|
|
17
|
+
const emits = defineEmits<{
|
|
18
|
+
(e: 'filter'): void
|
|
19
|
+
(e: 'reset', value: number): void
|
|
20
|
+
}>();
|
|
21
|
+
|
|
22
|
+
const filterVisible = ref(false);
|
|
23
|
+
const loading = computed(() => {
|
|
24
|
+
const _loading1 = props.loading;
|
|
25
|
+
const _loading2: boolean = props.filterQuery?.isFetching.value;
|
|
26
|
+
|
|
27
|
+
if (_loading1 === undefined && _loading2 === undefined)
|
|
28
|
+
return false;
|
|
29
|
+
|
|
30
|
+
if (_loading1 !== undefined)
|
|
31
|
+
return _loading1;
|
|
32
|
+
|
|
33
|
+
return _loading2;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
function filter() {
|
|
37
|
+
props.filterParams?.update?.();
|
|
38
|
+
emits('filter');
|
|
39
|
+
filterVisible.value = false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function reset() {
|
|
43
|
+
props.filterForm?.$form.resetFields?.();
|
|
44
|
+
props.filterParams?.update?.();
|
|
45
|
+
emits('reset', 1);
|
|
46
|
+
filterVisible.value = false;
|
|
47
|
+
}
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<div class="p-3 bg-$antd-colorBgContainer text-14px rounded-2" v-bind="$attrs">
|
|
52
|
+
<!-- .filter-params 为空时显示 .filter-params-tips -->
|
|
53
|
+
|
|
54
|
+
<div class="m--3 p-3" @click="filterVisible = true">
|
|
55
|
+
<div class="filter-params">
|
|
56
|
+
<slot name="params" />
|
|
57
|
+
</div>
|
|
58
|
+
<div class="filter-params-tips">
|
|
59
|
+
条件筛选,点击打开
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<!-- 操作区 -->
|
|
64
|
+
<div v-if="$slots.actions || $slots.moreActions" class="actions">
|
|
65
|
+
<slot name="actions" />
|
|
66
|
+
|
|
67
|
+
<ADropdown v-if="$slots.moreActions" trigger="click" destroyPopupOnHide>
|
|
68
|
+
<AButton type="link" size="small">
|
|
69
|
+
更多
|
|
70
|
+
</AButton>
|
|
71
|
+
<template #overlay>
|
|
72
|
+
<slot name="moreActions" />
|
|
73
|
+
</template>
|
|
74
|
+
</ADropdown>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<ADrawer
|
|
79
|
+
v-model:open="filterVisible" class="filter-drawer" placement="bottom"
|
|
80
|
+
height="50vh"
|
|
81
|
+
>
|
|
82
|
+
<template #extra>
|
|
83
|
+
<AButton class="mr-3 my--3" :disabled="loading" @click="reset()">
|
|
84
|
+
重置
|
|
85
|
+
</AButton>
|
|
86
|
+
<AButton class="my--3" type="primary" :loading="loading" @click="filter()">
|
|
87
|
+
筛选
|
|
88
|
+
</AButton>
|
|
89
|
+
</template>
|
|
90
|
+
<template #default>
|
|
91
|
+
<slot />
|
|
92
|
+
</template>
|
|
93
|
+
</ADrawer>
|
|
94
|
+
</template>
|
|
95
|
+
|
|
96
|
+
<style scoped lang="scss">
|
|
97
|
+
.filter-params {
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-wrap: wrap;
|
|
100
|
+
justify-content: flex-start;
|
|
101
|
+
gap: 5px 15px;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// .filter-params 为空时显示 .filter-params-tips
|
|
105
|
+
.filter-params-tips {
|
|
106
|
+
display: none;
|
|
107
|
+
color: theme('colors.gray.DEFAULT');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.filter-params:empty {
|
|
111
|
+
display: none;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.filter-params:empty + .filter-params-tips {
|
|
115
|
+
display: block;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.actions {
|
|
119
|
+
display: flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
justify-content: flex-end;
|
|
122
|
+
border-top: 1px solid var(--antd-colorBorderSecondary);
|
|
123
|
+
margin-top: 0.75rem;
|
|
124
|
+
padding-top: 0.75rem;
|
|
125
|
+
}
|
|
126
|
+
</style>
|
|
127
|
+
|
|
128
|
+
<style lang="scss">
|
|
129
|
+
.filter-drawer {
|
|
130
|
+
.ant-drawer-header {
|
|
131
|
+
padding: 16px;
|
|
132
|
+
|
|
133
|
+
.ant-drawer-close {
|
|
134
|
+
--expand: 5px;
|
|
135
|
+
|
|
136
|
+
padding: var(--expand);
|
|
137
|
+
margin: calc(var(--expand) * -1) var(--expand) calc(var(--expand) * -1) 0;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.ant-drawer-body {
|
|
142
|
+
padding: 16px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.ant-form-item {
|
|
146
|
+
margin-bottom: 0;
|
|
147
|
+
|
|
148
|
+
.ant-form-item-label {
|
|
149
|
+
padding-bottom: 0;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Checkbox } from 'ant-design-vue';
|
|
2
|
+
import { Checkbox, FormItemRest } from 'ant-design-vue';
|
|
3
3
|
import { computed, triggerRef, watch } from 'vue';
|
|
4
4
|
|
|
5
5
|
interface TTree {
|
|
@@ -9,19 +9,6 @@ interface TTree {
|
|
|
9
9
|
children?: TTree[]
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function treeToIds(tree: TTree[]) {
|
|
13
|
-
const ids = [] as number[];
|
|
14
|
-
|
|
15
|
-
const isCheckedFn = (node: TTree) => {
|
|
16
|
-
node.checked && ids.push(node.id);
|
|
17
|
-
node.children?.length && node.children.forEach(isCheckedFn);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
tree.forEach(isCheckedFn);
|
|
21
|
-
|
|
22
|
-
return ids;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
12
|
function treeToTable(tree: TTree[]) {
|
|
26
13
|
interface TD {
|
|
27
14
|
id: number
|
|
@@ -79,47 +66,36 @@ function treeToStates(tree: TTree[]) {
|
|
|
79
66
|
|
|
80
67
|
tree.forEach(assId);
|
|
81
68
|
|
|
82
|
-
// for (const id in ids) {
|
|
83
|
-
// const state = states[id];
|
|
84
|
-
// state.indet = isIndet(state.children.map(cid => states[cid].checked));
|
|
85
|
-
// state.children.forEach(cid => states[cid].checked = state.checked);
|
|
86
|
-
// [...state.parents].reverse().forEach((pid) => {
|
|
87
|
-
// const checks = states[pid].children.map(cid => states[cid].checked);
|
|
88
|
-
// state.indet = isIndet(checks);
|
|
89
|
-
// state.checked = checks.every(checked => checked);
|
|
90
|
-
// });
|
|
91
|
-
// }
|
|
92
|
-
|
|
93
|
-
// Object.keys(states)
|
|
94
|
-
// [...ids].forEach((id) => {
|
|
95
|
-
// const state = states[id];
|
|
96
|
-
// state.checked = true;
|
|
97
|
-
// state.children.forEach((cid) => {
|
|
98
|
-
// states[cid].checked = true;
|
|
99
|
-
// states[cid].indet = false;
|
|
100
|
-
// });
|
|
101
|
-
// });
|
|
102
|
-
|
|
103
69
|
return states;
|
|
104
70
|
}
|
|
105
71
|
|
|
106
72
|
function updateStates(states: ReturnType<typeof treeToStates>, id: number, checked: boolean) {
|
|
107
73
|
const state = states[id];
|
|
74
|
+
|
|
75
|
+
if (!state)
|
|
76
|
+
return;
|
|
77
|
+
|
|
108
78
|
state.checked = checked;
|
|
109
79
|
state.indet = false;
|
|
110
80
|
state.children.forEach((cid) => {
|
|
111
|
-
states[cid]
|
|
112
|
-
|
|
81
|
+
const cState = states[cid];
|
|
82
|
+
if (cState) {
|
|
83
|
+
cState.checked = checked;
|
|
84
|
+
cState.indet = false;
|
|
85
|
+
}
|
|
113
86
|
});
|
|
114
|
-
[...state.parents].
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
87
|
+
[...state.parents].forEach((pid) => {
|
|
88
|
+
const pState = states[pid];
|
|
89
|
+
if (pState) {
|
|
90
|
+
const checks = pState.children.map(cid => states[cid]?.checked);
|
|
91
|
+
pState.indet = isIndet(checks);
|
|
92
|
+
pState.checked = checks.every(checked => checked);
|
|
93
|
+
}
|
|
118
94
|
});
|
|
119
95
|
}
|
|
120
96
|
|
|
121
97
|
function statesToIds(states: ReturnType<typeof treeToStates>) {
|
|
122
|
-
return Object.keys(states).map(Number).filter(id => states[id]
|
|
98
|
+
return Object.keys(states).map(Number).filter(id => states[id]?.checked);
|
|
123
99
|
}
|
|
124
100
|
|
|
125
101
|
function findAllParents(tree: any[], id: number, path: any[] = []): any[] | undefined {
|
|
@@ -157,60 +133,71 @@ function isIndet(arr: boolean[]) {
|
|
|
157
133
|
|
|
158
134
|
<script setup lang="ts">
|
|
159
135
|
const props = defineProps<{
|
|
160
|
-
treeData: TTree[]
|
|
136
|
+
treeData: TTree[] | null | undefined
|
|
161
137
|
}>();
|
|
162
138
|
const ids = defineModel<number[]>('value', { default: [] });
|
|
163
|
-
const tableData = computed(() => treeToTable(props.treeData));
|
|
164
|
-
const stateMap = computed(() => treeToStates(props.treeData));
|
|
139
|
+
const tableData = computed(() => props.treeData && treeToTable(props.treeData));
|
|
140
|
+
const stateMap = computed(() => props.treeData && treeToStates(props.treeData));
|
|
165
141
|
|
|
166
142
|
watch(ids, (newV, oldV) => {
|
|
167
|
-
if (newV === oldV)
|
|
143
|
+
if (newV === oldV || !stateMap.value)
|
|
168
144
|
return;
|
|
169
145
|
|
|
170
|
-
newV.forEach(id => updateStates(stateMap.value
|
|
146
|
+
newV.forEach(id => updateStates(stateMap.value!, id, true));
|
|
171
147
|
triggerRef(stateMap);
|
|
172
148
|
}, { immediate: true });
|
|
173
149
|
|
|
150
|
+
watch(stateMap, (newV) => {
|
|
151
|
+
if (newV) {
|
|
152
|
+
ids.value.forEach(id => updateStates(newV, id, true));
|
|
153
|
+
triggerRef(stateMap);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
174
157
|
function onCheckChange(id: number) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
158
|
+
if (stateMap.value) {
|
|
159
|
+
const checked = !ids.value.includes(id);
|
|
160
|
+
updateStates(stateMap.value, id, checked);
|
|
161
|
+
ids.value = statesToIds(stateMap.value);
|
|
162
|
+
}
|
|
178
163
|
}
|
|
179
164
|
</script>
|
|
180
165
|
|
|
181
166
|
<template>
|
|
182
167
|
<table class="w-full border-collapse border-$antd-colorBorderSecondary" border>
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
<
|
|
196
|
-
:checked="stateMap[row[1].id].indet ? false : stateMap[row[1].id].checked"
|
|
197
|
-
:indeterminate="stateMap[row[1].id].indet" @change="onCheckChange(row[1].id)"
|
|
198
|
-
>
|
|
199
|
-
{{ row[1].label }}
|
|
200
|
-
</Checkbox>
|
|
201
|
-
</td>
|
|
202
|
-
<!-- 功能 -->
|
|
203
|
-
<td v-if="row[2]" class="px-[1em] py-0.5em">
|
|
204
|
-
<div class="feat-list">
|
|
168
|
+
<FormItemRest>
|
|
169
|
+
<tr v-for="(row, ri) of tableData" :key="ri">
|
|
170
|
+
<!-- 模块 -->
|
|
171
|
+
<td v-if="row[0]" class="w-[6em] px-[1em] py-0.5em" :rowspan="row[0].span">
|
|
172
|
+
<Checkbox
|
|
173
|
+
:checked="stateMap?.[row[0].id].indet ? false : stateMap?.[row[0].id].checked"
|
|
174
|
+
:indeterminate="stateMap?.[row[0].id].indet" @change="onCheckChange(row[0].id)"
|
|
175
|
+
>
|
|
176
|
+
{{ row[0].label }}{{ row[0].id }}
|
|
177
|
+
</Checkbox>
|
|
178
|
+
</td>
|
|
179
|
+
<!-- 页面 -->
|
|
180
|
+
<td v-if="row[1]" class="w-[9em] px-[1em] py-0.5em">
|
|
205
181
|
<Checkbox
|
|
206
|
-
|
|
207
|
-
@change="onCheckChange(
|
|
182
|
+
:checked="stateMap?.[row[1].id].indet ? false : stateMap?.[row[1].id].checked"
|
|
183
|
+
:indeterminate="stateMap?.[row[1].id].indet" @change="onCheckChange(row[1].id)"
|
|
208
184
|
>
|
|
209
|
-
{{
|
|
185
|
+
{{ row[1].label }} {{ row[1].id }}
|
|
210
186
|
</Checkbox>
|
|
211
|
-
</
|
|
212
|
-
|
|
213
|
-
|
|
187
|
+
</td>
|
|
188
|
+
<!-- 功能 -->
|
|
189
|
+
<td v-if="row[2]" class="px-[1em] py-0.5em">
|
|
190
|
+
<div class="feat-list">
|
|
191
|
+
<Checkbox
|
|
192
|
+
v-for="fItem of row[2]" :key="fItem?.id" :checked="stateMap?.[fItem.id].checked"
|
|
193
|
+
@change="onCheckChange(fItem.id)"
|
|
194
|
+
>
|
|
195
|
+
{{ fItem.label }} {{ fItem.id }}
|
|
196
|
+
</Checkbox>
|
|
197
|
+
</div>
|
|
198
|
+
</td>
|
|
199
|
+
</tr>
|
|
200
|
+
</FormItemRest>
|
|
214
201
|
</table>
|
|
215
202
|
</template>
|
|
216
203
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as PermissionTreeCheckbox
|
|
1
|
+
export { default as PermissionTreeCheckbox } from './PermissionTree.vue';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as ScrollNav } from './src/ScrollNav.vue';
|
|
1
|
+
export { default as ScrollNav } from './src/ScrollNav.vue';
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue';
|
|
3
|
-
|
|
4
|
-
const props = defineProps<{
|
|
5
|
-
seconds: number
|
|
6
|
-
}>();
|
|
7
|
-
|
|
8
|
-
const formattedDuration = computed(() => {
|
|
9
|
-
const days = Math.floor(props.seconds / (3600 * 24));
|
|
10
|
-
const hours = Math.floor((props.seconds % (3600 * 24)) / 3600);
|
|
11
|
-
const minutes = Math.floor((props.seconds % 3600) / 60);
|
|
12
|
-
const seconds = props.seconds % 60;
|
|
13
|
-
let formattedDuration = '';
|
|
14
|
-
|
|
15
|
-
days >= 1 && (formattedDuration += `${Math.floor(days)}天 `);
|
|
16
|
-
hours >= 1 && (formattedDuration += `${Math.floor(hours)}小时 `);
|
|
17
|
-
minutes >= 1 && (formattedDuration += `${Math.floor(minutes)}分钟 `);
|
|
18
|
-
seconds >= 1 && (formattedDuration += `${Math.floor(seconds)}秒`);
|
|
19
|
-
|
|
20
|
-
return formattedDuration;
|
|
21
|
-
});
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<template>
|
|
25
|
-
<span>{{ formattedDuration }}</span>
|
|
26
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
seconds: number
|
|
6
|
+
}>();
|
|
7
|
+
|
|
8
|
+
const formattedDuration = computed(() => {
|
|
9
|
+
const days = Math.floor(props.seconds / (3600 * 24));
|
|
10
|
+
const hours = Math.floor((props.seconds % (3600 * 24)) / 3600);
|
|
11
|
+
const minutes = Math.floor((props.seconds % 3600) / 60);
|
|
12
|
+
const seconds = props.seconds % 60;
|
|
13
|
+
let formattedDuration = '';
|
|
14
|
+
|
|
15
|
+
days >= 1 && (formattedDuration += `${Math.floor(days)}天 `);
|
|
16
|
+
hours >= 1 && (formattedDuration += `${Math.floor(hours)}小时 `);
|
|
17
|
+
minutes >= 1 && (formattedDuration += `${Math.floor(minutes)}分钟 `);
|
|
18
|
+
seconds >= 1 && (formattedDuration += `${Math.floor(seconds)}秒`);
|
|
19
|
+
|
|
20
|
+
return formattedDuration;
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<span>{{ formattedDuration }}</span>
|
|
26
|
+
</template>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { computed, h } from 'vue';
|
|
2
|
-
import { Tag as ATag } from 'ant-design-vue';
|
|
3
|
-
import type { TagProps } from 'ant-design-vue';
|
|
4
|
-
|
|
5
|
-
export function createTagGetter(typeMapFn: () => { [code: number | string]: [ text: string, color: TagProps['color'] ] }) {
|
|
6
|
-
const typeMap = computed(typeMapFn);
|
|
7
|
-
|
|
8
|
-
return (type: number | string) => {
|
|
9
|
-
const [text, color] = typeMap.value[type] ?? [];
|
|
10
|
-
|
|
11
|
-
return text ? h(ATag, { color }, () => text) : h('span', null, '-');
|
|
12
|
-
};
|
|
13
|
-
}
|
|
1
|
+
import { computed, h } from 'vue';
|
|
2
|
+
import { Tag as ATag } from 'ant-design-vue';
|
|
3
|
+
import type { TagProps } from 'ant-design-vue';
|
|
4
|
+
|
|
5
|
+
export function createTagGetter(typeMapFn: () => { [code: number | string]: [ text: string, color: TagProps['color'] ] }) {
|
|
6
|
+
const typeMap = computed(typeMapFn);
|
|
7
|
+
|
|
8
|
+
return (type: number | string) => {
|
|
9
|
+
const [text, color] = typeMap.value[type] ?? [];
|
|
10
|
+
|
|
11
|
+
return text ? h(ATag, { color }, () => text) : h('span', null, '-');
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { setupPageProgress } from './pageProgress';
|
|
2
|
-
export { setupPageTitle } from './pageTitle';
|
|
3
|
-
export { setupCollapseMenu } from './collapseMenu';
|
|
1
|
+
export { setupPageProgress } from './pageProgress';
|
|
2
|
+
export { setupPageTitle } from './pageTitle';
|
|
3
|
+
export { setupCollapseMenu } from './collapseMenu';
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import type { Router } from 'vue-router';
|
|
2
|
-
import { useStyleTag } from '@vueuse/core';
|
|
3
|
-
import NProgress from 'nprogress';
|
|
4
|
-
import 'nprogress/nprogress.css';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 用于显示页面跳转时,页面顶部进度条
|
|
8
|
-
*/
|
|
9
|
-
export function setupPageProgress(router: Router) {
|
|
10
|
-
NProgress.configure({ showSpinner: false });
|
|
11
|
-
useStyleTag(`
|
|
12
|
-
#nprogress .bar {
|
|
13
|
-
height: 3px;
|
|
14
|
-
background: var(--antd-colorPrimary);
|
|
15
|
-
}
|
|
16
|
-
#nprogress .peg {
|
|
17
|
-
box-shadow: 0 0 10px var(--antd-colorPrimary), 0 0 5px var(--antd-colorPrimary);
|
|
18
|
-
}
|
|
19
|
-
`);
|
|
20
|
-
|
|
21
|
-
router.beforeEach(() => {
|
|
22
|
-
NProgress.start();
|
|
23
|
-
});
|
|
24
|
-
router.afterEach(() => {
|
|
25
|
-
setTimeout(() => NProgress.done(), 200);
|
|
26
|
-
});
|
|
27
|
-
}
|
|
1
|
+
import type { Router } from 'vue-router';
|
|
2
|
+
import { useStyleTag } from '@vueuse/core';
|
|
3
|
+
import NProgress from 'nprogress';
|
|
4
|
+
import 'nprogress/nprogress.css';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 用于显示页面跳转时,页面顶部进度条
|
|
8
|
+
*/
|
|
9
|
+
export function setupPageProgress(router: Router) {
|
|
10
|
+
NProgress.configure({ showSpinner: false });
|
|
11
|
+
useStyleTag(`
|
|
12
|
+
#nprogress .bar {
|
|
13
|
+
height: 3px;
|
|
14
|
+
background: var(--antd-colorPrimary);
|
|
15
|
+
}
|
|
16
|
+
#nprogress .peg {
|
|
17
|
+
box-shadow: 0 0 10px var(--antd-colorPrimary), 0 0 5px var(--antd-colorPrimary);
|
|
18
|
+
}
|
|
19
|
+
`);
|
|
20
|
+
|
|
21
|
+
router.beforeEach(() => {
|
|
22
|
+
NProgress.start();
|
|
23
|
+
});
|
|
24
|
+
router.afterEach(() => {
|
|
25
|
+
setTimeout(() => NProgress.done(), 200);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
// table 组件头部圆角设为 0
|
|
3
|
-
.ant-table-wrapper {
|
|
4
|
-
.ant-table .ant-table-header,
|
|
5
|
-
table,
|
|
6
|
-
.ant-table-container table > thead > tr:first-child > *:first-child,
|
|
7
|
-
.ant-table-container table > thead > tr:first-child > *:last-child {
|
|
8
|
-
border-radius: 0;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.ant-pagination {
|
|
12
|
-
margin-bottom: 0;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// 隐藏在 sticky 模式下的滚动条
|
|
18
|
-
.ant-table-sticky-scroll {
|
|
19
|
-
display: none;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// 卡片
|
|
23
|
-
.ant-card .ant-card-actions > li > span {
|
|
24
|
-
cursor: inherit;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Tab 溢出出现下列框时
|
|
28
|
-
.ant-tabs-dropdown-menu-title-content {
|
|
29
|
-
display: flex;
|
|
30
|
-
align-items: center;
|
|
31
|
-
justify-content: space-between;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// 表格
|
|
35
|
-
.ant-table-wrapper {
|
|
36
|
-
.ant-table-row-expand-icon-collapsed::before {
|
|
37
|
-
height: 1.5px;
|
|
38
|
-
}
|
|
39
|
-
.ant-table-row-expand-icon-collapsed::after {
|
|
40
|
-
width: 1.5px;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.ant-drawer {
|
|
45
|
-
&:focus {
|
|
46
|
-
outline: none;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
&.ant-drawer-bottom .ant-drawer-content {
|
|
50
|
-
border-top-left-radius: 8px;
|
|
51
|
-
border-top-right-radius: 8px;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
1
|
+
:root {
|
|
2
|
+
// table 组件头部圆角设为 0
|
|
3
|
+
.ant-table-wrapper {
|
|
4
|
+
.ant-table .ant-table-header,
|
|
5
|
+
table,
|
|
6
|
+
.ant-table-container table > thead > tr:first-child > *:first-child,
|
|
7
|
+
.ant-table-container table > thead > tr:first-child > *:last-child {
|
|
8
|
+
border-radius: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.ant-pagination {
|
|
12
|
+
margin-bottom: 0;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
// 隐藏在 sticky 模式下的滚动条
|
|
18
|
+
.ant-table-sticky-scroll {
|
|
19
|
+
display: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 卡片
|
|
23
|
+
.ant-card .ant-card-actions > li > span {
|
|
24
|
+
cursor: inherit;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Tab 溢出出现下列框时
|
|
28
|
+
.ant-tabs-dropdown-menu-title-content {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: space-between;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 表格
|
|
35
|
+
.ant-table-wrapper {
|
|
36
|
+
.ant-table-row-expand-icon-collapsed::before {
|
|
37
|
+
height: 1.5px;
|
|
38
|
+
}
|
|
39
|
+
.ant-table-row-expand-icon-collapsed::after {
|
|
40
|
+
width: 1.5px;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.ant-drawer {
|
|
45
|
+
&:focus {
|
|
46
|
+
outline: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&.ant-drawer-bottom .ant-drawer-content {
|
|
50
|
+
border-top-left-radius: 8px;
|
|
51
|
+
border-top-right-radius: 8px;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import type { App } from 'vue';
|
|
2
|
-
|
|
3
|
-
export function formLabelAlign(app: App) {
|
|
4
|
-
const directiveName = 'antd-form-label-align';
|
|
5
|
-
const resizeObserverKey = `${directiveName}@resizeObserver`;
|
|
6
|
-
|
|
7
|
-
function init(el: HTMLElement) {
|
|
8
|
-
const labels = el.querySelectorAll('.ant-form-item .ant-form-item-label');
|
|
9
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
10
|
-
const widths = entries.map(e => e.borderBoxSize?.[0]?.inlineSize ?? 0);
|
|
11
|
-
const maxWidth = Math.max(...widths);
|
|
12
|
-
|
|
13
|
-
if (maxWidth <= 0)
|
|
14
|
-
return;
|
|
15
|
-
|
|
16
|
-
el.style.setProperty('--max-label-width', `${maxWidth}px`);
|
|
17
|
-
entries.forEach((e) => {
|
|
18
|
-
const target = e.target as HTMLElement;
|
|
19
|
-
target.style.setProperty('width', 'var(--max-label-width)');
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
Array.from(labels).forEach(label => resizeObserver.observe(label));
|
|
24
|
-
|
|
25
|
-
return resizeObserver;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
app.directive(directiveName, {
|
|
29
|
-
mounted(el: HTMLElement) {
|
|
30
|
-
(el as any)[resizeObserverKey] = init(el);
|
|
31
|
-
},
|
|
32
|
-
updated(el) {
|
|
33
|
-
(el as any)[resizeObserverKey] = init(el);
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
}
|
|
1
|
+
import type { App } from 'vue';
|
|
2
|
+
|
|
3
|
+
export function formLabelAlign(app: App) {
|
|
4
|
+
const directiveName = 'antd-form-label-align';
|
|
5
|
+
const resizeObserverKey = `${directiveName}@resizeObserver`;
|
|
6
|
+
|
|
7
|
+
function init(el: HTMLElement) {
|
|
8
|
+
const labels = el.querySelectorAll('.ant-form-item .ant-form-item-label');
|
|
9
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
10
|
+
const widths = entries.map(e => e.borderBoxSize?.[0]?.inlineSize ?? 0);
|
|
11
|
+
const maxWidth = Math.max(...widths);
|
|
12
|
+
|
|
13
|
+
if (maxWidth <= 0)
|
|
14
|
+
return;
|
|
15
|
+
|
|
16
|
+
el.style.setProperty('--max-label-width', `${maxWidth}px`);
|
|
17
|
+
entries.forEach((e) => {
|
|
18
|
+
const target = e.target as HTMLElement;
|
|
19
|
+
target.style.setProperty('width', 'var(--max-label-width)');
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
Array.from(labels).forEach(label => resizeObserver.observe(label));
|
|
24
|
+
|
|
25
|
+
return resizeObserver;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
app.directive(directiveName, {
|
|
29
|
+
mounted(el: HTMLElement) {
|
|
30
|
+
(el as any)[resizeObserverKey] = init(el);
|
|
31
|
+
},
|
|
32
|
+
updated(el) {
|
|
33
|
+
(el as any)[resizeObserverKey] = init(el);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
package/package.json
CHANGED
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@peng_kai/kit",
|
|
3
|
-
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
5
|
-
"description": "",
|
|
6
|
-
"author": "",
|
|
7
|
-
"license": "ISC",
|
|
8
|
-
"keywords": [],
|
|
9
|
-
"main": "index.js",
|
|
10
|
-
"scripts": {
|
|
11
|
-
"dev:js": "tsx ./admin/scripts/deploy.ts",
|
|
12
|
-
"lint": "eslint .",
|
|
13
|
-
"lint:fix": "eslint . --fix"
|
|
14
|
-
},
|
|
15
|
-
"peerDependencies": {
|
|
16
|
-
"ant-design-vue": "4.2.3",
|
|
17
|
-
"vue": "3.4.31",
|
|
18
|
-
"vue-router": "4.4.0"
|
|
19
|
-
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"@aws-sdk/client-s3": "^3.609.0",
|
|
22
|
-
"@aws-sdk/lib-storage": "^3.609.0",
|
|
23
|
-
"@babel/generator": "^7.24.7",
|
|
24
|
-
"@babel/parser": "^7.24.7",
|
|
25
|
-
"@babel/traverse": "^7.24.7",
|
|
26
|
-
"@babel/types": "^7.24.7",
|
|
27
|
-
"@ckeditor/ckeditor5-vue": "^5.1.0",
|
|
28
|
-
"@fingerprintjs/fingerprintjs": "^4.4.1",
|
|
29
|
-
"@tanstack/vue-query": "^5.49.1",
|
|
30
|
-
"@vueuse/components": "^10.11.0",
|
|
31
|
-
"@vueuse/core": "^10.11.0",
|
|
32
|
-
"@vueuse/router": "^10.11.0",
|
|
33
|
-
"a-calc": "^1.3.12",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"vue": "^
|
|
50
|
-
"vue-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"@ckeditor/ckeditor5-
|
|
55
|
-
"@ckeditor/ckeditor5-
|
|
56
|
-
"@ckeditor/ckeditor5-
|
|
57
|
-
"@ckeditor/ckeditor5-
|
|
58
|
-
"@ckeditor/ckeditor5-
|
|
59
|
-
"@ckeditor/ckeditor5-
|
|
60
|
-
"@ckeditor/ckeditor5-
|
|
61
|
-
"@ckeditor/ckeditor5-
|
|
62
|
-
"@ckeditor/ckeditor5-
|
|
63
|
-
"@ckeditor/ckeditor5-
|
|
64
|
-
"@ckeditor/ckeditor5-
|
|
65
|
-
"@ckeditor/ckeditor5-
|
|
66
|
-
"@ckeditor/ckeditor5-
|
|
67
|
-
"@ckeditor/ckeditor5-
|
|
68
|
-
"@ckeditor/ckeditor5-html-
|
|
69
|
-
"@ckeditor/ckeditor5-
|
|
70
|
-
"@ckeditor/ckeditor5-
|
|
71
|
-
"@ckeditor/ckeditor5-
|
|
72
|
-
"@ckeditor/ckeditor5-
|
|
73
|
-
"@ckeditor/ckeditor5-
|
|
74
|
-
"@ckeditor/ckeditor5-
|
|
75
|
-
"@ckeditor/ckeditor5-
|
|
76
|
-
"@ckeditor/ckeditor5-
|
|
77
|
-
"@ckeditor/ckeditor5-
|
|
78
|
-
"@ckeditor/ckeditor5-
|
|
79
|
-
"@ckeditor/ckeditor5-
|
|
80
|
-
"@ckeditor/ckeditor5-
|
|
81
|
-
"@ckeditor/ckeditor5-
|
|
82
|
-
"@ckeditor/ckeditor5-
|
|
83
|
-
"@ckeditor/ckeditor5-
|
|
84
|
-
"@
|
|
85
|
-
"@
|
|
86
|
-
"@types/
|
|
87
|
-
"@types/
|
|
88
|
-
"@types/
|
|
89
|
-
"@types/
|
|
90
|
-
"
|
|
91
|
-
"type-fest": "^4.21.0",
|
|
92
|
-
"typescript": "^5.5.3",
|
|
93
|
-
"vue-component-type-helpers": "^2.0.24"
|
|
94
|
-
}
|
|
95
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@peng_kai/kit",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.2.29",
|
|
5
|
+
"description": "",
|
|
6
|
+
"author": "",
|
|
7
|
+
"license": "ISC",
|
|
8
|
+
"keywords": [],
|
|
9
|
+
"main": "index.js",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"dev:js": "tsx ./admin/scripts/deploy.ts",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"lint:fix": "eslint . --fix"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"ant-design-vue": "4.2.3",
|
|
17
|
+
"vue": "3.4.31",
|
|
18
|
+
"vue-router": "4.4.0"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@aws-sdk/client-s3": "^3.609.0",
|
|
22
|
+
"@aws-sdk/lib-storage": "^3.609.0",
|
|
23
|
+
"@babel/generator": "^7.24.7",
|
|
24
|
+
"@babel/parser": "^7.24.7",
|
|
25
|
+
"@babel/traverse": "^7.24.7",
|
|
26
|
+
"@babel/types": "^7.24.7",
|
|
27
|
+
"@ckeditor/ckeditor5-vue": "^5.1.0",
|
|
28
|
+
"@fingerprintjs/fingerprintjs": "^4.4.1",
|
|
29
|
+
"@tanstack/vue-query": "^5.49.1",
|
|
30
|
+
"@vueuse/components": "^10.11.0",
|
|
31
|
+
"@vueuse/core": "^10.11.0",
|
|
32
|
+
"@vueuse/router": "^10.11.0",
|
|
33
|
+
"a-calc": "^1.3.12",
|
|
34
|
+
"archiver": "^7.0.1",
|
|
35
|
+
"axios": "^1.7.2",
|
|
36
|
+
"bignumber.js": "^9.1.2",
|
|
37
|
+
"chokidar": "^3.6.0",
|
|
38
|
+
"crypto-es": "^2.1.0",
|
|
39
|
+
"dayjs": "^1.11.11",
|
|
40
|
+
"echarts": "^5.4.3",
|
|
41
|
+
"execa": "^9.3.0",
|
|
42
|
+
"fast-glob": "^3.3.2",
|
|
43
|
+
"localstorage-slim": "^2.7.1",
|
|
44
|
+
"lodash-es": "^4.17.21",
|
|
45
|
+
"nprogress": "^0.2.0",
|
|
46
|
+
"pinia": "^2.1.7",
|
|
47
|
+
"tsx": "^4.16.00",
|
|
48
|
+
"vue": "^3.4.31",
|
|
49
|
+
"vue-i18n": "^9.13.1",
|
|
50
|
+
"vue-router": "^4.4.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@ckeditor/ckeditor5-adapter-ckfinder": "^41.1.0",
|
|
54
|
+
"@ckeditor/ckeditor5-alignment": "^41.1.0",
|
|
55
|
+
"@ckeditor/ckeditor5-autoformat": "^41.1.0",
|
|
56
|
+
"@ckeditor/ckeditor5-basic-styles": "^41.1.0",
|
|
57
|
+
"@ckeditor/ckeditor5-block-quote": "^41.1.0",
|
|
58
|
+
"@ckeditor/ckeditor5-build-classic": "^41.1.0",
|
|
59
|
+
"@ckeditor/ckeditor5-code-block": "^41.1.0",
|
|
60
|
+
"@ckeditor/ckeditor5-document-outline": "^41.1.0",
|
|
61
|
+
"@ckeditor/ckeditor5-editor-classic": "^41.1.0",
|
|
62
|
+
"@ckeditor/ckeditor5-essentials": "^41.1.0",
|
|
63
|
+
"@ckeditor/ckeditor5-font": "^41.1.0",
|
|
64
|
+
"@ckeditor/ckeditor5-heading": "^41.1.0",
|
|
65
|
+
"@ckeditor/ckeditor5-highlight": "^41.1.0",
|
|
66
|
+
"@ckeditor/ckeditor5-horizontal-line": "^41.1.0",
|
|
67
|
+
"@ckeditor/ckeditor5-html-embed": "^41.1.0",
|
|
68
|
+
"@ckeditor/ckeditor5-html-support": "^41.1.0",
|
|
69
|
+
"@ckeditor/ckeditor5-image": "^41.1.0",
|
|
70
|
+
"@ckeditor/ckeditor5-import-word": "^41.1.0",
|
|
71
|
+
"@ckeditor/ckeditor5-indent": "^41.1.0",
|
|
72
|
+
"@ckeditor/ckeditor5-link": "^41.1.0",
|
|
73
|
+
"@ckeditor/ckeditor5-list": "^41.1.0",
|
|
74
|
+
"@ckeditor/ckeditor5-media-embed": "^41.1.0",
|
|
75
|
+
"@ckeditor/ckeditor5-paragraph": "^41.1.0",
|
|
76
|
+
"@ckeditor/ckeditor5-remove-format": "^41.1.0",
|
|
77
|
+
"@ckeditor/ckeditor5-show-blocks": "^41.1.0",
|
|
78
|
+
"@ckeditor/ckeditor5-source-editing": "^41.1.0",
|
|
79
|
+
"@ckeditor/ckeditor5-table": "^41.1.0",
|
|
80
|
+
"@ckeditor/ckeditor5-theme-lark": "^41.1.0",
|
|
81
|
+
"@ckeditor/ckeditor5-typing": "^41.1.0",
|
|
82
|
+
"@ckeditor/ckeditor5-upload": "^41.1.0",
|
|
83
|
+
"@ckeditor/ckeditor5-word-count": "^41.1.0",
|
|
84
|
+
"@peng_kai/lint": "^0.1.0",
|
|
85
|
+
"@types/archiver": "^6.0.2",
|
|
86
|
+
"@types/crypto-js": "^4.2.2",
|
|
87
|
+
"@types/lodash-es": "^4.17.12",
|
|
88
|
+
"@types/node": "^18.19.39",
|
|
89
|
+
"@types/nprogress": "^0.2.3",
|
|
90
|
+
"ant-design-vue": "^4.2.3",
|
|
91
|
+
"type-fest": "^4.21.0",
|
|
92
|
+
"typescript": "^5.5.3",
|
|
93
|
+
"vue-component-type-helpers": "^2.0.24"
|
|
94
|
+
}
|
|
95
|
+
}
|
package/stylelint.config.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
// root: true,
|
|
3
|
-
extends: ['@peng_kai/lint/vue/stylelint_v2'],
|
|
4
|
-
rules: {
|
|
5
|
-
'custom-property-pattern': '(antd-([a-z][a-zA-Z0-9]+)*)|(([a-z][a-z0-9]*)(-[a-z0-9]+)*)',
|
|
6
|
-
},
|
|
7
|
-
};
|
|
1
|
+
module.exports = {
|
|
2
|
+
// root: true,
|
|
3
|
+
extends: ['@peng_kai/lint/vue/stylelint_v2'],
|
|
4
|
+
rules: {
|
|
5
|
+
'custom-property-pattern': '(antd-([a-z][a-zA-Z0-9]+)*)|(([a-z][a-z0-9]*)(-[a-z0-9]+)*)',
|
|
6
|
+
},
|
|
7
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as InfiniteQuery } from './src/InfiniteQuery.vue';
|
|
1
|
+
export { default as InfiniteQuery } from './src/InfiniteQuery.vue';
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { onUnmounted, watch } from 'vue';
|
|
2
|
-
import type { Ref } from 'vue';
|
|
3
|
-
import { useIntersectionObserver, useIntervalFn } from '@vueuse/core';
|
|
4
|
-
|
|
5
|
-
export function useCreateTrigger(containerEle: Ref<HTMLElement | undefined>, callback: Function, distance: string) {
|
|
6
|
-
const triggerEl = document.createElement('div');
|
|
7
|
-
|
|
8
|
-
Object.assign(triggerEl.style, {
|
|
9
|
-
position: 'relative',
|
|
10
|
-
zIndex: '5',
|
|
11
|
-
marginTop: `-${distance}`,
|
|
12
|
-
marginBottom: distance,
|
|
13
|
-
width: '5px',
|
|
14
|
-
height: '5px',
|
|
15
|
-
// background: 'red',
|
|
16
|
-
} satisfies Partial<CSSStyleDeclaration>);
|
|
17
|
-
|
|
18
|
-
useIntervalFn(() => {
|
|
19
|
-
const { transform } = triggerEl.style;
|
|
20
|
-
|
|
21
|
-
if (transform)
|
|
22
|
-
triggerEl.style.removeProperty('transform');
|
|
23
|
-
else triggerEl.style.setProperty('transform', 'translateX(-200%)');
|
|
24
|
-
}, 500);
|
|
25
|
-
|
|
26
|
-
useIntersectionObserver(triggerEl, ([entry]) => {
|
|
27
|
-
if (entry.isIntersecting)
|
|
28
|
-
callback();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
watch(containerEle, (ele) => {
|
|
32
|
-
if (ele)
|
|
33
|
-
ele.append(triggerEl);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
onUnmounted(() => {
|
|
37
|
-
triggerEl.remove();
|
|
38
|
-
});
|
|
39
|
-
}
|
|
1
|
+
import { onUnmounted, watch } from 'vue';
|
|
2
|
+
import type { Ref } from 'vue';
|
|
3
|
+
import { useIntersectionObserver, useIntervalFn } from '@vueuse/core';
|
|
4
|
+
|
|
5
|
+
export function useCreateTrigger(containerEle: Ref<HTMLElement | undefined>, callback: Function, distance: string) {
|
|
6
|
+
const triggerEl = document.createElement('div');
|
|
7
|
+
|
|
8
|
+
Object.assign(triggerEl.style, {
|
|
9
|
+
position: 'relative',
|
|
10
|
+
zIndex: '5',
|
|
11
|
+
marginTop: `-${distance}`,
|
|
12
|
+
marginBottom: distance,
|
|
13
|
+
width: '5px',
|
|
14
|
+
height: '5px',
|
|
15
|
+
// background: 'red',
|
|
16
|
+
} satisfies Partial<CSSStyleDeclaration>);
|
|
17
|
+
|
|
18
|
+
useIntervalFn(() => {
|
|
19
|
+
const { transform } = triggerEl.style;
|
|
20
|
+
|
|
21
|
+
if (transform)
|
|
22
|
+
triggerEl.style.removeProperty('transform');
|
|
23
|
+
else triggerEl.style.setProperty('transform', 'translateX(-200%)');
|
|
24
|
+
}, 500);
|
|
25
|
+
|
|
26
|
+
useIntersectionObserver(triggerEl, ([entry]) => {
|
|
27
|
+
if (entry.isIntersecting)
|
|
28
|
+
callback();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
watch(containerEle, (ele) => {
|
|
32
|
+
if (ele)
|
|
33
|
+
ele.append(triggerEl);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
onUnmounted(() => {
|
|
37
|
+
triggerEl.remove();
|
|
38
|
+
});
|
|
39
|
+
}
|