from pathlib import Path root = Path('C:/kefu') p=root/'admin-web/apps/web-antd/src/api/request.ts';s=p.read_text(encoding='utf-8') s=s.replace("import { refreshTokenApi } from './core';", "import { refreshTokenApi } from './core';\nimport { responseErrorMessage } from './error-message';") start=s.index(' // 这里可以根据业务进行定制') end=s.index('\n }),',start) s=s[:start]+''' // FastAPI detail may be a validation array or object, never pass it directly to a toast. message.error(responseErrorMessage(error?.response?.data, msg));'''+s[end:] p.write_text(s,encoding='utf-8',newline='\n') p=root/'admin-web/apps/web-antd/src/views/knowledge/center.vue';s=p.read_text(encoding='utf-8') s=s.replace("import { ALL_ACCOUNTS } from '#/api/console';", "import { ALL_ACCOUNTS } from '#/api/console';\nimport { requestErrorMessage } from '#/api/error-message';") s=s.replace("const testQuery = ref('');", "const testQuery = ref('');\nconst searchError = ref('');") s=s.replace('result.value = null; overview.value = null;', "result.value = null; searchError.value = ''; overview.value = null;") start=s.index('async function test() {');end=s.index('\nasync function download()',start) s=s[:start]+'''async function test() { if (busy.value) return; result.value = null; searchError.value = ''; if (!single.value) { searchError.value = '请先选择具体账号'; return; } const text = testQuery.value.trim(); const length = Array.from(text).length; if (length < 2) { searchError.value = '请输入至少 2 个字符的检索问题'; return; } if (length > 2000) { searchError.value = '检索问题不能超过 2000 个字符'; return; } testQuery.value = text; const id = accountId.value; const generation = detailGeneration; busy.value = true; try { const found = await searchKnowledge(id, text); if (generation === detailGeneration) result.value = found; } catch (error) { if (generation === detailGeneration) searchError.value = requestErrorMessage(error, '检索失败,请稍后重试'); } finally { busy.value = false; } }'''+s[end:] s=s.replace(' \n ', ':loading="busy" @search="test" @change="searchError = \'\'" />\n ') s=s.replace('description="没有可靠命中。请补充问题信息,或整理相应知识。"', ':description="overview && !overview.counts.published ? \'当前账号没有已发布知识,审核通过后还需发布才能检索。\' : \'没有可靠命中。请补充问题信息,或发布相应知识。\'"') p.write_text(s,encoding='utf-8',newline='\n') p=root/'wechat_rpa/knowledge_api.py';s=p.read_text(encoding='utf-8') s=s.replace('from pydantic import BaseModel, Field', 'from pydantic import BaseModel, Field, field_validator') s=s.replace('class SearchBody(BaseModel):\n query: str = Field(min_length=2, max_length=2000)', '''class SearchBody(BaseModel): query: str = Field(min_length=2, max_length=2000) @field_validator('query', mode='before') @classmethod def trim_query(cls, value): return value.strip() if isinstance(value, str) else value''') p.write_text(s,encoding='utf-8',newline='\n') print('Search validation and structured error display updated.')