Skip to content

Commit 7046df4

Browse files
committed
feat: tool update icon
1 parent df50fe9 commit 7046df4

5 files changed

Lines changed: 214 additions & 102 deletions

File tree

‎ui/src/views/home/components/ranking/HomeRankings.vue‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ function handleRangeChange({ startTime, endTime }: MkDateRangeValue) {
8383
function handleOpenRanking(kind: HomeRankingKind) {
8484
selectedKind.value = kind
8585
}
86+
function handleRankingDrawerClosed() {
87+
selectedKind.value = undefined
88+
}
8689
onMounted(loadRankings)
8790
</script>
8891
<template>
@@ -131,6 +134,13 @@ onMounted(loadRankings)
131134
<template #description="{ record }">对话 {{ numberFormat(record.chat_record_count) }} 次</template>
132135
</RankingCard>
133136
</div>
134-
<RankingDrawer :api="api" v-if="selectedKind" :workspace-id="workspaceId" :initial-kind="selectedKind" :initial-range="range" />
137+
<RankingDrawer
138+
v-if="selectedKind"
139+
:api="api"
140+
:workspace-id="workspaceId"
141+
:initial-kind="selectedKind"
142+
:initial-range="range"
143+
@closed="handleRankingDrawerClosed"
144+
/>
135145
</section>
136146
</template>

‎ui/src/views/tool/tool-form/DataSourceFormDrawer.vue‎

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import type { FormInstance, FormRules } from 'element-plus'
55
import type ToolApi from '@/api/admin/workspace/tool/tool'
66
import type SystemResourceToolApi from '@/api/admin/system/resource-management/tool/tool'
77
import type SystemSharedToolApi from '@/api/admin/system/shared-resources/tool/tool'
8-
import { TOOL_TYPE } from '@/api/enums'
8+
import { FILE_SOURCE_TYPE, TOOL_TYPE } from '@/api/enums'
9+
import FileApi from '@/api/admin/file'
910
import type { DynamicFormField, ToolInputField, ToolItem, ToolPayload } from '@/api/types'
11+
import MkEditAvatar from '@/components/mk-edit-avatar/index.vue'
1012
import { useStore } from '@/stores'
1113
import { MsgConfirm, MsgSuccess } from '@/utils/message'
1214
import InitFieldTable from './component/init-field/InitFieldTable.vue'
@@ -56,28 +58,44 @@ const formRules: FormRules<DataSourceFormModel> = {
5658
name: [{ whitespace: true, required: true, message: '请输入数据源名称', trigger: 'blur' }],
5759
}
5860
61+
// 暂存确认后的头像文件,恢复默认时清空。
62+
const iconFile = ref<File | null>(null)
63+
function handleIconChange(file: File | null) {
64+
iconFile.value = file
65+
}
66+
5967
function handleSubmit() {
60-
formRef.value?.validate((valid) => {
61-
if (!valid) return
68+
return formRef.value?.validate((valid) => {
69+
if (!valid || loading.value) return
6270
63-
const payload: ToolPayload = { ...cloneDeep(dataSourceForm), tool_type: TOOL_TYPE.DATA_SOURCE }
6471
loading.value = true
6572
const currentEditId = editId.value
6673
const isEdit = Boolean(currentEditId)
67-
const request = currentEditId
68-
? props.api.putTool(currentEditId, payload)
69-
: 'postTool' in props.api
70-
? props.api.postTool({ ...payload, folder_id: props.folderId || null })
71-
: Promise.reject(new Error('资源管理不支持创建工具'))
72-
73-
request
74-
.then((savedTool) => {
75-
const refreshCurrentUser = isEdit ? Promise.resolve() : auth.loadAuthBaseProfile()
76-
return refreshCurrentUser.then(() => {
77-
MsgSuccess(isEdit ? '保存成功' : '创建成功')
78-
visible.value = false
79-
if (isEdit) emit('update', savedTool)
80-
else emit('refresh')
74+
// 新头像先上传并替换预览地址,再提交完整工具表单。
75+
const uploadIcon = iconFile.value
76+
? FileApi.postUploadFile(iconFile.value, currentEditId, FILE_SOURCE_TYPE.TOOL).request.then((icon) => {
77+
dataSourceForm.icon = icon
78+
iconFile.value = null
79+
})
80+
: Promise.resolve()
81+
82+
return uploadIcon
83+
.then(() => {
84+
const payload: ToolPayload = { ...cloneDeep(dataSourceForm), tool_type: TOOL_TYPE.DATA_SOURCE }
85+
const request = currentEditId
86+
? props.api.putTool(currentEditId, payload)
87+
: 'postTool' in props.api
88+
? props.api.postTool({ ...payload, folder_id: props.folderId || null })
89+
: Promise.reject(new Error('资源管理不支持创建工具'))
90+
91+
return request.then((savedTool) => {
92+
const refreshCurrentUser = isEdit ? Promise.resolve() : auth.loadAuthBaseProfile()
93+
return refreshCurrentUser.then(() => {
94+
MsgSuccess(isEdit ? '保存成功' : '创建成功')
95+
visible.value = false
96+
if (isEdit) emit('update', savedTool)
97+
else emit('refresh')
98+
})
8199
})
82100
})
83101
.finally(() => {
@@ -123,6 +141,7 @@ function open(tool?: ToolItem, asCopy = false) {
123141
}
124142
125143
function handleBeforeClose() {
144+
if (loading.value) return
126145
if (JSON.stringify(dataSourceForm) === originalForm.value) {
127146
visible.value = false
128147
return
@@ -136,6 +155,7 @@ function handleBeforeClose() {
136155
137156
function resetData() {
138157
Object.assign(dataSourceForm, { code: codeTemplate, desc: '', icon: '', init_field_list: [], input_field_list: [], name: '' })
158+
iconFile.value = null
139159
editId.value = undefined
140160
originalForm.value = ''
141161
loading.value = false
@@ -155,7 +175,7 @@ defineExpose({ open })
155175
<MkDrawer v-model="visible" :before-close="handleBeforeClose" :title="title" size="60%" @closed="handleClosed">
156176
<el-form
157177
ref="formRef"
158-
v-loading="formLoading"
178+
v-loading="formLoading || loading"
159179
:model="dataSourceForm"
160180
:rules="formRules"
161181
label-position="top"
@@ -165,8 +185,12 @@ defineExpose({ open })
165185
<h4 class="mk-title-decoration mb-4">基本信息</h4>
166186
<el-form-item label="名称" prop="name">
167187
<div class="flex-align-center w-full gap-3">
168-
<!-- // TODO 修改头像 -->
169-
<ToolIcon :icon="dataSourceForm.icon" :size="32" :type="TOOL_TYPE.DATA_SOURCE" />
188+
<!-- 设置工具头像 -->
189+
<MkEditAvatar v-model="dataSourceForm.icon" @change="handleIconChange">
190+
<template #default="{ icon }">
191+
<ToolIcon :icon="icon" :type="TOOL_TYPE.DATA_SOURCE" />
192+
</template>
193+
</MkEditAvatar>
170194
<el-input
171195
v-model="dataSourceForm.name"
172196
maxlength="64"
@@ -194,7 +218,7 @@ defineExpose({ open })
194218
</el-form>
195219

196220
<template #footer>
197-
<el-button plain :disabled="loading" @click="handleBeforeClose">取消</el-button>
221+
<el-button plain :disabled="loading || formLoading" @click="handleBeforeClose">取消</el-button>
198222
<el-button type="primary" :disabled="formLoading" :loading="loading" @click="handleSubmit">
199223
{{ editId ? '保存' : '创建' }}
200224
</el-button>

‎ui/src/views/tool/tool-form/McpFormDrawer.vue‎

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import type { FormInstance, FormRules } from 'element-plus'
55
import type ToolApi from '@/api/admin/workspace/tool/tool'
66
import type SystemResourceToolApi from '@/api/admin/system/resource-management/tool/tool'
77
import type SystemSharedToolApi from '@/api/admin/system/shared-resources/tool/tool'
8-
import { TOOL_TYPE } from '@/api/enums'
8+
import { FILE_SOURCE_TYPE, TOOL_TYPE } from '@/api/enums'
9+
import FileApi from '@/api/admin/file'
910
import type { ToolItem, ToolPayload } from '@/api/types'
11+
import MkEditAvatar from '@/components/mk-edit-avatar/index.vue'
1012
import { useStore } from '@/stores'
1113
import { MsgConfirm, MsgError, MsgSuccess } from '@/utils/message'
1214
@@ -43,6 +45,12 @@ const formRules: FormRules<McpFormModel> = {
4345
name: [{ whitespace: true, required: true, message: '请输入 MCP 名称', trigger: 'blur' }],
4446
}
4547
48+
// 暂存确认后的头像文件,恢复默认时清空。
49+
const iconFile = ref<File | null>(null)
50+
function handleIconChange(file: File | null) {
51+
iconFile.value = file
52+
}
53+
4654
function isValidConfig() {
4755
try {
4856
const config: unknown = JSON.parse(mcpForm.code)
@@ -55,27 +63,37 @@ function isValidConfig() {
5563
}
5664
5765
function handleSubmit() {
58-
formRef.value?.validate((valid) => {
59-
if (!valid || !isValidConfig()) return
66+
return formRef.value?.validate((valid) => {
67+
if (!valid || loading.value || !isValidConfig()) return
6068
61-
const payload: ToolPayload = { ...cloneDeep(mcpForm), tool_type: TOOL_TYPE.MCP }
6269
loading.value = true
6370
const currentEditId = editId.value
6471
const isEdit = Boolean(currentEditId)
65-
const request = currentEditId
66-
? props.api.putTool(currentEditId, payload)
67-
: 'postTool' in props.api
68-
? props.api.postTool({ ...payload, folder_id: props.folderId || null })
69-
: Promise.reject(new Error('资源管理不支持创建工具'))
70-
71-
request
72-
.then((savedTool) => {
73-
const refreshCurrentUser = isEdit ? Promise.resolve() : auth.loadAuthBaseProfile()
74-
return refreshCurrentUser.then(() => {
75-
MsgSuccess(isEdit ? '保存成功' : '创建成功')
76-
visible.value = false
77-
if (isEdit) emit('update', savedTool)
78-
else emit('refresh')
72+
// 新头像先上传并替换预览地址,再提交完整工具表单。
73+
const uploadIcon = iconFile.value
74+
? FileApi.postUploadFile(iconFile.value, currentEditId, FILE_SOURCE_TYPE.TOOL).request.then((icon) => {
75+
mcpForm.icon = icon
76+
iconFile.value = null
77+
})
78+
: Promise.resolve()
79+
80+
return uploadIcon
81+
.then(() => {
82+
const payload: ToolPayload = { ...cloneDeep(mcpForm), tool_type: TOOL_TYPE.MCP }
83+
const request = currentEditId
84+
? props.api.putTool(currentEditId, payload)
85+
: 'postTool' in props.api
86+
? props.api.postTool({ ...payload, folder_id: props.folderId || null })
87+
: Promise.reject(new Error('资源管理不支持创建工具'))
88+
89+
return request.then((savedTool) => {
90+
const refreshCurrentUser = isEdit ? Promise.resolve() : auth.loadAuthBaseProfile()
91+
return refreshCurrentUser.then(() => {
92+
MsgSuccess(isEdit ? '保存成功' : '创建成功')
93+
visible.value = false
94+
if (isEdit) emit('update', savedTool)
95+
else emit('refresh')
96+
})
7997
})
8098
})
8199
.finally(() => {
@@ -128,6 +146,7 @@ function open(tool?: ToolItem, asCopy = false) {
128146
}
129147
130148
function handleBeforeClose() {
149+
if (loading.value) return
131150
if (JSON.stringify(mcpForm) === originalForm.value) {
132151
visible.value = false
133152
return
@@ -141,6 +160,7 @@ function handleBeforeClose() {
141160
142161
function resetData() {
143162
Object.assign(mcpForm, { code: '', desc: '', icon: '', name: '' })
163+
iconFile.value = null
144164
editId.value = undefined
145165
originalForm.value = ''
146166
loading.value = false
@@ -160,7 +180,7 @@ defineExpose({ open })
160180
<MkDrawer v-model="visible" :before-close="handleBeforeClose" :title="title" size="60%" @closed="handleClosed">
161181
<el-form
162182
ref="formRef"
163-
v-loading="formLoading"
183+
v-loading="formLoading || loading"
164184
:model="mcpForm"
165185
:rules="formRules"
166186
label-position="top"
@@ -170,8 +190,12 @@ defineExpose({ open })
170190
<h4 class="mk-title-decoration mb-4">基本信息</h4>
171191
<el-form-item label="名称" prop="name">
172192
<div class="flex-align-center w-full gap-3">
173-
<!-- // TODO修改头像 -->
174-
<ToolIcon :icon="mcpForm.icon" :size="32" :type="TOOL_TYPE.MCP" />
193+
<!-- 设置工具头像 -->
194+
<MkEditAvatar v-model="mcpForm.icon" @change="handleIconChange">
195+
<template #default="{ icon }">
196+
<ToolIcon :icon="icon" :type="TOOL_TYPE.MCP" />
197+
</template>
198+
</MkEditAvatar>
175199
<el-input v-model="mcpForm.name" maxlength="64" placeholder="请输入 MCP 名称" show-word-limit @blur="mcpForm.name = mcpForm.name.trim()" />
176200
</div>
177201
</el-form-item>
@@ -199,7 +223,7 @@ defineExpose({ open })
199223
</el-form>
200224

201225
<template #footer>
202-
<el-button plain :disabled="loading" @click="handleBeforeClose">取消</el-button>
226+
<el-button plain :disabled="loading || formLoading" @click="handleBeforeClose">取消</el-button>
203227
<el-button plain :disabled="loading || formLoading" @click="handleTestConnection"> 测试连接 </el-button>
204228
<el-button type="primary" :disabled="formLoading" :loading="loading" @click="handleSubmit">
205229
{{ editId ? '保存' : '创建' }}

0 commit comments

Comments
 (0)