Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-resource
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-resource
Commits
1f0c5c61
提交
1f0c5c61
authored
9月 18, 2025
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: update
上级
9e6ace2f
全部展开
显示空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
1380 行增加
和
37 行删除
+1380
-37
menus.ts
src/assets/menus.ts
+43
-37
LLMConfigForm.vue
src/modules/system/llm/components/LLMConfigForm.vue
+319
-0
LLMConfigList.vue
src/modules/system/llm/components/LLMConfigList.vue
+340
-0
SensitivePersonManager.vue
src/modules/system/llm/components/SensitivePersonManager.vue
+0
-0
SensitiveWordManager.vue
src/modules/system/llm/components/SensitiveWordManager.vue
+0
-0
TextProcessConfig.vue
src/modules/system/llm/components/TextProcessConfig.vue
+210
-0
index.ts
src/modules/system/llm/index.ts
+10
-0
Index.vue
src/modules/system/llm/views/Index.vue
+77
-0
llmStorage.ts
src/utils/llmStorage.ts
+381
-0
没有找到文件。
src/assets/menus.ts
浏览文件 @
1f0c5c61
...
...
@@ -20,7 +20,8 @@ import {
QuestionFilled
,
EditPen
,
DataAnalysis
,
ChatDotRound
ChatDotRound
,
Setting
,
}
from
'@element-plus/icons-vue'
export
const
menus
:
IMenuItem
[]
=
[
{
...
...
@@ -32,37 +33,37 @@ export const menus: IMenuItem[] = [
tag
:
'v1-resource-video-list'
,
icon
:
VideoCamera
,
name
:
'视频'
,
path
:
'/resource/video'
path
:
'/resource/video'
,
},
{
tag
:
'v1-resource-courseware-list'
,
icon
:
Suitcase
,
name
:
'课件'
,
path
:
'/resource/courseware'
path
:
'/resource/courseware'
,
},
{
tag
:
'v1-resource-lesson-plan-list'
,
icon
:
FolderOpened
,
name
:
'教案'
,
path
:
'/resource/lessonplan'
path
:
'/resource/lessonplan'
,
},
{
tag
:
'v1-resource-other-information-list'
,
icon
:
Files
,
name
:
'其他资料'
,
path
:
'/resource/other'
path
:
'/resource/other'
,
},
{
icon
:
Collection
,
name
:
'题库管理'
,
path
:
import
.
meta
.
env
.
VITE_QA_CENTER_URL
+
'/question/list'
path
:
import
.
meta
.
env
.
VITE_QA_CENTER_URL
+
'/question/list'
,
},
{
icon
:
ToiletPaper
,
name
:
'试卷管理'
,
path
:
import
.
meta
.
env
.
VITE_QA_CENTER_URL
+
'/paper/list'
}
]
path
:
import
.
meta
.
env
.
VITE_QA_CENTER_URL
+
'/paper/list'
,
}
,
]
,
},
{
tag
:
'v1-course'
,
...
...
@@ -73,15 +74,15 @@ export const menus: IMenuItem[] = [
tag
:
'v1-course-list'
,
icon
:
Monitor
,
name
:
'我的课程'
,
path
:
'/course/my'
path
:
'/course/my'
,
},
{
tag
:
'v1-course-create'
,
icon
:
Edit
,
name
:
'新建课程'
,
path
:
'/course/update-course'
}
]
path
:
'/course/update-course'
,
}
,
]
,
},
{
tag
:
'v1-learning'
,
...
...
@@ -92,51 +93,51 @@ export const menus: IMenuItem[] = [
tag
:
'v1-backend-lecturer-list'
,
icon
:
UserFilled
,
name
:
'讲师管理'
,
path
:
'/admin/teacher'
path
:
'/admin/teacher'
,
},
{
tag
:
'v1-learning-teacher-list'
,
icon
:
School
,
name
:
'教工用户管理'
,
path
:
'/admin/staff'
path
:
'/admin/staff'
,
},
{
tag
:
'v1-learning-student-list'
,
icon
:
User
,
name
:
'学生管理'
,
path
:
'/admin/student'
path
:
'/admin/student'
,
},
{
tag
:
'v1-backend-specialty-list'
,
icon
:
Promotion
,
name
:
'专业管理'
,
path
:
'/admin/pro'
path
:
'/admin/pro'
,
},
{
tag
:
'v1-learning-class-list'
,
icon
:
School
,
name
:
'班级管理'
,
path
:
'/admin/class'
path
:
'/admin/class'
,
},
{
tag
:
'v1-learning-semester-list'
,
icon
:
Guide
,
name
:
'学期管理'
,
path
:
'/admin/semester'
path
:
'/admin/semester'
,
},
{
tag
:
'v1-backend-category-list'
,
icon
:
Filter
,
name
:
'类别管理'
,
path
:
'/admin/category'
path
:
'/admin/category'
,
},
{
icon
:
Coordinate
,
name
:
'资源审核管理'
,
path
:
'/admin/audit'
}
]
path
:
'/admin/audit'
,
}
,
]
,
},
{
tag
:
'v1-backend'
,
...
...
@@ -147,21 +148,26 @@ export const menus: IMenuItem[] = [
tag
:
'v1-backend-data-dictionary-list'
,
icon
:
Notebook
,
name
:
'数据字典'
,
path
:
'/system/dictionary'
path
:
'/system/dictionary'
,
},
{
tag
:
'v1-backend-cover-list'
,
icon
:
Picture
,
name
:
'封面管理'
,
path
:
'/system/cover'
path
:
'/system/cover'
,
},
{
tag
:
'v1-backend-suggestion-list'
,
icon
:
ChatDotRound
,
name
:
' 投诉建议管理'
,
path
:
'/system/suggestion'
}
]
path
:
'/system/suggestion'
,
},
{
icon
:
Setting
,
name
:
'大模型配置'
,
path
:
'/system/llm'
,
},
],
},
{
tag
:
'v1-teaching'
,
...
...
@@ -172,19 +178,19 @@ export const menus: IMenuItem[] = [
tag
:
'v1-teaching-discussion'
,
icon
:
QuestionFilled
,
name
:
'帖子管理'
,
path
:
'/teach/posts'
path
:
'/teach/posts'
,
},
{
tag
:
'v1-teaching-paper-paper-list'
,
icon
:
EditPen
,
name
:
'批改试卷'
,
path
:
'/teach/exam'
path
:
'/teach/exam'
,
},
{
tag
:
'v1-teaching-job-list'
,
icon
:
Edit
,
name
:
'批改大作业'
,
path
:
'/teach/work'
path
:
'/teach/work'
,
},
{
tag
:
''
,
...
...
@@ -192,7 +198,7 @@ export const menus: IMenuItem[] = [
name
:
'课程资源数据画像'
,
path
:
import
.
meta
.
env
.
VITE_BI_URL
+
'/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!8d44!!6e90!!6570!!636e!!753b!!50cf!.db&platform=PC&browserType=chrome'
'/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!8d44!!6e90!!6570!!636e!!753b!!50cf!.db&platform=PC&browserType=chrome'
,
},
{
tag
:
''
,
...
...
@@ -200,7 +206,7 @@ export const menus: IMenuItem[] = [
name
:
'在线学习数据画像'
,
path
:
import
.
meta
.
env
.
VITE_BI_URL
+
'/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!5b66!!4e60!!884c!!4e3a!!753b!!50cf!.db&platform=PC&browserType=chrome'
'/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!5b66!!4e60!!884c!!4e3a!!753b!!50cf!.db&platform=PC&browserType=chrome'
,
},
{
tag
:
''
,
...
...
@@ -208,8 +214,8 @@ export const menus: IMenuItem[] = [
name
:
'生源地分布'
,
path
:
import
.
meta
.
env
.
VITE_BI_URL
+
'/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!751f!!6e90!!5730!!5206!!5e03!.db&platform=PC&browserType=chrome'
}
]
}
'/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!751f!!6e90!!5730!!5206!!5e03!.db&platform=PC&browserType=chrome'
,
}
,
]
,
}
,
]
src/modules/system/llm/components/LLMConfigForm.vue
0 → 100644
浏览文件 @
1f0c5c61
<
template
>
<el-dialog
v-model=
"visible"
:title=
"isEdit ? '编辑大模型配置' : '新增大模型配置'"
width=
"800px"
:before-close=
"handleClose"
>
<el-form
ref=
"formRef"
:model=
"formData"
:rules=
"rules"
label-width=
"120px"
class=
"llm-config-form"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"配置名称"
prop=
"name"
>
<el-input
v-model=
"formData.name"
placeholder=
"请输入配置名称"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"提供商"
prop=
"provider"
>
<el-select
v-model=
"formData.provider"
placeholder=
"请选择提供商"
@
change=
"handleProviderChange"
>
<el-option
v-for=
"provider in providerOptions"
:key=
"provider.value"
:label=
"provider.label"
:value=
"provider.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"模型名称"
prop=
"model_name"
>
<el-select
v-model=
"formData.model_name"
placeholder=
"请选择模型"
filterable
>
<el-option
v-for=
"model in modelOptions"
:key=
"model.value"
:label=
"model.label"
:value=
"model.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"API地址"
prop=
"api_url"
>
<el-input
v-model=
"formData.api_url"
placeholder=
"请输入API地址"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item
label=
"API密钥"
prop=
"api_key"
>
<el-input
v-model=
"formData.api_key"
type=
"password"
placeholder=
"请输入API密钥"
show-password
/>
</el-form-item>
<el-form-item
label=
"描述"
prop=
"description"
>
<el-input
v-model=
"formData.description"
type=
"textarea"
:rows=
"3"
placeholder=
"请输入配置描述"
/>
</el-form-item>
<el-divider
content-position=
"left"
>
高级参数配置
</el-divider>
<el-row
:gutter=
"20"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"最大令牌数"
prop=
"max_tokens"
>
<el-input-number
v-model=
"formData.max_tokens"
:min=
"1"
:max=
"100000"
controls-position=
"right"
style=
"width: 100%"
/>
</el-form-item>
</el-col>
<el-col
:span=
"8"
>
<el-form-item
label=
"温度"
prop=
"temperature"
>
<el-input-number
v-model=
"formData.temperature"
:min=
"0"
:max=
"2"
:step=
"0.1"
controls-position=
"right"
style=
"width: 100%"
/>
</el-form-item>
</el-col>
<el-col
:span=
"8"
>
<el-form-item
label=
"Top P"
prop=
"top_p"
>
<el-input-number
v-model=
"formData.top_p"
:min=
"0"
:max=
"1"
:step=
"0.1"
controls-position=
"right"
style=
"width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"频率惩罚"
prop=
"frequency_penalty"
>
<el-input-number
v-model=
"formData.frequency_penalty"
:min=
"-2"
:max=
"2"
:step=
"0.1"
controls-position=
"right"
style=
"width: 100%"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"存在惩罚"
prop=
"presence_penalty"
>
<el-input-number
v-model=
"formData.presence_penalty"
:min=
"-2"
:max=
"2"
:step=
"0.1"
controls-position=
"right"
style=
"width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item
label=
"启用状态"
prop=
"is_enabled"
>
<el-switch
v-model=
"formData.is_enabled"
/>
<span
class=
"form-tip"
>
启用后该配置将可用于文本处理
</span>
</el-form-item>
</el-form>
<template
#
footer
>
<div
class=
"dialog-footer"
>
<el-button
@
click=
"handleClose"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
:loading=
"submitting"
>
{{
isEdit
?
'更新'
:
'创建'
}}
</el-button>
</div>
</
template
>
</el-dialog>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
computed
,
watch
}
from
'vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
{
llmConfigStorage
}
from
'@/utils/llmStorage'
interface
Props
{
visible
:
boolean
editData
?:
any
}
interface
Emits
{
(
e
:
'update:visible'
,
value
:
boolean
):
void
(
e
:
'success'
):
void
}
const
props
=
defineProps
<
Props
>
()
const
emit
=
defineEmits
<
Emits
>
()
const
formRef
=
ref
<
FormInstance
>
()
const
submitting
=
ref
(
false
)
// 提供商选项
const
providerOptions
=
[
{
label
:
'DeepSeek'
,
value
:
'deepseek'
},
{
label
:
'通义千问 (Qwen)'
,
value
:
'qwen'
},
{
label
:
'自定义'
,
value
:
'custom'
},
]
// 模型选项(根据提供商动态加载)
const
modelOptions
=
ref
<
Array
<
{
label
:
string
;
value
:
string
}
>>
([])
// 表单数据
const
formData
=
reactive
({
name
:
''
,
provider
:
''
,
model_name
:
''
,
api_key
:
''
,
api_url
:
''
,
max_tokens
:
4000
,
temperature
:
0.7
,
top_p
:
0.9
,
frequency_penalty
:
0
,
presence_penalty
:
0
,
is_enabled
:
true
,
description
:
''
,
})
// 表单验证规则
const
rules
:
FormRules
=
{
name
:
[
{
required
:
true
,
message
:
'请输入配置名称'
,
trigger
:
'blur'
},
{
min
:
2
,
max
:
50
,
message
:
'配置名称长度在 2 到 50 个字符'
,
trigger
:
'blur'
},
],
provider
:
[{
required
:
true
,
message
:
'请选择提供商'
,
trigger
:
'change'
}],
model_name
:
[{
required
:
true
,
message
:
'请选择模型名称'
,
trigger
:
'change'
}],
api_key
:
[{
required
:
true
,
message
:
'请输入API密钥'
,
trigger
:
'blur'
}],
api_url
:
[
{
required
:
true
,
message
:
'请输入API地址'
,
trigger
:
'blur'
},
{
type
:
'url'
,
message
:
'请输入正确的URL格式'
,
trigger
:
'blur'
},
],
max_tokens
:
[{
required
:
true
,
message
:
'请输入最大令牌数'
,
trigger
:
'blur'
}],
}
// 计算属性
const
isEdit
=
computed
(()
=>
!!
props
.
editData
)
// 监听对话框显示状态
watch
(
()
=>
props
.
visible
,
(
visible
)
=>
{
if
(
visible
)
{
if
(
props
.
editData
)
{
Object
.
assign
(
formData
,
props
.
editData
)
}
else
{
resetForm
()
}
loadModelOptions
()
}
}
)
// 监听提供商变化
watch
(
()
=>
formData
.
provider
,
()
=>
{
loadModelOptions
()
formData
.
model_name
=
''
}
)
// 重置表单
const
resetForm
=
()
=>
{
Object
.
assign
(
formData
,
{
name
:
''
,
provider
:
''
,
model_name
:
''
,
api_key
:
''
,
api_url
:
''
,
max_tokens
:
4000
,
temperature
:
0.7
,
top_p
:
0.9
,
frequency_penalty
:
0
,
presence_penalty
:
0
,
is_enabled
:
true
,
description
:
''
,
})
formRef
.
value
?.
clearValidate
()
}
// 加载模型选项
const
loadModelOptions
=
()
=>
{
modelOptions
.
value
=
getDefaultModels
(
formData
.
provider
)
}
// 获取默认模型列表
const
getDefaultModels
=
(
provider
:
string
)
=>
{
const
modelMap
:
Record
<
string
,
Array
<
{
label
:
string
;
value
:
string
}
>>
=
{
deepseek
:
[
{
label
:
'DeepSeek-V2'
,
value
:
'deepseek-chat'
},
{
label
:
'DeepSeek-Coder'
,
value
:
'deepseek-coder'
},
],
qwen
:
[
{
label
:
'Qwen2.5-72B-Instruct'
,
value
:
'qwen2.5-72b-instruct'
},
{
label
:
'Qwen2.5-32B-Instruct'
,
value
:
'qwen2.5-32b-instruct'
},
{
label
:
'Qwen2.5-14B-Instruct'
,
value
:
'qwen2.5-14b-instruct'
},
{
label
:
'Qwen2.5-7B-Instruct'
,
value
:
'qwen2.5-7b-instruct'
},
],
custom
:
[{
label
:
'自定义模型'
,
value
:
'custom'
}],
}
return
modelMap
[
provider
]
||
[]
}
// 处理提供商变化
const
handleProviderChange
=
()
=>
{
// 根据提供商设置默认API地址
const
defaultUrls
:
Record
<
string
,
string
>
=
{
deepseek
:
'https://api.deepseek.com/v1/chat/completions'
,
qwen
:
'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation'
,
custom
:
''
,
}
formData
.
api_url
=
defaultUrls
[
formData
.
provider
]
||
''
}
// 移除测试连接功能
// 提交表单
const
handleSubmit
=
async
()
=>
{
if
(
!
formRef
.
value
)
return
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
submitting
.
value
=
true
try
{
if
(
isEdit
.
value
&&
props
.
editData
?.
id
)
{
llmConfigStorage
.
update
(
props
.
editData
.
id
,
formData
)
ElMessage
.
success
(
'更新成功'
)
}
else
{
llmConfigStorage
.
create
(
formData
)
ElMessage
.
success
(
'创建成功'
)
}
emit
(
'success'
)
handleClose
()
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
||
'操作失败'
)
}
finally
{
submitting
.
value
=
false
}
}
// 关闭对话框
const
handleClose
=
()
=>
{
emit
(
'update:visible'
,
false
)
resetForm
()
}
</
script
>
<
style
lang=
"scss"
scoped
>
.llm-config-form
{
.form-tip
{
margin-left
:
10px
;
color
:
#909399
;
font-size
:
12px
;
}
}
.dialog-footer
{
text-align
:
right
;
}
</
style
>
src/modules/system/llm/components/LLMConfigList.vue
0 → 100644
浏览文件 @
1f0c5c61
<
template
>
<div
class=
"llm-config-list"
>
<!-- 搜索栏 -->
<div
class=
"search-bar"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"6"
>
<el-input
v-model=
"searchForm.name"
placeholder=
"请输入配置名称"
clearable
@
clear=
"handleSearch"
@
keyup
.
enter=
"handleSearch"
>
<template
#
prefix
>
<el-icon><Search
/></el-icon>
</
template
>
</el-input>
</el-col>
<el-col
:span=
"4"
>
<el-select
v-model=
"searchForm.provider"
placeholder=
"选择提供商"
clearable
@
change=
"handleSearch"
>
<el-option
v-for=
"provider in providerOptions"
:key=
"provider.value"
:label=
"provider.label"
:value=
"provider.value"
/>
</el-select>
</el-col>
<el-col
:span=
"4"
>
<el-select
v-model=
"searchForm.is_enabled"
placeholder=
"启用状态"
clearable
@
change=
"handleSearch"
>
<el-option
label=
"已启用"
value=
"true"
/>
<el-option
label=
"已禁用"
value=
"false"
/>
</el-select>
</el-col>
<el-col
:span=
"6"
>
<el-button
type=
"primary"
@
click=
"handleSearch"
>
<el-icon><Search
/></el-icon>
搜索
</el-button>
<el-button
@
click=
"handleReset"
>
<el-icon><Refresh
/></el-icon>
重置
</el-button>
</el-col>
<el-col
:span=
"4"
class=
"text-right"
>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
新增配置
</el-button>
</el-col>
</el-row>
</div>
<!-- 表格 -->
<el-table
v-loading=
"loading"
:data=
"tableData"
stripe
style=
"width: 100%"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
/>
<el-table-column
prop=
"name"
label=
"配置名称"
min-width=
"150"
/>
<el-table-column
prop=
"provider"
label=
"提供商"
width=
"120"
>
<
template
#
default=
"{ row }"
>
<el-tag
:type=
"getProviderTagType(row.provider) as any"
>
{{
getProviderLabel
(
row
.
provider
)
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
prop=
"model_name"
label=
"模型名称"
min-width=
"180"
/>
<el-table-column
prop=
"api_url"
label=
"API地址"
min-width=
"200"
show-overflow-tooltip
/>
<el-table-column
prop=
"max_tokens"
label=
"最大令牌"
width=
"100"
/>
<el-table-column
prop=
"temperature"
label=
"温度"
width=
"80"
/>
<el-table-column
prop=
"is_enabled"
label=
"状态"
width=
"80"
>
<
template
#
default=
"{ row }"
>
<el-switch
v-model=
"row.is_enabled"
@
change=
"handleToggleStatus(row)"
:loading=
"row.statusLoading"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"created_time"
label=
"创建时间"
width=
"160"
>
<
template
#
default=
"{ row }"
>
{{
formatDate
(
row
.
created_time
)
}}
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"150"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-button
type=
"primary"
size=
"small"
@
click=
"handleEdit(row)"
>
编辑
</el-button>
<el-button
type=
"danger"
size=
"small"
@
click=
"handleDelete(row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- 移除分页组件 -->
<!-- 批量操作 -->
<div
v-if=
"selectedRows.length > 0"
class=
"batch-actions"
>
<el-alert
:title=
"`已选择 ${selectedRows.length} 项`"
type=
"info"
show-icon
:closable=
"false"
>
<
template
#
default
>
<el-button
type=
"danger"
size=
"small"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
<el-button
type=
"warning"
size=
"small"
@
click=
"handleBatchDisable"
>
批量禁用
</el-button>
<el-button
type=
"success"
size=
"small"
@
click=
"handleBatchEnable"
>
批量启用
</el-button>
</
template
>
</el-alert>
</div>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
onMounted
}
from
'vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
Search
,
Refresh
,
Plus
}
from
'@element-plus/icons-vue'
import
{
llmConfigStorage
}
from
'@/utils/llmStorage'
interface
Props
{
onEdit
:
(
data
:
any
)
=>
void
}
const
props
=
defineProps
<
Props
>
()
// 搜索表单
const
searchForm
=
reactive
({
name
:
''
,
provider
:
''
,
is_enabled
:
''
,
})
// 提供商选项
const
providerOptions
=
[
{
label
:
'DeepSeek'
,
value
:
'deepseek'
},
{
label
:
'通义千问'
,
value
:
'qwen'
},
{
label
:
'自定义'
,
value
:
'custom'
},
]
// 表格数据
const
tableData
=
ref
<
any
[]
>
([])
const
loading
=
ref
(
false
)
const
selectedRows
=
ref
<
any
[]
>
([])
// 移除分页相关变量
// 获取提供商标签类型
const
getProviderTagType
=
(
provider
:
string
)
=>
{
const
typeMap
:
Record
<
string
,
string
>
=
{
deepseek
:
'primary'
,
qwen
:
'success'
,
custom
:
'danger'
,
}
return
typeMap
[
provider
]
||
'info'
}
// 获取提供商标签
const
getProviderLabel
=
(
provider
:
string
)
=>
{
const
option
=
providerOptions
.
find
((
item
)
=>
item
.
value
===
provider
)
return
option
?.
label
||
provider
}
// 格式化日期
const
formatDate
=
(
dateStr
?:
string
)
=>
{
if
(
!
dateStr
)
return
'-'
return
new
Date
(
dateStr
).
toLocaleString
(
'zh-CN'
)
}
// 加载数据
const
loadData
=
()
=>
{
loading
.
value
=
true
try
{
// 获取所有数据
let
allData
=
llmConfigStorage
.
getAll
()
// 应用搜索过滤
if
(
searchForm
.
name
)
{
allData
=
allData
.
filter
((
item
:
any
)
=>
item
.
name
.
toLowerCase
().
includes
(
searchForm
.
name
.
toLowerCase
()))
}
if
(
searchForm
.
provider
)
{
allData
=
allData
.
filter
((
item
:
any
)
=>
item
.
provider
===
searchForm
.
provider
)
}
if
(
searchForm
.
is_enabled
)
{
const
enabled
=
searchForm
.
is_enabled
===
'true'
allData
=
allData
.
filter
((
item
:
any
)
=>
item
.
is_enabled
===
enabled
)
}
// 直接显示所有数据,不分页
tableData
.
value
=
allData
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
||
'加载数据失败'
)
}
finally
{
loading
.
value
=
false
}
}
// 搜索
const
handleSearch
=
()
=>
{
loadData
()
}
// 重置搜索
const
handleReset
=
()
=>
{
Object
.
assign
(
searchForm
,
{
name
:
''
,
provider
:
''
,
is_enabled
:
''
,
})
handleSearch
()
}
// 新增
const
handleAdd
=
()
=>
{
props
.
onEdit
({})
}
// 编辑
const
handleEdit
=
(
row
:
any
)
=>
{
props
.
onEdit
(
row
)
}
// 移除测试连接功能
// 删除
const
handleDelete
=
async
(
row
:
any
)
=>
{
try
{
await
ElMessageBox
.
confirm
(
`确定要删除配置 "
${
row
.
name
}
" 吗?`
,
'确认删除'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
if
(
row
.
id
)
{
llmConfigStorage
.
delete
(
row
.
id
)
ElMessage
.
success
(
'删除成功'
)
loadData
()
}
}
catch
(
error
:
any
)
{
if
(
error
!==
'cancel'
)
{
ElMessage
.
error
(
error
.
message
||
'删除失败'
)
}
}
}
// 切换状态
const
handleToggleStatus
=
async
(
row
:
any
)
=>
{
if
(
!
row
.
id
)
return
row
.
statusLoading
=
true
try
{
llmConfigStorage
.
update
(
row
.
id
,
{
is_enabled
:
row
.
is_enabled
})
ElMessage
.
success
(
row
.
is_enabled
?
'启用成功'
:
'禁用成功'
)
}
catch
(
error
:
any
)
{
row
.
is_enabled
=
!
row
.
is_enabled
// 回滚状态
ElMessage
.
error
(
error
.
message
||
'操作失败'
)
}
finally
{
row
.
statusLoading
=
false
}
}
// 选择变化
const
handleSelectionChange
=
(
selection
:
any
[])
=>
{
selectedRows
.
value
=
selection
}
// 批量删除
const
handleBatchDelete
=
async
()
=>
{
try
{
await
ElMessageBox
.
confirm
(
`确定要删除选中的
${
selectedRows
.
value
.
length
}
个配置吗?`
,
'确认批量删除'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
selectedRows
.
value
.
filter
((
item
)
=>
item
.
id
).
forEach
((
item
)
=>
llmConfigStorage
.
delete
(
item
.
id
))
ElMessage
.
success
(
'批量删除成功'
)
loadData
()
}
catch
(
error
:
any
)
{
if
(
error
!==
'cancel'
)
{
ElMessage
.
error
(
error
.
message
||
'批量删除失败'
)
}
}
}
// 批量禁用
const
handleBatchDisable
=
async
()
=>
{
try
{
selectedRows
.
value
.
filter
((
item
)
=>
item
.
id
)
.
forEach
((
item
)
=>
llmConfigStorage
.
update
(
item
.
id
,
{
is_enabled
:
false
}))
ElMessage
.
success
(
'批量禁用成功'
)
loadData
()
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
||
'批量禁用失败'
)
}
}
// 批量启用
const
handleBatchEnable
=
async
()
=>
{
try
{
selectedRows
.
value
.
filter
((
item
)
=>
item
.
id
)
.
forEach
((
item
)
=>
llmConfigStorage
.
update
(
item
.
id
,
{
is_enabled
:
true
}))
ElMessage
.
success
(
'批量启用成功'
)
loadData
()
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
||
'批量启用失败'
)
}
}
// 移除分页变化方法
// 暴露刷新方法
defineExpose
({
refresh
:
loadData
,
})
onMounted
(()
=>
{
loadData
()
})
</
script
>
<
style
lang=
"scss"
scoped
>
.llm-config-list
{
.search-bar
{
margin-bottom
:
20px
;
padding
:
20px
;
background
:
#f5f7fa
;
border-radius
:
6px
;
}
.pagination-wrapper
{
margin-top
:
20px
;
text-align
:
right
;
}
.batch-actions
{
margin-top
:
20px
;
}
.text-right
{
text-align
:
right
;
}
}
</
style
>
src/modules/system/llm/components/SensitivePersonManager.vue
0 → 100644
浏览文件 @
1f0c5c61
差异被折叠。
点击展开。
src/modules/system/llm/components/SensitiveWordManager.vue
0 → 100644
浏览文件 @
1f0c5c61
差异被折叠。
点击展开。
src/modules/system/llm/components/TextProcessConfig.vue
0 → 100644
浏览文件 @
1f0c5c61
<
template
>
<div
class=
"text-process-config"
>
<el-card
class=
"config-card"
>
<template
#
header
>
<div
class=
"card-header"
>
<span>
文本处理配置
</span>
<el-button
type=
"primary"
@
click=
"handleSave"
:loading=
"saving"
>
保存配置
</el-button>
</div>
</
template
>
<el-form
ref=
"formRef"
:model=
"configData"
:rules=
"rules"
label-width=
"200px"
class=
"config-form"
>
<!-- 意识形态检测配置 -->
<el-divider
content-position=
"left"
>
意识形态检测配置
</el-divider>
<el-form-item
label=
"启用意识形态检测"
prop=
"enable_ideology_check"
>
<el-switch
v-model=
"configData.enable_ideology_check"
/>
<div
class=
"form-tip"
>
启用后将对文本进行意识形态相关内容的检测和过滤
</div>
</el-form-item>
<!-- 敏感词过滤配置 -->
<el-divider
content-position=
"left"
>
敏感词过滤配置
</el-divider>
<el-form-item
label=
"启用敏感词过滤"
prop=
"enable_sensitive_word_filter"
>
<el-switch
v-model=
"configData.enable_sensitive_word_filter"
/>
<div
class=
"form-tip"
>
启用后将检测并处理文本中的敏感词
</div>
</el-form-item>
<el-form-item
v-if=
"configData.enable_sensitive_word_filter"
label=
"自动替换敏感词"
prop=
"auto_replace_sensitive_words"
>
<el-switch
v-model=
"configData.auto_replace_sensitive_words"
/>
<div
class=
"form-tip"
>
启用后自动将敏感词替换为指定内容
</div>
</el-form-item>
<el-form-item
v-if=
"configData.enable_sensitive_word_filter && configData.auto_replace_sensitive_words"
label=
"自定义替换内容"
prop=
"custom_replacement"
>
<el-input
v-model=
"configData.custom_replacement"
placeholder=
"请输入替换内容,默认为***"
maxlength=
"50"
show-word-limit
/>
<div
class=
"form-tip"
>
当检测到敏感词时,将替换为此内容
</div>
</el-form-item>
<!-- 敏感人物过滤配置 -->
<el-divider
content-position=
"left"
>
敏感人物过滤配置
</el-divider>
<el-form-item
label=
"启用敏感人物过滤"
prop=
"enable_sensitive_person_filter"
>
<el-switch
v-model=
"configData.enable_sensitive_person_filter"
/>
<div
class=
"form-tip"
>
启用后将检测并处理文本中涉及的敏感人物
</div>
</el-form-item>
</el-form>
</el-card>
<!-- 移除测试区域 -->
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
onMounted
}
from
'vue'
import
{
ElMessage
}
from
'element-plus'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
{
textProcessStorage
}
from
'@/utils/llmStorage'
// 表单引用
const
formRef
=
ref
<
FormInstance
>
()
const
saving
=
ref
(
false
)
// 配置数据
const
configData
=
reactive
({
enable_ideology_check
:
true
,
enable_sensitive_word_filter
:
true
,
enable_sensitive_person_filter
:
true
,
auto_replace_sensitive_words
:
true
,
custom_replacement
:
'***'
,
})
// 移除测试相关变量
// 表单验证规则
const
rules
:
FormRules
=
{
custom_replacement
:
[{
max
:
50
,
message
:
'替换内容不能超过50个字符'
,
trigger
:
'blur'
}],
}
// 获取级别标签类型
const
getLevelTagType
=
(
level
:
string
)
=>
{
const
typeMap
:
Record
<
string
,
string
>
=
{
low
:
'info'
,
medium
:
'warning'
,
high
:
'danger'
,
}
return
typeMap
[
level
]
||
'info'
}
// 获取级别标签
const
getLevelLabel
=
(
level
:
string
)
=>
{
const
labelMap
:
Record
<
string
,
string
>
=
{
low
:
'低'
,
medium
:
'中'
,
high
:
'高'
,
}
return
labelMap
[
level
]
||
level
}
// 移除测试相关方法
// 加载配置
const
loadConfig
=
()
=>
{
try
{
const
config
=
textProcessStorage
.
get
()
Object
.
assign
(
configData
,
config
)
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
||
'加载配置失败'
)
}
}
// 保存配置
const
handleSave
=
async
()
=>
{
if
(
!
formRef
.
value
)
return
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
saving
.
value
=
true
try
{
textProcessStorage
.
update
(
configData
)
ElMessage
.
success
(
'配置保存成功'
)
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
||
'保存失败'
)
}
finally
{
saving
.
value
=
false
}
}
// 移除测试文本处理功能
onMounted
(()
=>
{
loadConfig
()
})
</
script
>
<
style
lang=
"scss"
scoped
>
.text-process-config
{
.config-card
,
.test-card
{
margin-bottom
:
20px
;
}
.card-header
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
}
.config-form
{
.form-tip
{
color
:
#909399
;
font-size
:
12px
;
margin-top
:
5px
;
}
}
.test-result
{
margin-top
:
20px
;
.result-section
{
margin-bottom
:
20px
;
h4
{
margin-bottom
:
10px
;
color
:
#303133
;
}
}
.sensitive-words
,
.sensitive-persons
{
margin-top
:
10px
;
.word-tag
,
.person-tag
{
margin-right
:
8px
;
margin-bottom
:
8px
;
}
}
.processed-text
{
padding
:
15px
;
background
:
#f5f7fa
;
border-radius
:
6px
;
border
:
1px
solid
#e4e7ed
;
line-height
:
1
.6
;
color
:
#606266
;
}
.score-tip
{
margin-top
:
10px
;
color
:
#909399
;
font-size
:
12px
;
}
.score-text
{
color
:
#fff
;
font-weight
:
bold
;
}
}
}
</
style
>
src/modules/system/llm/index.ts
0 → 100644
浏览文件 @
1f0c5c61
import
type
{
RouteRecordRaw
}
from
'vue-router'
import
AppLayout
from
'@/components/layout/Index.vue'
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
{
path
:
'/system/llm'
,
component
:
AppLayout
,
children
:
[{
path
:
''
,
component
:
()
=>
import
(
'./views/Index.vue'
)
}]
}
]
src/modules/system/llm/views/Index.vue
0 → 100644
浏览文件 @
1f0c5c61
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
'vue'
import
{
ElTabs
,
ElTabPane
}
from
'element-plus'
// 移除类型导入
import
LLMConfigList
from
'../components/LLMConfigList.vue'
import
LLMConfigForm
from
'../components/LLMConfigForm.vue'
import
SensitiveWordManager
from
'../components/SensitiveWordManager.vue'
import
SensitivePersonManager
from
'../components/SensitivePersonManager.vue'
import
TextProcessConfig
from
'../components/TextProcessConfig.vue'
// 当前激活的标签页
const
activeTab
=
ref
(
'llm-config'
)
// 表单相关
const
formVisible
=
ref
(
false
)
const
editData
=
ref
<
any
>
()
// 处理编辑
const
handleEdit
=
(
data
:
any
)
=>
{
editData
.
value
=
data
formVisible
.
value
=
true
}
// 处理表单成功
const
handleFormSuccess
=
()
=>
{
formVisible
.
value
=
false
editData
.
value
=
undefined
// 刷新列表
if
(
listRef
.
value
)
{
listRef
.
value
.
refresh
()
}
}
// 列表引用
const
listRef
=
ref
()
</
script
>
<
template
>
<div
class=
"llm-management"
>
<el-tabs
v-model=
"activeTab"
type=
"border-card"
class=
"management-tabs"
>
<!-- 大模型配置 -->
<el-tab-pane
label=
"大模型配置"
name=
"llm-config"
>
<LLMConfigList
:on-edit=
"handleEdit"
ref=
"listRef"
/>
</el-tab-pane>
<!-- 敏感词管理 -->
<el-tab-pane
label=
"敏感词管理"
name=
"sensitive-word"
>
<SensitiveWordManager
/>
</el-tab-pane>
<!-- 敏感人物管理 -->
<el-tab-pane
label=
"敏感人物管理"
name=
"sensitive-person"
>
<SensitivePersonManager
/>
</el-tab-pane>
<!-- 文本处理配置 -->
<el-tab-pane
label=
"文本处理配置"
name=
"text-process"
>
<TextProcessConfig
/>
</el-tab-pane>
</el-tabs>
<!-- 大模型配置表单 -->
<LLMConfigForm
v-model:visible=
"formVisible"
:edit-data=
"editData"
@
success=
"handleFormSuccess"
/>
</div>
</
template
>
<
style
lang=
"scss"
scoped
>
.llm-management
{
.management-tabs
{
min-height
:
600px
;
:deep
(
.el-tabs__content
)
{
padding
:
20px
;
}
}
}
</
style
>
src/utils/llmStorage.ts
0 → 100644
浏览文件 @
1f0c5c61
// 本地存储工具函数
// 存储键名常量
const
STORAGE_KEYS
=
{
LLM_CONFIGS
:
'llm_configs'
,
SENSITIVE_WORDS
:
'sensitive_words'
,
SENSITIVE_PERSONS
:
'sensitive_persons'
,
TEXT_PROCESS_CONFIG
:
'text_process_config'
,
LLM_FEATURES
:
'llm_features'
,
}
// 生成唯一ID
const
generateId
=
()
=>
{
return
Date
.
now
().
toString
(
36
)
+
Math
.
random
().
toString
(
36
).
substr
(
2
)
}
// 获取当前时间戳
const
getCurrentTime
=
()
=>
{
return
new
Date
().
toISOString
()
}
// 通用存储操作
const
storage
=
{
// 获取数据
get
<
T
>
(
key
:
string
,
defaultValue
:
T
):
T
{
try
{
const
item
=
localStorage
.
getItem
(
key
)
return
item
?
JSON
.
parse
(
item
)
:
defaultValue
}
catch
(
error
)
{
console
.
error
(
`Error getting data from localStorage for key
${
key
}
:`
,
error
)
return
defaultValue
}
},
// 设置数据
set
<
T
>
(
key
:
string
,
value
:
T
):
void
{
try
{
localStorage
.
setItem
(
key
,
JSON
.
stringify
(
value
))
}
catch
(
error
)
{
console
.
error
(
`Error setting data to localStorage for key
${
key
}
:`
,
error
)
}
},
// 删除数据
remove
(
key
:
string
):
void
{
try
{
localStorage
.
removeItem
(
key
)
}
catch
(
error
)
{
console
.
error
(
`Error removing data from localStorage for key
${
key
}
:`
,
error
)
}
},
}
// 大模型配置相关操作
export
const
llmConfigStorage
=
{
// 获取所有配置
getAll
()
{
return
storage
.
get
(
STORAGE_KEYS
.
LLM_CONFIGS
,
[]
as
any
[])
},
// 根据ID获取配置
getById
(
id
:
string
)
{
const
configs
=
this
.
getAll
()
return
configs
.
find
((
config
:
any
)
=>
config
.
id
===
id
)
},
// 创建配置
create
(
config
:
any
)
{
const
configs
=
this
.
getAll
()
const
newConfig
=
{
...
config
,
id
:
generateId
(),
created_time
:
getCurrentTime
(),
updated_time
:
getCurrentTime
(),
}
configs
.
push
(
newConfig
)
storage
.
set
(
STORAGE_KEYS
.
LLM_CONFIGS
,
configs
)
return
newConfig
},
// 更新配置
update
(
id
:
string
,
updates
:
any
)
{
const
configs
=
this
.
getAll
()
const
index
=
configs
.
findIndex
((
config
:
any
)
=>
config
.
id
===
id
)
if
(
index
!==
-
1
)
{
configs
[
index
]
=
{
...
configs
[
index
],
...
updates
,
updated_time
:
getCurrentTime
(),
}
storage
.
set
(
STORAGE_KEYS
.
LLM_CONFIGS
,
configs
)
return
configs
[
index
]
}
return
null
},
// 删除配置
delete
(
id
:
string
)
{
const
configs
=
this
.
getAll
()
const
filteredConfigs
=
configs
.
filter
((
config
:
any
)
=>
config
.
id
!==
id
)
storage
.
set
(
STORAGE_KEYS
.
LLM_CONFIGS
,
filteredConfigs
)
return
true
},
// 搜索配置
search
(
params
:
{
name
?:
string
;
provider
?:
string
;
is_enabled
?:
string
})
{
let
configs
=
this
.
getAll
()
if
(
params
.
name
)
{
configs
=
configs
.
filter
((
config
:
any
)
=>
config
.
name
.
toLowerCase
().
includes
(
params
.
name
!
.
toLowerCase
()))
}
if
(
params
.
provider
)
{
configs
=
configs
.
filter
((
config
:
any
)
=>
config
.
provider
===
params
.
provider
)
}
if
(
params
.
is_enabled
)
{
const
enabled
=
params
.
is_enabled
===
'true'
configs
=
configs
.
filter
((
config
:
any
)
=>
config
.
is_enabled
===
enabled
)
}
return
configs
},
}
// 敏感词相关操作
export
const
sensitiveWordStorage
=
{
// 获取所有敏感词
getAll
()
{
return
storage
.
get
(
STORAGE_KEYS
.
SENSITIVE_WORDS
,
[]
as
any
[])
},
// 根据ID获取敏感词
getById
(
id
:
string
)
{
const
words
=
this
.
getAll
()
return
words
.
find
((
word
:
any
)
=>
word
.
id
===
id
)
},
// 创建敏感词
create
(
word
:
any
)
{
const
words
=
this
.
getAll
()
const
newWord
=
{
...
word
,
id
:
generateId
(),
created_time
:
getCurrentTime
(),
}
words
.
push
(
newWord
)
storage
.
set
(
STORAGE_KEYS
.
SENSITIVE_WORDS
,
words
)
return
newWord
},
// 更新敏感词
update
(
id
:
string
,
updates
:
any
)
{
const
words
=
this
.
getAll
()
const
index
=
words
.
findIndex
((
word
:
any
)
=>
word
.
id
===
id
)
if
(
index
!==
-
1
)
{
words
[
index
]
=
{
...
words
[
index
],
...
updates
}
storage
.
set
(
STORAGE_KEYS
.
SENSITIVE_WORDS
,
words
)
return
words
[
index
]
}
return
null
},
// 删除敏感词
delete
(
id
:
string
)
{
const
words
=
this
.
getAll
()
const
filteredWords
=
words
.
filter
((
word
:
any
)
=>
word
.
id
!==
id
)
storage
.
set
(
STORAGE_KEYS
.
SENSITIVE_WORDS
,
filteredWords
)
return
true
},
// 搜索敏感词
search
(
params
:
{
word
?:
string
;
level
?:
string
})
{
let
words
=
this
.
getAll
()
if
(
params
.
word
)
{
words
=
words
.
filter
((
word
:
any
)
=>
word
.
word
.
toLowerCase
().
includes
(
params
.
word
!
.
toLowerCase
()))
}
if
(
params
.
level
)
{
words
=
words
.
filter
((
word
:
any
)
=>
word
.
level
===
params
.
level
)
}
return
words
},
// 批量导入
batchImport
(
words
:
string
[],
level
:
string
)
{
const
existingWords
=
this
.
getAll
()
const
newWords
=
words
.
map
((
word
)
=>
({
id
:
generateId
(),
word
:
word
.
trim
(),
level
,
replacement
:
'***'
,
is_enabled
:
true
,
created_time
:
getCurrentTime
(),
}))
const
allWords
=
[...
existingWords
,
...
newWords
]
storage
.
set
(
STORAGE_KEYS
.
SENSITIVE_WORDS
,
allWords
)
return
newWords
},
}
// 敏感人物相关操作
export
const
sensitivePersonStorage
=
{
// 获取所有敏感人物
getAll
()
{
return
storage
.
get
(
STORAGE_KEYS
.
SENSITIVE_PERSONS
,
[]
as
any
[])
},
// 根据ID获取敏感人物
getById
(
id
:
string
)
{
const
persons
=
this
.
getAll
()
return
persons
.
find
((
person
:
any
)
=>
person
.
id
===
id
)
},
// 创建敏感人物
create
(
person
:
any
)
{
const
persons
=
this
.
getAll
()
const
newPerson
=
{
...
person
,
id
:
generateId
(),
created_time
:
getCurrentTime
(),
}
persons
.
push
(
newPerson
)
storage
.
set
(
STORAGE_KEYS
.
SENSITIVE_PERSONS
,
persons
)
return
newPerson
},
// 更新敏感人物
update
(
id
:
string
,
updates
:
any
)
{
const
persons
=
this
.
getAll
()
const
index
=
persons
.
findIndex
((
person
:
any
)
=>
person
.
id
===
id
)
if
(
index
!==
-
1
)
{
persons
[
index
]
=
{
...
persons
[
index
],
...
updates
}
storage
.
set
(
STORAGE_KEYS
.
SENSITIVE_PERSONS
,
persons
)
return
persons
[
index
]
}
return
null
},
// 删除敏感人物
delete
(
id
:
string
)
{
const
persons
=
this
.
getAll
()
const
filteredPersons
=
persons
.
filter
((
person
:
any
)
=>
person
.
id
!==
id
)
storage
.
set
(
STORAGE_KEYS
.
SENSITIVE_PERSONS
,
filteredPersons
)
return
true
},
// 搜索敏感人物
search
(
params
:
{
name
?:
string
;
level
?:
string
})
{
let
persons
=
this
.
getAll
()
if
(
params
.
name
)
{
persons
=
persons
.
filter
(
(
person
:
any
)
=>
person
.
name
.
toLowerCase
().
includes
(
params
.
name
!
.
toLowerCase
())
||
person
.
aliases
.
some
((
alias
:
string
)
=>
alias
.
toLowerCase
().
includes
(
params
.
name
!
.
toLowerCase
()))
)
}
if
(
params
.
level
)
{
persons
=
persons
.
filter
((
person
:
any
)
=>
person
.
level
===
params
.
level
)
}
return
persons
},
}
// 文本处理配置相关操作
export
const
textProcessStorage
=
{
// 获取配置
get
()
{
return
storage
.
get
(
STORAGE_KEYS
.
TEXT_PROCESS_CONFIG
,
{
enable_ideology_check
:
true
,
enable_sensitive_word_filter
:
true
,
enable_sensitive_person_filter
:
true
,
auto_replace_sensitive_words
:
true
,
custom_replacement
:
'***'
,
})
},
// 更新配置
update
(
config
:
any
)
{
storage
.
set
(
STORAGE_KEYS
.
TEXT_PROCESS_CONFIG
,
config
)
return
config
},
}
// 大模型功能配置相关操作
export
const
llmFeatureStorage
=
{
// 获取所有功能
getAll
()
{
return
storage
.
get
(
STORAGE_KEYS
.
LLM_FEATURES
,
[]
as
any
[])
},
// 根据大模型ID获取功能
getByLLMId
(
llmId
:
string
)
{
const
features
=
this
.
getAll
()
return
features
.
filter
((
feature
:
any
)
=>
feature
.
llm_id
===
llmId
)
},
// 创建功能
create
(
feature
:
any
)
{
const
features
=
this
.
getAll
()
const
newFeature
=
{
...
feature
,
id
:
generateId
(),
created_time
:
getCurrentTime
(),
updated_time
:
getCurrentTime
(),
}
features
.
push
(
newFeature
)
storage
.
set
(
STORAGE_KEYS
.
LLM_FEATURES
,
features
)
return
newFeature
},
// 更新功能
update
(
id
:
string
,
updates
:
any
)
{
const
features
=
this
.
getAll
()
const
index
=
features
.
findIndex
((
feature
:
any
)
=>
feature
.
id
===
id
)
if
(
index
!==
-
1
)
{
features
[
index
]
=
{
...
features
[
index
],
...
updates
,
updated_time
:
getCurrentTime
(),
}
storage
.
set
(
STORAGE_KEYS
.
LLM_FEATURES
,
features
)
return
features
[
index
]
}
return
null
},
// 删除功能
delete
(
id
:
string
)
{
const
features
=
this
.
getAll
()
const
filteredFeatures
=
features
.
filter
((
feature
:
any
)
=>
feature
.
id
!==
id
)
storage
.
set
(
STORAGE_KEYS
.
LLM_FEATURES
,
filteredFeatures
)
return
true
},
// 获取可用功能模板
getAvailableFeatures
()
{
return
[
{
code
:
'text_generation'
,
name
:
'文本生成'
,
description
:
'基于输入生成文本内容'
,
},
{
code
:
'text_summarization'
,
name
:
'文本摘要'
,
description
:
'生成文本的摘要内容'
,
},
{
code
:
'text_translation'
,
name
:
'文本翻译'
,
description
:
'将文本翻译为其他语言'
,
},
{
code
:
'text_analysis'
,
name
:
'文本分析'
,
description
:
'分析文本的情感、主题等'
,
},
{
code
:
'question_answering'
,
name
:
'问答系统'
,
description
:
'回答用户提出的问题'
,
},
]
},
}
// 导出所有存储操作
export
default
{
llmConfigStorage
,
sensitiveWordStorage
,
sensitivePersonStorage
,
textProcessStorage
,
llmFeatureStorage
,
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论