Skip to content

Commit e0444ce

Browse files
feat: The document list column supports width adjustment
1 parent d394da1 commit e0444ce

3 files changed

Lines changed: 102 additions & 5 deletions

File tree

ui/src/components/app-table/index.vue

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
:max-height="tableHeight"
55
v-bind="$attrs"
66
ref="appTableRef"
7+
@header-dragend="handleHeaderDragend"
78
:tooltip-options="{
89
popperClass: 'max-w-350',
910
}"
@@ -54,7 +55,7 @@
5455
</div>
5556
</template>
5657
<script setup lang="ts">
57-
import { ref, nextTick, watch, computed, onMounted } from 'vue'
58+
import { ref, nextTick, watch, computed, onMounted, useAttrs } from 'vue'
5859
import { MsgError } from '@/utils/message'
5960
import { t } from '@/locales'
6061
@@ -64,6 +65,8 @@ import useStore from '@/stores'
6465
6566
const { common } = useStore()
6667
68+
const attrs = useAttrs()
69+
6770
const props = defineProps({
6871
paginationConfig: {
6972
type: Object,
@@ -148,6 +151,78 @@ function clearSelection() {
148151
appTableRef.value?.clearSelection()
149152
}
150153
154+
/* ----------------- 列宽拖拽持久化 ----------------- */
155+
const COLUMN_WIDTH_PREFIX = 'app-table-column-width:'
156+
157+
function widthStorageKey() {
158+
return `${COLUMN_WIDTH_PREFIX}${props.storeKey}`
159+
}
160+
161+
function loadWidthMap(): Record<string, number> {
162+
try {
163+
return JSON.parse(localStorage.getItem(widthStorageKey()) || '{}')
164+
} catch {
165+
return {}
166+
}
167+
}
168+
169+
function saveWidthMap(map: Record<string, number>) {
170+
try {
171+
localStorage.setItem(widthStorageKey(), JSON.stringify(map))
172+
} catch {
173+
/* ignore quota / serialization errors */
174+
}
175+
}
176+
177+
/**
178+
* 列的稳定标识:优先用 prop / column-key,其次回退到渲染顺序下标。
179+
*/
180+
function getColumnKey(column: any, index: number) {
181+
return column?.property || column?.columnKey || `__col_${index}__`
182+
}
183+
184+
/**
185+
* 拖拽结束后,记录该列的最新宽度
186+
*/
187+
function handleHeaderDragend(newWidth: number, _oldWidth: number, column: any) {
188+
if (!props.storeKey || !column || !newWidth) {
189+
return
190+
}
191+
const cols = appTableRef.value?.columns || []
192+
const index = cols.findIndex((c: any) => c.id === column.id)
193+
const key = getColumnKey(column, index)
194+
const map = loadWidthMap()
195+
map[key] = Math.round(newWidth)
196+
saveWidthMap(map)
197+
}
198+
199+
/**
200+
* 表格渲染后,把缓存的列宽应用回去
201+
*/
202+
function restoreColumnWidths() {
203+
if (!props.storeKey) {
204+
return
205+
}
206+
const map = loadWidthMap()
207+
if (!map || !Object.keys(map).length) {
208+
return
209+
}
210+
const table = appTableRef.value
211+
const cols = table?.columns || []
212+
let changed = false
213+
cols.forEach((column: any, index: number) => {
214+
const w = map[getColumnKey(column, index)]
215+
if (typeof w === 'number' && w > 0 && column.realWidth !== w) {
216+
column.width = w
217+
column.realWidth = w
218+
changed = true
219+
}
220+
})
221+
if (changed) {
222+
table?.doLayout?.()
223+
}
224+
}
225+
151226
function toggleRowSelection(row: any, selected?: boolean, ignoreSelectable = true) {
152227
appTableRef.value?.toggleRowSelection(row, selected, ignoreSelectable)
153228
}
@@ -169,7 +244,19 @@ onMounted(() => {
169244
tableHeight.value = window.innerHeight - props.maxTableHeight
170245
})()
171246
}
247+
248+
// 首次渲染后恢复缓存的列宽
249+
nextTick(restoreColumnWidths)
172250
})
251+
252+
// 数据变化(翻页 / 筛选 / 轮询刷新)会重建列,重新应用缓存列宽
253+
watch(
254+
() => attrs.data,
255+
() => {
256+
nextTick(restoreColumnWidths)
257+
},
258+
)
259+
173260
</script>
174261

175262
<style lang="scss" scoped>

ui/src/styles/element-plus.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
--el-card-padding: calc(var(--app-base-px) * 2);
2525
--el-card-border-radius: 6px;
2626
box-shadow: 0px 2px 4px 0px rgba(var(--el-text-color-primary-rgb), 0.12) !important;
27-
--el-border-color-light: var(--el-border-color); overflow: visible;
27+
--el-border-color-light: var(--el-border-color);
28+
overflow: visible;
2829
&.is-never-shadow {
2930
border: 1px solid var(--el-card-border-color);
3031
box-shadow: none !important;
@@ -223,6 +224,9 @@
223224
background: var(--el-table-current-row-bg-color);
224225
}
225226
}
227+
.el-table__border-left-patch {
228+
display: none !important;
229+
}
226230

227231
// dialog
228232
.el-dialog {

ui/src/views/document/index.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,12 @@
159159
:remote-method="getUserList"
160160
style="width: 190px"
161161
>
162-
<el-option v-for="u in user_options" :key="u.id" :value="u.id" :label="u.nick_name" />
162+
<el-option
163+
v-for="u in user_options"
164+
:key="u.id"
165+
:value="u.id"
166+
:label="u.nick_name"
167+
/>
163168
</el-select>
164169
</div>
165170

@@ -198,6 +203,7 @@
198203
:row-key="(row: any) => row.id"
199204
:storeKey="storeKey"
200205
@cell-click="cellClickHandle"
206+
border
201207
>
202208
<el-table-column
203209
type="selection"
@@ -929,7 +935,7 @@ import TagDrawer from './tag/TagDrawer.vue'
929935
import TagSettingDrawer from './tag/TagSettingDrawer.vue'
930936
import AddTagDialog from '@/views/document/tag/MulAddTagDialog.vue'
931937
import ExecutionRecord from '@/views/knowledge-workflow/component/execution-record/ExecutionRecordDrawer.vue'
932-
import UserApi from "@/api/user/user.ts";
938+
import UserApi from '@/api/user/user.ts'
933939
934940
const route = useRoute()
935941
const router = useRouter()
@@ -1652,7 +1658,7 @@ function getUserList(query: string) {
16521658
const actualWorkspaceId = workspaceId || (query ? { nick_name: query } : '')
16531659
const actualQuery = workspaceId ? (query ? { nick_name: query } : '') : undefined
16541660
if (apiType.value === 'systemManage') {
1655-
UserApi.getAllMemberList(query ? {nick_name: query} : '')
1661+
UserApi.getAllMemberList(query ? { nick_name: query } : '')
16561662
.then((res: any) => {
16571663
user_options.value = res.data || []
16581664
})

0 commit comments

Comments
 (0)