mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 09:17:06 +08:00
feat: terminology management
This commit is contained in:
@@ -2,7 +2,6 @@ import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from sqlalchemy import and_, or_, select, func, delete, update
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.orm import aliased
|
||||
|
||||
from apps.terminology.models.terminology_model import Terminology, TerminologyInfo
|
||||
@@ -25,7 +24,7 @@ def page_terminology(session: SessionDep, current_page: int = 1, page_size: int
|
||||
# 步骤1:先找到所有匹配的节点ID(无论是父节点还是子节点)
|
||||
matched_ids_subquery = (
|
||||
select(Terminology.id)
|
||||
.where(Terminology.name.like(keyword_pattern)) # LIKE查询条件
|
||||
.where(Terminology.word.like(keyword_pattern)) # LIKE查询条件
|
||||
.subquery()
|
||||
)
|
||||
|
||||
@@ -60,7 +59,7 @@ def page_terminology(session: SessionDep, current_page: int = 1, page_size: int
|
||||
children_subquery = (
|
||||
select(
|
||||
child.pid,
|
||||
func.jsonb_agg(child.name).order_by(child.create_time.desc()).label('children_names')
|
||||
func.jsonb_agg(child.word).filter(child.word.isnot(None)).label('other_words')
|
||||
)
|
||||
.where(child.pid.isnot(None))
|
||||
.group_by(child.pid)
|
||||
@@ -74,10 +73,7 @@ def page_terminology(session: SessionDep, current_page: int = 1, page_size: int
|
||||
Terminology.word,
|
||||
Terminology.create_time,
|
||||
Terminology.description,
|
||||
func.coalesce(
|
||||
children_subquery.c.children_names,
|
||||
func.cast('[]', JSONB)
|
||||
).label('other_words')
|
||||
children_subquery.c.other_words
|
||||
)
|
||||
.outerjoin(
|
||||
children_subquery,
|
||||
@@ -110,10 +106,7 @@ def page_terminology(session: SessionDep, current_page: int = 1, page_size: int
|
||||
Terminology.word,
|
||||
Terminology.create_time,
|
||||
Terminology.description,
|
||||
func.coalesce(
|
||||
func.jsonb_agg(child.word),
|
||||
func.cast('[]', JSONB)
|
||||
).label('other_words')
|
||||
func.jsonb_agg(child.word).filter(child.word.isnot(None)).label('other_words')
|
||||
)
|
||||
.outerjoin(child, and_(Terminology.id == child.pid))
|
||||
.where(Terminology.id.in_(paginated_parent_ids))
|
||||
@@ -130,7 +123,7 @@ def page_terminology(session: SessionDep, current_page: int = 1, page_size: int
|
||||
word=row.word,
|
||||
create_time=row.create_time,
|
||||
description=row.description,
|
||||
other_words=row.other_words,
|
||||
other_words=row.other_words if row.other_words else [],
|
||||
))
|
||||
|
||||
return current_page, page_size, total_count, total_pages, _list
|
||||
@@ -153,7 +146,7 @@ def create_terminology(session: SessionDep, info: TerminologyInfo):
|
||||
if info.other_words:
|
||||
for other_word in info.other_words:
|
||||
_list.append(
|
||||
Terminology(pid=result.id, word=other_word, create_time=create_time, description=info.description))
|
||||
Terminology(pid=result.id, word=other_word, create_time=create_time))
|
||||
session.bulk_save_objects(_list)
|
||||
session.flush()
|
||||
session.commit()
|
||||
@@ -180,7 +173,7 @@ def update_terminology(session: SessionDep, info: TerminologyInfo):
|
||||
if info.other_words:
|
||||
for other_word in info.other_words:
|
||||
_list.append(
|
||||
Terminology(pid=info.id, word=other_word, create_time=create_time, description=info.description))
|
||||
Terminology(pid=info.id, word=other_word, create_time=create_time))
|
||||
session.bulk_save_objects(_list)
|
||||
session.flush()
|
||||
session.commit()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, reactive, unref, nextTick } from 'vue'
|
||||
import { nextTick, onMounted, reactive, ref, unref } from 'vue'
|
||||
import icon_export_outlined from '@/assets/svg/icon_export_outlined.svg'
|
||||
import { professionalApi } from '@/api/professional'
|
||||
import { formatTimestamp } from '@/utils/date'
|
||||
@@ -72,7 +72,7 @@ const exportBatchUser = () => {
|
||||
cancelButtonText: t('common.cancel'),
|
||||
customClass: 'confirm-no_icon',
|
||||
autofocus: false,
|
||||
}
|
||||
},
|
||||
).then(() => {
|
||||
professionalApi.deleteEmbedded(multipleSelectionAll.value.map((ele) => ele.id)).then(() => {
|
||||
ElMessage({
|
||||
@@ -112,7 +112,7 @@ const deleteBatchUser = () => {
|
||||
cancelButtonText: t('common.cancel'),
|
||||
customClass: 'confirm-no_icon',
|
||||
autofocus: false,
|
||||
}
|
||||
},
|
||||
).then(() => {
|
||||
professionalApi.deleteEmbedded(multipleSelectionAll.value.map((ele) => ele.id)).then(() => {
|
||||
ElMessage({
|
||||
@@ -297,19 +297,20 @@ const deleteHandlerItem = (idx: number) => {
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-button secondary @click="exportAllUser">
|
||||
<template #icon>
|
||||
<icon_export_outlined />
|
||||
</template>
|
||||
{{ $t('professional.export_all') }}
|
||||
</el-button>
|
||||
<el-button secondary @click="editHandler(null)">
|
||||
<template #icon>
|
||||
<ccmUpload></ccmUpload>
|
||||
</template>
|
||||
{{ $t('user.batch_import') }}
|
||||
</el-button>
|
||||
|
||||
<template v-if="false">
|
||||
<el-button secondary @click="exportAllUser">
|
||||
<template #icon>
|
||||
<icon_export_outlined />
|
||||
</template>
|
||||
{{ $t('professional.export_all') }}
|
||||
</el-button>
|
||||
<el-button secondary @click="editHandler(null)">
|
||||
<template #icon>
|
||||
<ccmUpload></ccmUpload>
|
||||
</template>
|
||||
{{ $t('user.batch_import') }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-button type="primary" @click="editHandler(null)">
|
||||
<template #icon>
|
||||
<icon_add_outlined></icon_add_outlined>
|
||||
@@ -434,8 +435,8 @@ const deleteHandlerItem = (idx: number) => {
|
||||
<button class="danger-button" @click="deleteBatchUser">{{ $t('dashboard.delete') }}</button>
|
||||
|
||||
<span class="selected">{{
|
||||
$t('user.selected_2_items', { msg: multipleSelectionAll.length })
|
||||
}}</span>
|
||||
$t('user.selected_2_items', { msg: multipleSelectionAll.length })
|
||||
}}</span>
|
||||
|
||||
<el-button text @click="cancelDelete">
|
||||
{{ $t('common.cancel') }}
|
||||
@@ -577,23 +578,27 @@ const deleteHandlerItem = (idx: number) => {
|
||||
height: auto;
|
||||
padding-top: 200px;
|
||||
}
|
||||
|
||||
.tool-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.page-title {
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.table-content {
|
||||
max-height: calc(100% - 104px);
|
||||
overflow-y: auto;
|
||||
@@ -606,6 +611,7 @@ const deleteHandlerItem = (idx: number) => {
|
||||
.ed-icon {
|
||||
color: #646a73;
|
||||
}
|
||||
|
||||
.user-status-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -618,8 +624,10 @@ const deleteHandlerItem = (idx: number) => {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.field-comment {
|
||||
height: 24px;
|
||||
|
||||
.ed-icon {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
@@ -716,9 +724,11 @@ const deleteHandlerItem = (idx: number) => {
|
||||
.ed-form-item--label-top .ed-form-item__label {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.ed-form-item__label {
|
||||
color: #646a73;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
line-height: 22px;
|
||||
@@ -761,6 +771,7 @@ const deleteHandlerItem = (idx: number) => {
|
||||
border-radius: 6px;
|
||||
margin-right: -4px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: #1f23291a;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user