@peng_kai/kit 0.3.0-beta.10 → 0.3.0-beta.11

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.
@@ -1,13 +1,15 @@
1
1
  <script setup lang="ts">
2
- import { Button, Menu, MenuItem, Dropdown } from 'ant-design-vue';
2
+ import { Button, Menu, MenuItem, Dropdown, type TableColumnsType } from 'ant-design-vue';
3
3
  import { computed } from 'vue';
4
4
  import { onTtaTimeZone } from '../../date';
5
+ import { TableSettingModal } from './more/TableSetting.vue'
5
6
 
6
7
  const props = withDefaults(defineProps<{
7
8
  loading?: boolean
8
9
  filterQuery?: any
9
10
  filterParams?: any
10
11
  filterForm?: any
12
+ tableColumns?: TableColumnsType<any>
11
13
  }>(), {
12
14
  loading: undefined,
13
15
  });
@@ -40,6 +42,15 @@ function reset() {
40
42
  emits('reset');
41
43
  }
42
44
 
45
+ function openTableSettingModal() {
46
+ const tableColumns = props.tableColumns?.map((x: any) => ({
47
+ ...x,
48
+ title: typeof x.title === 'string' ? x.title : x.dataIndex || '',
49
+ })) || [];
50
+
51
+ TableSettingModal.open({ tableColumns });
52
+ }
53
+
43
54
  onTtaTimeZone(() => {
44
55
  setTimeout(() => {
45
56
  props.filterParams?.update?.(true);
@@ -62,11 +73,15 @@ onTtaTimeZone(() => {
62
73
  </Button>
63
74
  <template #overlay>
64
75
  <Menu>
65
- <MenuItem>设置表格</MenuItem>
76
+ <MenuItem v-if="props.tableColumns" @click="openTableSettingModal">
77
+ 设置表格
78
+ </MenuItem>
66
79
  </Menu>
67
80
  </template>
68
81
  </Dropdown>
69
82
  </slot>
83
+
84
+ <TableSettingModal.PresetComponent />
70
85
  </div>
71
86
  </template>
72
87
 
@@ -75,7 +90,7 @@ onTtaTimeZone(() => {
75
90
  :slotted(.filter-btn) {
76
91
  position: relative;
77
92
 
78
- .ant-btn-loading-icon{
93
+ .ant-btn-loading-icon {
79
94
  position: absolute;
80
95
  left: 50%;
81
96
  transform: translateX(-50%);
@@ -85,7 +100,7 @@ onTtaTimeZone(() => {
85
100
  margin-inline-end: 0 !important;
86
101
  }
87
102
 
88
- + span {
103
+ +span {
89
104
  visibility: hidden;
90
105
  }
91
106
  }
@@ -0,0 +1,63 @@
1
+ <script lang="ts">
2
+ import { Button, Switch, Divider, Select, type TableColumnsType } from 'ant-design-vue';
3
+ import { reactive, defineAsyncComponent, ref } from 'vue';
4
+ import { useDragAndDrop } from "fluid-dnd/vue";
5
+ import { useAntdModal } from '../../../../../antd/hooks/useAntdModal';
6
+
7
+ export const TableSettingModal = useAntdModal(
8
+ // eslint-disable-next-line import/no-self-import
9
+ defineAsyncComponent(() => import('./TableSetting.vue')),
10
+ {
11
+ title: '表格设置',
12
+ width: 500,
13
+ // footer: null,
14
+ centered: true,
15
+ maskClosable: false,
16
+ }
17
+ );
18
+
19
+ const showTypeOptions = [
20
+ { label: '显示', value: 'show' },
21
+ { label: '简略', value: 'simple' },
22
+ { label: '隐藏', value: 'hidden' },
23
+ ];
24
+ </script>
25
+
26
+ <script lang="ts" setup>
27
+ const props = defineProps<{
28
+ tableColumns: TableColumnsType<any>
29
+ }>();
30
+ const columnsConfig = ref(props.tableColumns.map((col: any) => ({
31
+ title: col.title as string,
32
+ dataIndex: col.dataIndex as string,
33
+ visible: col.visible !== false,
34
+ })));
35
+
36
+ const [$ctn] = useDragAndDrop(columnsConfig, {
37
+ handlerSelector: '.drag-handler',
38
+ draggingClass: 'op-50',
39
+ direction: 'vertical',
40
+ });
41
+ </script>
42
+
43
+ <template>
44
+ <div>
45
+ <div>
46
+ <Divider>列设置</Divider>
47
+ <div ref="$ctn">
48
+ <div v-for="(col, i) in columnsConfig" :key="col.dataIndex" :index="i" class="flex items-center gap-2 p-2 select-none">
49
+ <div class="drag-handler flex items-center justify-center cursor-move p-1 -m-2">
50
+ <i class="i-material-symbols:drag-indicator" />
51
+ </div>
52
+ <span class="mr-auto">{{ col.title }}</span>
53
+ <Select value="show" :options="showTypeOptions" />
54
+ <!-- <Switch checked-children="简略" un-checked-children="简略" />
55
+ <Switch checked-children="显示" un-checked-children="显示" />
56
+ <Button>上</Button>
57
+ <Button>下</Button> -->
58
+ </div>
59
+ </div>
60
+
61
+ </div>
62
+ </div>
63
+ </template>
@@ -8,7 +8,7 @@ const { arrivedState, measure } = useScroll($content);
8
8
  const contentCssVars = computed(() => {
9
9
  const {top: arrivedTop, bottom: arrivedBtm} = arrivedState;
10
10
  return {
11
- '--top-e': arrivedTop ? '0%' : '0',
11
+ '--top-e': arrivedTop ? '0%' : '5px',
12
12
  '--btm-s': arrivedBtm ? '100%' : '99.5%',
13
13
  // 'margin-top': arrivedTop ? '0' : '-5px',
14
14
  };
@@ -3,4 +3,62 @@ export { default as Content } from './Content.vue';
3
3
  export { default as Menu } from './Menu.vue';
4
4
  export { default as Tabs } from './Tabs.vue';
5
5
  export { default as Layout } from './Layout.vue';
6
- export { default as Notice } from './Notice.vue';
6
+ export { default as Notice } from './Notice.vue';
7
+
8
+ /* #B 优化表格水平滚动(测试版方案) */
9
+ const antTableHeaders = new WeakSet<HTMLElement>();
10
+ setInterval(() => {
11
+ const $header = document.querySelector('.antd-cover__table-sticky-pagination .ant-table-header') as HTMLElement;
12
+
13
+ if (!$header || antTableHeaders.has($header))
14
+ return;
15
+
16
+ antTableHeaders.add($header);
17
+ $header.addEventListener('wheel', (ev) => {
18
+ ev.preventDefault();
19
+ const $body = (ev.currentTarget as HTMLElement).parentElement?.querySelector(':scope > .ant-table-body');
20
+
21
+ if ($body) {
22
+ const left = $body.scrollLeft + (ev.deltaY < 0 ? -100 : 100);
23
+ $body.scroll({ left });
24
+ }
25
+ })
26
+
27
+ const tipsKey = 'HIDDEN_TABLE_HORIZONTAL_SCROLLING_PROMPT';
28
+ const hiddenTips = localStorage.getItem(tipsKey);
29
+
30
+ if (!hiddenTips) {
31
+ const tips = `将鼠标指针移至表头,通过滚动鼠标滚轮来水平滑动表格(点击可关闭此提示)`;
32
+ const ctn = document.createElement('div');
33
+ ctn.className = `pos-sticky left-0 top-0 w-full h-full bg-$antd-colorPrimary text-center lh-relaxed text-white`;
34
+ ctn.innerHTML = tips;
35
+ ctn.onclick = () => {
36
+ ctn.remove();
37
+ localStorage.setItem(tipsKey, '1');
38
+ };
39
+ $header.appendChild(ctn);
40
+ }
41
+ }, 1000);
42
+ /* #E */
43
+
44
+ /* #B 高亮最后一次操作的表格行 */
45
+ window.addEventListener('click', (ev) => {
46
+ const targetEle = ev.target as HTMLElement;
47
+ const closestRow = targetEle.closest('.ant-table-row');
48
+
49
+ if (closestRow) {
50
+ document.querySelectorAll('.last-clicked-cell').forEach((cell) => {
51
+ cell.classList.remove('ant-table-cell-row-hover');
52
+ cell.classList.remove('last-clicked-cell');
53
+ });
54
+
55
+ const cells = closestRow.querySelectorAll(':scope > .ant-table-cell');
56
+ setTimeout(() => {
57
+ cells.forEach((cell) => {
58
+ cell.classList.add('ant-table-cell-row-hover');
59
+ cell.classList.add('last-clicked-cell');
60
+ });
61
+ }, 300);
62
+ }
63
+ });
64
+ /* #E */
@@ -103,7 +103,7 @@
103
103
  z-index: 2;
104
104
  margin-bottom: -9px !important;
105
105
  background-color: var(--pagination-bg-color);
106
- box-shadow: 0 0 0 14px var(--pagination-bg-color);
106
+ box-shadow: 0 0 0 14.5px var(--pagination-bg-color);
107
107
  }
108
108
  }
109
109
 
@@ -1,4 +1,4 @@
1
- import { computed, reactive, ref } from 'vue';
1
+ import { computed, reactive, ref, toValue } from 'vue';
2
2
  import { pick } from 'lodash-es';
3
3
  import type { UseQueryReturnType } from '@tanstack/vue-query';
4
4
  import type { Table, TableProps } from 'ant-design-vue';
@@ -54,7 +54,7 @@ export function useAntdTable<
54
54
  }
55
55
  }
56
56
  };
57
- const defineColumns = (columnsGetter: () => LocalColumnsType) => computed(columnsGetter);
57
+ const { defineColumns } = useTableColumns<LocalColumnsType>();
58
58
  const defineRowSelection = (rowSelectionGetter: () => LocalTableRowSelection = () => ({})) => {
59
59
  const rowSelection = reactive(rowSelectionGetter());
60
60
 
@@ -128,3 +128,51 @@ type GetRecordType<T> = T extends UseQueryReturnType<infer D, any>
128
128
  ? NonNullable<D['list']>[0]
129
129
  : never
130
130
  : never;
131
+
132
+ function useTableColumns<LCT extends any[]>() {
133
+ type ColumnConfig = {title: string, dataIndex: string, visible: boolean}
134
+
135
+ const columnsConfig = ref<Array<ColumnConfig> | null>(null);
136
+ let originalColumns: LCT | null = null;
137
+
138
+ const defineColumns = (columnsGetter: () => LCT) => {
139
+ originalColumns = toValue(columnsGetter) || [] as unknown as LCT;
140
+
141
+ return computed(() => {
142
+ const config = columnsConfig.value;
143
+ let columns = columnsGetter();
144
+
145
+ if (config?.length) {
146
+ // 过滤掉不可见的列
147
+ columns = columns.filter((col: any) => {
148
+ const x = config.find(c => c.dataIndex === col.dataIndex);
149
+ return x ? x.visible : true;
150
+ }) as LCT;
151
+ // 基于 config 的顺序排序
152
+ columns = config.map(x => {
153
+ const col = columns.find(c => c.dataIndex === x.dataIndex);
154
+ return col ? col : null;
155
+ }).filter(Boolean) as LCT;
156
+ }
157
+
158
+ return columns;
159
+ })
160
+ };
161
+
162
+ const setColumnsConfig = (columns: Array<ColumnConfig>) => {
163
+ columnsConfig.value = columns;
164
+
165
+ // if (!columnsConfig.value) {
166
+ // columnsConfig.value = originalColumns?.map(col => ({
167
+ // title: col.title,
168
+ // dataIndex: col.dataIndex as string,
169
+ // visible: true,
170
+ // })) || [];
171
+ // }
172
+ };
173
+
174
+
175
+ return {
176
+ defineColumns,
177
+ };
178
+ }
package/package.json CHANGED
@@ -1,94 +1,95 @@
1
- {
2
- "name": "@peng_kai/kit",
3
- "type": "module",
4
- "version": "0.3.0-beta.10",
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.6",
17
- "vue": "3.5.17",
18
- "vue-router": "4.5.1"
19
- },
20
- "dependencies": {
21
- "@aws-sdk/client-s3": "^3.835.0",
22
- "@aws-sdk/lib-storage": "^3.835.0",
23
- "@babel/generator": "^7.27.5",
24
- "@babel/parser": "^7.27.5",
25
- "@babel/traverse": "^7.27.4",
26
- "@babel/types": "^7.27.6",
27
- "@ckeditor/ckeditor5-vue": "^5.1.0",
28
- "@fingerprintjs/fingerprintjs": "^4.6.2",
29
- "@tanstack/vue-query": "^5.81.2",
30
- "@vueuse/components": "^13.4.0",
31
- "@vueuse/core": "^13.4.0",
32
- "@vueuse/router": "^13.4.0",
33
- "archiver": "^7.0.1",
34
- "axios": "^1.10.0",
35
- "bignumber.js": "^9.3.0",
36
- "chokidar": "^3.6.0",
37
- "crypto-es": "^2.1.0",
38
- "dayjs": "^1.11.13",
39
- "echarts": "^5.5.1",
40
- "execa": "^9.4.0",
41
- "fast-glob": "^3.3.2",
42
- "localstorage-slim": "^2.7.1",
43
- "lodash-es": "^4.17.21",
44
- "nprogress": "^0.2.0",
45
- "pinia": "^3.0.3",
46
- "tsx": "^4.16.00",
47
- "vue": "^3.5.17",
48
- "vue-i18n": "^11.1.7",
49
- "vue-router": "^4.5.1"
50
- },
51
- "devDependencies": {
52
- "@ckeditor/ckeditor5-adapter-ckfinder": "^41.1.0",
53
- "@ckeditor/ckeditor5-alignment": "^41.1.0",
54
- "@ckeditor/ckeditor5-autoformat": "^41.1.0",
55
- "@ckeditor/ckeditor5-basic-styles": "^41.1.0",
56
- "@ckeditor/ckeditor5-block-quote": "^41.1.0",
57
- "@ckeditor/ckeditor5-build-classic": "^41.1.0",
58
- "@ckeditor/ckeditor5-code-block": "^41.1.0",
59
- "@ckeditor/ckeditor5-document-outline": "^41.1.0",
60
- "@ckeditor/ckeditor5-editor-classic": "^41.1.0",
61
- "@ckeditor/ckeditor5-essentials": "^41.1.0",
62
- "@ckeditor/ckeditor5-font": "^41.1.0",
63
- "@ckeditor/ckeditor5-heading": "^41.1.0",
64
- "@ckeditor/ckeditor5-highlight": "^41.1.0",
65
- "@ckeditor/ckeditor5-horizontal-line": "^41.1.0",
66
- "@ckeditor/ckeditor5-html-embed": "^41.1.0",
67
- "@ckeditor/ckeditor5-html-support": "^41.1.0",
68
- "@ckeditor/ckeditor5-image": "^41.1.0",
69
- "@ckeditor/ckeditor5-import-word": "^41.1.0",
70
- "@ckeditor/ckeditor5-indent": "^41.1.0",
71
- "@ckeditor/ckeditor5-link": "^41.1.0",
72
- "@ckeditor/ckeditor5-list": "^41.1.0",
73
- "@ckeditor/ckeditor5-media-embed": "^41.1.0",
74
- "@ckeditor/ckeditor5-paragraph": "^41.1.0",
75
- "@ckeditor/ckeditor5-remove-format": "^41.1.0",
76
- "@ckeditor/ckeditor5-show-blocks": "^41.1.0",
77
- "@ckeditor/ckeditor5-source-editing": "^41.1.0",
78
- "@ckeditor/ckeditor5-table": "^41.1.0",
79
- "@ckeditor/ckeditor5-theme-lark": "^41.1.0",
80
- "@ckeditor/ckeditor5-typing": "^41.1.0",
81
- "@ckeditor/ckeditor5-upload": "^41.1.0",
82
- "@ckeditor/ckeditor5-word-count": "^41.1.0",
83
- "@peng_kai/lint": "^0.1.0",
84
- "@types/archiver": "^6.0.3",
85
- "@types/crypto-js": "^4.2.2",
86
- "@types/lodash-es": "^4.17.12",
87
- "@types/node": "^22.15.33",
88
- "@types/nprogress": "^0.2.3",
89
- "ant-design-vue": "^4.2.6",
90
- "type-fest": "^4.41.0",
91
- "typescript": "^5.8.3",
92
- "vue-component-type-helpers": "^2.2.10"
93
- }
94
- }
1
+ {
2
+ "name": "@peng_kai/kit",
3
+ "type": "module",
4
+ "version": "0.3.0-beta.11",
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.6",
17
+ "vue": "3.5.17",
18
+ "vue-router": "4.5.1"
19
+ },
20
+ "dependencies": {
21
+ "@aws-sdk/client-s3": "^3.840.0",
22
+ "@aws-sdk/lib-storage": "^3.840.0",
23
+ "@babel/generator": "^7.27.5",
24
+ "@babel/parser": "^7.27.7",
25
+ "@babel/traverse": "^7.27.7",
26
+ "@babel/types": "^7.27.7",
27
+ "@ckeditor/ckeditor5-vue": "^5.1.0",
28
+ "@fingerprintjs/fingerprintjs": "^4.6.2",
29
+ "@tanstack/vue-query": "^5.81.5",
30
+ "@vueuse/components": "^13.4.0",
31
+ "@vueuse/core": "^13.4.0",
32
+ "@vueuse/router": "^13.4.0",
33
+ "archiver": "^7.0.1",
34
+ "axios": "^1.10.0",
35
+ "bignumber.js": "^9.3.0",
36
+ "chokidar": "^3.6.0",
37
+ "crypto-es": "^2.1.0",
38
+ "dayjs": "^1.11.13",
39
+ "echarts": "^5.5.1",
40
+ "execa": "^9.4.0",
41
+ "fast-glob": "^3.3.2",
42
+ "fluid-dnd": "^2.4.0",
43
+ "localstorage-slim": "^2.7.1",
44
+ "lodash-es": "^4.17.21",
45
+ "nprogress": "^0.2.0",
46
+ "pinia": "^3.0.3",
47
+ "tsx": "^4.16.00",
48
+ "vue": "^3.5.17",
49
+ "vue-i18n": "^11.1.7",
50
+ "vue-router": "^4.5.1"
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.3",
86
+ "@types/crypto-js": "^4.2.2",
87
+ "@types/lodash-es": "^4.17.12",
88
+ "@types/node": "^22.15.33",
89
+ "@types/nprogress": "^0.2.3",
90
+ "ant-design-vue": "^4.2.6",
91
+ "type-fest": "^4.41.0",
92
+ "typescript": "^5.8.3",
93
+ "vue-component-type-helpers": "^2.2.10"
94
+ }
95
+ }
@@ -1,4 +1,4 @@
1
- import { S3Client } from '@aws-sdk/client-s3';
1
+ import { S3Client, ChecksumAlgorithm } from '@aws-sdk/client-s3';
2
2
  import { Upload } from '@aws-sdk/lib-storage';
3
3
  import type { FileHandler } from './fileHandlers';
4
4
 
@@ -28,8 +28,13 @@ export class AwsS3 {
28
28
 
29
29
  const uploader = new Upload({
30
30
  client: s3Client!,
31
- params: { Bucket: this.bucket, Key: fullPath, Body: file },
31
+ params: {
32
+ Bucket: this.bucket, Key: fullPath, Body: file,
33
+ ChecksumAlgorithm: ChecksumAlgorithm.CRC32,
34
+ },
32
35
  leavePartsOnError: false,
36
+ queueSize: 4,
37
+ partSize: 5 * 1024 * 1024,
33
38
  });
34
39
 
35
40
  return { uploader, fileURL: `${this.domain}/${fullPath}` };
@@ -61,6 +66,8 @@ export class AwsS3 {
61
66
  secretAccessKey: params.secretAccessKey,
62
67
  sessionToken: params.sessionToken,
63
68
  },
69
+ requestChecksumCalculation: 'WHEN_REQUIRED',
70
+ responseChecksumValidation: 'WHEN_REQUIRED',
64
71
  });
65
72
 
66
73
  return this.s3Client;