diff --git a/.env.development b/.env.development index 07483ec..524387b 100644 --- a/.env.development +++ b/.env.development @@ -3,6 +3,6 @@ ENV = 'development' # 统一后端服务地址前缀(网关服务名:admin-go) # 开发环境走本地代理,避免 CORS -# VITE_API_URL = 'http://116.204.74.41:8000' -VITE_API_URL = 'http://192.168.3.30:8000' +VITE_API_URL = 'http://116.204.74.41:8000' +# VITE_API_URL = 'http://192.168.3.30:8000' # VITE_API_URL = 'http://192.168.3.135:8000' \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index f916b0e..551813f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -98,6 +98,18 @@ This is the **GFast UI** project (`gfast-ui`), a Vue 3 admin management system b These rules capture long-term repository preferences confirmed by the user and should be applied in future sessions unless the user explicitly overrides them. +### 最高优先级规则(覆盖以下所有规则) + +以下规则优先级高于本文件任何其他规则: + +1. **修改前必须确认**:任何代码修改前必须先向用户确认,用户明确同意后才能执行 +2. **反常问题必须上报**:遇到 Edit 反复失败、渲染异常、非预期行为等反常问题,必须立即向用户报告问题原因、可行方案和推荐方向,由用户选择后再继续 +3. **不确定必须询问**:不确定、不了解、不清楚的事情一律先问用户,不自行假设或绕路 +4. **改后影响检查**:代码修改完成后,必须逐一检查对其他代码的影响(渲染条件、接口字段、样式覆盖、其他引用处) +5. **改动评分与总结**:每次修改完成后,对本次改动按 1-10 分打分,并附上总结和改进建议 +6. **中文沟通**:所有与用户的沟通、说明、思考展示必须使用中文 +7. **操作后清理**:每次文件操作(拆分、替换、脚本执行等)完成后,必须检查并清理产生的临时文件,不得遗留在项目目录中 + ### Pagination Rules - Prefer the project global `pagination` component by default. diff --git a/src/api/settings/modelConfigV2/index.ts b/src/api/settings/modelConfigV2/index.ts index 602bb31..3abd0ac 100644 --- a/src/api/settings/modelConfigV2/index.ts +++ b/src/api/settings/modelConfigV2/index.ts @@ -54,9 +54,12 @@ export interface ModelManageItem { requestHeadMapping: Record; requestBodyMapping: Record; responseMapping: Record; + responseBodyMapping: string[]; tokenMapping?: TokenMapping; asyncTaskMapping?: AsyncTaskMapping; lastFrame?: string; + maxDuration: number; + tokenPredictPriceUnit: string; // 以下旧字段兼容 httpMethod?: string; systemModel?: boolean; @@ -164,9 +167,12 @@ export interface CreateModelManageParams { requestHeadMapping?: Record; requestBodyMapping?: Record; responseMapping?: Record; + responseBodyMapping?: string[]; tokenMapping?: TokenMapping; asyncTaskMapping?: AsyncTaskMapping; lastFrame?: string; + maxDuration?: number; + tokenPredictPriceUnit?: string; } /** 更新模型配置参数 */ diff --git a/src/views/settings/modelConfigV2/component/editModule.vue b/src/views/settings/modelConfigV2/component/editModule.vue index 63ff12a..36989c8 100644 --- a/src/views/settings/modelConfigV2/component/editModule.vue +++ b/src/views/settings/modelConfigV2/component/editModule.vue @@ -94,7 +94,13 @@ - + + + + + + + @@ -122,49 +128,30 @@ + + + + + + + - - Token 映射配置 - - - - - - - - - - - - - - - - - - - - - - - - + + Token 映射配置 + + + + + + + + + + + + + + + + + + + + + + + + @@ -278,7 +331,6 @@ import { updateModelManage, getModelManage, getModelSupplierList, - type ModelManageItem, type ModelTypeTreeNode, type ModelSupplierItem, type TokenMapping, @@ -348,12 +400,15 @@ const formData = reactive({ requestHeadMapping: {} as Record, requestBodyMapping: {} as Record, responseMapping: {} as Record, + responseBodyMapping: [] as string[], // Token 映射 tokenMapping: { ...defaultTokenMapping }, // 异步任务映射 asyncTaskMapping: { ...defaultAsyncTaskMapping }, // 视频 lastFrame: '', + maxDuration: 0, + tokenPredictPriceUnit: '', }); /** 获取选中模型类型路径上的所有标签 */ @@ -434,9 +489,28 @@ const tokenMappingOptions = computed(() => { const hasMappingConfig = computed(() => tokenMappingOptions.value.length > 0); /** 下拉占位文本 */ -const mappingPlaceholder = computed(() => - hasMappingConfig.value ? '请选择' : '请先配置响应映射' -); +const mappingPlaceholder = computed(() => { + if (hasMappingConfig.value) return '请选择'; + return formData.responseType === 2 ? '请先配置回调响应映射' : '请先配置响应映射'; +}); + +/** Task ID 路径下拉选项(来源响应映射) */ +const taskIdOptions = computed(() => { + const source = formData.responseMapping; + return source ? flattenWrappedFields(source) : []; +}); + +/** 是否有 Task ID 映射配置 */ +const hasTaskIdConfig = computed(() => taskIdOptions.value.length > 0); + +/** 任务状态路径下拉选项(来源回调响应映射) */ +const taskStatusOptions = computed(() => { + const source = formData.asyncTaskMapping.responseMapping; + return source ? flattenWrappedFields(source) : []; +}); + +/** 是否有任务状态映射配置 */ +const hasTaskStatusConfig = computed(() => taskStatusOptions.value.length > 0); /** 切换返回类型时清空 token mapping(初始加载时跳过) */ let _skipTokenClear = false; @@ -548,9 +622,12 @@ const resetForm = () => { formData.requestHeadMapping = {}; formData.requestBodyMapping = {}; formData.responseMapping = {}; + formData.responseBodyMapping = []; formData.tokenMapping = { ...defaultTokenMapping }; formData.asyncTaskMapping = { ...defaultAsyncTaskMapping }; formData.lastFrame = ''; + formData.maxDuration = 0; + formData.tokenPredictPriceUnit = ''; }; const openDialog = async (type: 'add' | 'edit', id?: string) => { @@ -579,9 +656,12 @@ const openDialog = async (type: 'add' | 'edit', id?: string) => { formData.requestHeadMapping = row.requestHeadMapping || row.requestMapping || {}; formData.requestBodyMapping = row.requestBodyMapping || {}; formData.responseMapping = row.responseMapping || {}; + formData.responseBodyMapping = row.responseBodyMapping || []; formData.tokenMapping = row.tokenMapping ? { ...defaultTokenMapping, ...row.tokenMapping } : { ...defaultTokenMapping }; formData.asyncTaskMapping = row.asyncTaskMapping ? { ...defaultAsyncTaskMapping, ...row.asyncTaskMapping } : { ...defaultAsyncTaskMapping }; formData.lastFrame = row.lastFrame || ''; + formData.maxDuration = row.maxDuration ?? 0; + formData.tokenPredictPriceUnit = row.tokenPredictPriceUnit || ''; } catch { // 关闭弹窗,错误由全局处理 dialogVisible.value = false; @@ -616,6 +696,7 @@ const handleSubmit = async () => { requestHeadMapping: Object.keys(formData.requestHeadMapping).length > 0 ? formData.requestHeadMapping : undefined, requestBodyMapping: Object.keys(formData.requestBodyMapping).length > 0 ? formData.requestBodyMapping : undefined, responseMapping: Object.keys(formData.responseMapping).length > 0 ? formData.responseMapping : undefined, + responseBodyMapping: formData.responseBodyMapping.length > 0 ? formData.responseBodyMapping : undefined, }; // 根据返回类型附加对应配置 @@ -636,12 +717,22 @@ const handleSubmit = async () => { if (formData.lastFrame) { lastFrame = formData.lastFrame; } + let maxDuration: number | undefined; + let tokenPredictPriceUnit: string | undefined; + if (isVideoModel.value) { + maxDuration = formData.maxDuration || undefined; + } + if (formData.tokenPredictPriceUnit) { + tokenPredictPriceUnit = formData.tokenPredictPriceUnit; + } const params: Record = { ...baseParams, ...(tokenMapping ? { tokenMapping } : {}), ...(asyncTaskMapping ? { asyncTaskMapping } : {}), ...(lastFrame ? { lastFrame } : {}), + ...(maxDuration ? { maxDuration } : {}), + ...(tokenPredictPriceUnit ? { tokenPredictPriceUnit } : {}), }; if (isEdit.value) {