Skip to content

Commit 0143584

Browse files
committed
pref: improve Table sort
1 parent 82de276 commit 0143584

File tree

12 files changed

+73
-128
lines changed

12 files changed

+73
-128
lines changed

frontend/src/components/Language-selector/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,4 @@ const changeLanguage = (lang: string) => {
7373
.selected-lang {
7474
color: var(--el-color-primary);
7575
}
76-
</style>
76+
</style>

frontend/src/utils/xss.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,13 @@ export function highlightKeyword(
2727
highlightClass: string = 'highlight'
2828
): string {
2929
if (!keyword) return escapeHtml(text)
30-
30+
3131
const escapedText = escapeHtml(text)
3232
const escapedKeyword = escapeHtml(keyword)
33-
33+
3434
// Use case-insensitive replace
3535
const regex = new RegExp(escapedKeyword, 'gi')
36-
return escapedText.replace(
37-
regex,
38-
(match) => `<span class="${highlightClass}">${match}</span>`
39-
)
36+
return escapedText.replace(regex, (match) => `<span class="${highlightClass}">${match}</span>`)
4037
}
4138

4239
/**
@@ -48,33 +45,33 @@ export function sanitizeHtml(html: string): string {
4845
// Create a temporary div to parse HTML
4946
const temp = document.createElement('div')
5047
temp.innerHTML = html
51-
48+
5249
// List of allowed tags
5350
const allowedTags = ['b', 'i', 'u', 'strong', 'em', 'span', 'p', 'br', 'a']
54-
51+
5552
// List of allowed attributes
5653
const allowedAttrs = ['class', 'href', 'title']
57-
54+
5855
// Remove disallowed tags and attributes
5956
const sanitize = (node: Node): void => {
6057
if (node.nodeType === Node.ELEMENT_NODE) {
6158
const element = node as Element
62-
59+
6360
// Check if tag is allowed
6461
if (!allowedTags.includes(element.tagName.toLowerCase())) {
6562
// Replace with text content
6663
const textNode = document.createTextNode(element.textContent || '')
6764
element.parentNode?.replaceChild(textNode, element)
6865
return
6966
}
70-
67+
7168
// Remove disallowed attributes
7269
Array.from(element.attributes).forEach((attr) => {
7370
if (!allowedAttrs.includes(attr.name.toLowerCase())) {
7471
element.removeAttribute(attr.name)
7572
}
7673
})
77-
74+
7875
// For links, ensure they don't use javascript: protocol
7976
if (element.tagName.toLowerCase() === 'a') {
8077
const href = element.getAttribute('href') || ''
@@ -83,11 +80,11 @@ export function sanitizeHtml(html: string): string {
8380
}
8481
}
8582
}
86-
83+
8784
// Recursively sanitize child nodes
8885
Array.from(node.childNodes).forEach(sanitize)
8986
}
90-
87+
9188
sanitize(temp)
9289
return temp.innerHTML
9390
}

frontend/src/views/chat/ChatTokenTime.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function getLogList() {
1919
<span>{{ $t('parameter.tokens_required') }} {{ totalTokens }}</span>
2020
<span style="margin-left: 12px">{{ $t('parameter.time_execution') }} {{ duration }} s</span>
2121

22-
<div @click="getLogList" class="detail">
22+
<div class="detail" @click="getLogList">
2323
<el-icon style="margin-right: 4px" size="16">
2424
<icon_logs_outlined></icon_logs_outlined>
2525
</el-icon>

frontend/src/views/chat/component/charts/Table.ts

Lines changed: 38 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { BaseChart, type ChartAxis, type ChartData } from '@/views/chat/component/BaseChart.ts'
22
import {
33
copyToClipboard,
4-
type Node,
54
type S2DataConfig,
65
S2Event,
76
type S2MountContainer,
@@ -71,106 +70,51 @@ export class Table extends BaseChart {
7170
data: this.data,
7271
}
7372

73+
const sortState: Record<string, string> = {}
74+
75+
const handleSortClick = (params: any) => {
76+
const { meta } = params
77+
const s2 = meta.spreadsheet
78+
if (s2 && meta.isLeaf) {
79+
const fieldId = meta.field
80+
const currentMethod = sortState[fieldId] || 'none'
81+
const sortOrder = ['none', 'desc', 'asc']
82+
const nextMethod = sortOrder[(sortOrder.indexOf(currentMethod) + 1) % sortOrder.length]
83+
sortState[fieldId] = nextMethod
84+
s2.groupSortByMethod(nextMethod === 'none' ? 'none' : (nextMethod as SortMethod), meta)
85+
s2.render()
86+
}
87+
}
88+
7489
const s2Options: S2Options = {
7590
width: 600,
7691
height: 360,
77-
showDefaultHeaderActionIcon: true,
92+
showDefaultHeaderActionIcon: false,
93+
headerActionIcons: [
94+
{
95+
icons: ['GlobalDesc'],
96+
belongsCell: 'colCell',
97+
displayCondition: (node: any) => node.isLeaf && sortState[node.field] === 'desc',
98+
onClick: handleSortClick,
99+
},
100+
{
101+
icons: ['GlobalAsc'],
102+
belongsCell: 'colCell',
103+
displayCondition: (node: any) => node.isLeaf && sortState[node.field] === 'asc',
104+
onClick: handleSortClick,
105+
},
106+
{
107+
icons: ['SortDown'],
108+
belongsCell: 'colCell',
109+
displayCondition: (node: any) =>
110+
node.isLeaf && (!sortState[node.field] || sortState[node.field] === 'none'),
111+
onClick: handleSortClick,
112+
},
113+
],
78114
tooltip: {
79115
operation: {
80-
// 开启组内排序
81116
sort: true,
82117
},
83-
dataCell: {
84-
enable: true,
85-
content: (cell) => {
86-
const meta = cell.getMeta()
87-
const container = document.createElement('div')
88-
container.style.padding = '8px 0'
89-
container.style.minWidth = '100px'
90-
container.style.maxWidth = '400px'
91-
container.style.display = 'flex'
92-
container.style.alignItems = 'center'
93-
container.style.padding = '8px 16px'
94-
container.style.cursor = 'pointer'
95-
container.style.color = '#606266'
96-
container.style.fontSize = '14px'
97-
container.style.whiteSpace = 'pre-wrap'
98-
99-
const text = document.createTextNode(meta.fieldValue)
100-
container.appendChild(text)
101-
102-
return container
103-
},
104-
},
105-
colCell: {
106-
enable: true,
107-
content: (cell) => {
108-
const meta = cell.getMeta()
109-
const { spreadsheet: s2 } = meta
110-
if (!meta.isLeaf) {
111-
return null
112-
}
113-
114-
// 创建类似Element Plus下拉菜单的结构
115-
const container = document.createElement('div')
116-
container.className = 'el-dropdown'
117-
container.style.padding = '8px 0'
118-
container.style.minWidth = '100px'
119-
120-
const menuItems = [
121-
{
122-
label: t('chat.sort_desc'),
123-
method: 'desc' as SortMethod,
124-
icon: 'el-icon-sort-down',
125-
},
126-
{ label: t('chat.sort_asc'), method: 'asc' as SortMethod, icon: 'el-icon-sort-up' },
127-
{ label: t('chat.sort_none'), method: 'none' as SortMethod, icon: 'el-icon-close' },
128-
]
129-
130-
menuItems.forEach((item) => {
131-
const itemEl = document.createElement('div')
132-
itemEl.className = 'el-dropdown-menu__item'
133-
itemEl.style.display = 'flex'
134-
itemEl.style.alignItems = 'center'
135-
itemEl.style.padding = '8px 16px'
136-
itemEl.style.cursor = 'pointer'
137-
itemEl.style.color = '#606266'
138-
itemEl.style.fontSize = '14px'
139-
140-
// 鼠标悬停效果
141-
itemEl.addEventListener('mouseenter', () => {
142-
itemEl.style.backgroundColor = '#f5f7fa'
143-
itemEl.style.color = '#409eff'
144-
})
145-
itemEl.addEventListener('mouseleave', () => {
146-
itemEl.style.backgroundColor = 'transparent'
147-
itemEl.style.color = '#606266'
148-
})
149-
150-
// 添加图标(如果需要)
151-
if (item.icon) {
152-
const icon = document.createElement('i')
153-
icon.className = item.icon
154-
icon.style.marginRight = '8px'
155-
icon.style.fontSize = '16px'
156-
itemEl.appendChild(icon)
157-
}
158-
159-
const text = document.createTextNode(item.label)
160-
itemEl.appendChild(text)
161-
162-
itemEl.addEventListener('click', (e) => {
163-
e.stopPropagation()
164-
s2.groupSortByMethod(item.method, meta as Node)
165-
// 可以在这里添加关闭tooltip的逻辑
166-
})
167-
168-
container.appendChild(itemEl)
169-
})
170-
171-
return container
172-
},
173-
},
174118
},
175119
// 如果有省略号, 复制到的是完整文本
176120
interaction: {

frontend/src/views/ds/DataTable.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ const btnSelectClick = (val: any) => {
364364
</el-icon>
365365
<div class="name">{{ info.name }}</div>
366366
<div class="export-remark">
367-
<el-button style="margin-right: 12px" @click="downloadTemplate" secondary>
367+
<el-button style="margin-right: 12px" secondary @click="downloadTemplate">
368368
<template #icon>
369369
<icon_import_outlined></icon_import_outlined>
370370
</template>
@@ -387,7 +387,7 @@ const btnSelectClick = (val: any) => {
387387
:content="$t('ds.form.choose_tables')"
388388
placement="top"
389389
>
390-
<el-button style="margin-right: -4px" @click="handleSelectTableList" text>
390+
<el-button style="margin-right: -4px" text @click="handleSelectTableList">
391391
<el-icon size="18">
392392
<icon_form_outlined></icon_form_outlined>
393393
</el-icon>

frontend/src/views/ds/TableRelationship.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,12 +419,12 @@ const save = () => {
419419
<svg style="position: fixed; top: -9999px" xmlns:xlink="http://www.w3.org/1999/xlink">
420420
<defs>
421421
<filter
422+
id="filter-dropShadow-v0-3329848037"
422423
x="-1"
423424
y="-1"
424425
width="3"
425426
height="3"
426427
filterUnits="objectBoundingBox"
427-
id="filter-dropShadow-v0-3329848037"
428428
>
429429
<feDropShadow
430430
stdDeviation="4"
@@ -436,18 +436,18 @@ const save = () => {
436436
</filter>
437437
</defs>
438438
</svg>
439-
<div v-loading="loading" v-if="!nodeIds.length" class="relationship-empty">
439+
<div v-if="!nodeIds.length" v-loading="loading" class="relationship-empty">
440440
{{ t('training.add_it_here') }}
441441
</div>
442-
<div v-loading="loading" v-else id="container"></div>
442+
<div v-else id="container" v-loading="loading"></div>
443443
<div
444-
@dragover.prevent.stop="dragover"
445-
@drop.prevent.stop="drop"
446444
v-show="dragging"
447445
class="drag-mask"
446+
@dragover.prevent.stop="dragover"
447+
@drop.prevent.stop="drop"
448448
></div>
449449
<div class="save-btn">
450-
<el-button type="primary" v-if="nodeIds.length" @click="save">
450+
<el-button v-if="nodeIds.length" type="primary" @click="save">
451451
{{ t('common.save') }}
452452
</el-button>
453453
</div>

frontend/src/views/system/appearance/LoginPreview.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
<div class="config-area">
4141
<div class="login-logo">
4242
<div class="login-logo-icon">
43-
<img height="52" v-if="pageLogin" :src="pageLogin" alt="" />
44-
<el-icon size="52" v-else
43+
<img v-if="pageLogin" height="52" :src="pageLogin" alt="" />
44+
<el-icon v-else size="52"
4545
><custom_small v-if="themeColor !== 'default'"></custom_small>
4646
<LOGO_fold v-else></LOGO_fold
4747
></el-icon>

frontend/src/views/system/appearance/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
<div class="navigate-preview" style="height: 425px">
164164
<div class="navigate-head">
165165
<div class="header-sql">
166-
<img height="30" width="30" v-if="pageLogin" :src="pageLogin" alt="" />
166+
<img v-if="pageLogin" height="30" width="30" :src="pageLogin" alt="" />
167167
<custom_small v-else-if="themeColor !== 'default'" class="logo" />
168168
<logo v-else></logo>
169169
<span style="margin-left: 8px">{{ loginForm.name }}</span>

frontend/src/views/system/model/Card.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ defineExpose({ showErrorMask })
6969
</div>
7070
<div class="type-value">
7171
<span class="type">{{ $t('model.model_type') }}</span>
72-
<span class="value"> {{ modelType.startsWith('modelType.') ? $t(modelType) : modelType }}</span>
72+
<span class="value">
73+
{{ modelType.startsWith('modelType.') ? $t(modelType) : modelType }}</span
74+
>
7375
</div>
7476
<div class="type-value">
7577
<span class="type">{{ $t('model.basic_model') }}</span>

frontend/src/views/system/model/Model.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,9 @@ const submit = (item: any) => {
426426
>
427427
<template #header="{ close }">
428428
<span style="white-space: nowrap">{{
429-
editModel ? $t('dashboard.edit') + $t('common.empty') + $t(activeNameI18nKey) : t('model.add_model')
429+
editModel
430+
? $t('dashboard.edit') + $t('common.empty') + $t(activeNameI18nKey)
431+
: t('model.add_model')
430432
}}</span>
431433
<div v-if="!editModel" class="flex-center" style="width: 100%">
432434
<el-steps custom style="max-width: 500px; flex: 1" :active="activeStep" align-center>

0 commit comments

Comments
 (0)