diff --git a/.vscode/settings.json b/.vscode/settings.json index f145f38..2db1f3d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -62,7 +62,7 @@ "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[typescript]": { - "editor.defaultFormatter": "rvest.vs-code-prettier-eslint" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[typescriptreact]": { "editor.defaultFormatter": "rvest.vs-code-prettier-eslint" diff --git a/src/api/new-ai/app.ts b/src/api/new-ai/app.ts index 046e213..8788e4e 100644 --- a/src/api/new-ai/app.ts +++ b/src/api/new-ai/app.ts @@ -20,41 +20,41 @@ import request from '@/config/axios' export const AppApi = { // 获取应用列表 getAppList: async (params: any) => { - return await request.get({ url: '/aigc/app/list', params }) + return await request.get({ url: '/chat/aigc/app/list', params }) }, // 获取应用分页数据 getAppPage: async (params: any) => { - return await request.get({ url: '/aigc/app/page', params }) + return await request.get({ url: '/chat/aigc/app/page', params }) }, // 获取应用详情 getApp: async (id: string) => { - return await request.get({ url: `/aigc/app/${id}` }) + return await request.get({ url: `/chat/aigc/app/${id}` }) }, // 根据模型ID获取应用 getAppByModelId: async (id: string) => { - return await request.get({ url: `/aigc/app/byModelId/${id}` }) + return await request.get({ url: `/chat/aigc/app/byModelId/${id}` }) }, // 获取应用API通道 getAppApiChannel: async (appId: string) => { - return await request.get({ url: `/aigc/app/channel/api/${appId}` }) + return await request.get({ url: `/chat/aigc/app/channel/api/${appId}` }) }, // 新增应用 createApp: async (data: any) => { - return await request.post({ url: '/aigc/app', data }) + return await request.post({ url: '/chat/aigc/app', data }) }, // 更新应用 updateApp: async (data: any) => { - return await request.put({ url: '/aigc/app', data }) + return await request.put({ url: '/chat/aigc/app', data }) }, // 删除应用 deleteApp: async (id: string) => { - return await request.delete({ url: `/aigc/app/${id}` }) + return await request.delete({ url: `/chat/aigc/app/${id}` }) } } diff --git a/src/api/new-ai/appApi.ts b/src/api/new-ai/appApi.ts index b78eb86..9b3793f 100644 --- a/src/api/new-ai/appApi.ts +++ b/src/api/new-ai/appApi.ts @@ -20,41 +20,41 @@ import request from '@/config/axios' export const AppApiManagement = { // 获取API列表 getApiList: async (params: any) => { - return await request.get({ url: '/aigc/app/api/list', params }) + return await request.get({ url: '/chat/aigc/app/api/list', params }) }, // 获取API分页数据 getApiPage: async (params: any) => { - return await request.get({ url: '/aigc/app/api/page', params }) + return await request.get({ url: '/chat/aigc/app/api/page', params }) }, // 获取API详情 getApi: async (id: string) => { - return await request.get({ url: `/aigc/app/api/${id}` }) + return await request.get({ url: `/chat/aigc/app/api/${id}` }) }, // 新增API createApi: async (data: any) => { - return await request.post({ url: '/aigc/app/api', data }) + return await request.post({ url: '/chat/aigc/app/api', data }) }, // 更新API updateApi: async (data: any) => { - return await request.put({ url: '/aigc/app/api', data }) + return await request.put({ url: '/chat/aigc/app/api', data }) }, // 删除API deleteApi: async (id: string) => { - return await request.delete({ url: `/aigc/app/api/${id}` }) + return await request.delete({ url: `/chat/aigc/app/api/${id}` }) }, // 发布API publishApi: async (id: string) => { - return await request.put({ url: `/aigc/app/api/publish/${id}` }) + return await request.put({ url: `/chat/aigc/app/api/publish/${id}` }) }, // 下线API offlineApi: async (id: string) => { - return await request.put({ url: `/aigc/app/api/offline/${id}` }) + return await request.put({ url: `/chat/aigc/app/api/offline/${id}` }) } } diff --git a/src/api/new-ai/chat.ts b/src/api/new-ai/chat.ts index 447e21b..5072b61 100644 --- a/src/api/new-ai/chat.ts +++ b/src/api/new-ai/chat.ts @@ -23,7 +23,7 @@ export function chat( onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void ) { return request.post({ - url: '/aigc/chat/completions', + url: '/chat/aigc/chat/completions', data, signal: controller.signal, onDownloadProgress, @@ -33,26 +33,26 @@ export function chat( export function clean(conversationId: string | null) { return request.delete({ - url: `/aigc/chat/messages/clean/${conversationId}` + url: `/chat/aigc/chat/messages/clean/${conversationId}` }) } export function getMessages(conversationId?: string | number) { return request.get({ - url: `/aigc/chat/messages/${conversationId}` + url: `/chat/aigc/chat/messages/${conversationId}` }) } export function getAppInfo(params: any) { return request.get({ - url: `/aigc/app/info`, + url: `/chat/aigc/app/info`, params }) } export function getImageModels() { return request.get({ - url: '/aigc/chat/getImageModels' + url: '/chat/aigc/chat/getImageModels' }) } @@ -61,7 +61,7 @@ export function getImageModels() { */ export function genImage(data: any) { return request.post({ - url: '/aigc/chat/image', + url: '/chat/aigc/chat/image', data }) } @@ -71,7 +71,7 @@ export function genImage(data: any) { */ export function genMindMap(data: any) { return request.post({ - url: '/aigc/chat/mindmap', + url: '/chat/aigc/chat/mindmap', data }) } diff --git a/src/api/new-ai/oss.ts b/src/api/new-ai/oss.ts index 6fd99ad..199e015 100644 --- a/src/api/new-ai/oss.ts +++ b/src/api/new-ai/oss.ts @@ -24,8 +24,8 @@ export class OssApi { * 获取OSS上传策略 */ static policy() { - return request.get({ - url: '/oss/policy' + return request.get({ + url: '/chat/oss/policy' }) } @@ -33,9 +33,9 @@ export class OssApi { * 获取文件列表 */ static list(params: any) { - return request.get({ - url: '/oss/list', - params + return request.get({ + url: '/chat/oss/list', + params }) } @@ -43,20 +43,19 @@ export class OssApi { * 删除文件 */ static del(objectName: string) { - return request.delete({ - url: `/oss/${objectName}` + return request.delete({ + url: `/chat/oss/${objectName}` }) } /** * 上传文件 */ - static upload(data: FormData) { - return request.post({ - url: '/aigc/oss/upload', - headers: { - 'Content-Type': 'multipart/form-data', - }, + static uploadUrl = '/chat/aigc/oss/upload' + + static upload(data: any) { + return request.upload({ + url: '/chat/aigc/oss/upload', data }) } @@ -65,8 +64,8 @@ export class OssApi { * 获取文件访问URL */ static getUrl(objectName: string) { - return request.get({ - url: `/oss/url/${objectName}` + return request.get({ + url: `/chat/oss/url/${objectName}` }) } } diff --git a/src/components/Form/src/Form.vue b/src/components/Form/src/Form.vue index 4d59f03..f23e103 100644 --- a/src/components/Form/src/Form.vue +++ b/src/components/Form/src/Form.vue @@ -113,7 +113,9 @@ export default defineComponent({ } } } - + const setValue = (key: string, value: any) => { + formModel.value[key] = value + } const getElFormRef = (): ComponentRef => { return unref(elFormRef) as ComponentRef } @@ -129,7 +131,8 @@ export default defineComponent({ addSchema, setSchema, getElFormRef, - clearForm + clearForm, + setValue }) // 监听表单结构化数组,重新生成formModel diff --git a/src/components/UploadFile/src/UploadImg.vue b/src/components/UploadFile/src/UploadImg.vue index ac0c162..f152e2b 100644 --- a/src/components/UploadFile/src/UploadImg.vue +++ b/src/components/UploadFile/src/UploadImg.vue @@ -79,7 +79,9 @@ const props = defineProps({ width: propTypes.string.def('150px'), // 组件宽度 ==> 非必传(默认为 150px) borderradius: propTypes.string.def('8px'), // 组件边框圆角 ==> 非必传(默认为 8px) showDelete: propTypes.bool.def(true), // 是否显示删除按钮 - showBtnText: propTypes.bool.def(true) // 是否显示按钮文字 + showBtnText: propTypes.bool.def(true), // 是否显示按钮文字 + customApi: propTypes.func.def(() => undefined), // 上传接口地址 ==> 非必传(默认为 '') + successBefore: propTypes.func.def(() => undefined), // 上传成功之前的钩子 ==> 非必传(默认为 undefined) }) const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 @@ -99,7 +101,7 @@ const deleteImg = () => { emit('update:modelValue', '') } -const { uploadUrl, httpRequest } = useUpload() +const { uploadUrl, httpRequest } = useUpload({ customApi: props.customApi }) const editImg = () => { const dom = document.querySelector(`#${uuid.value} .el-upload__input`) @@ -117,8 +119,12 @@ const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => { // 图片上传成功提示 const uploadSuccess: UploadProps['onSuccess'] = (res: any): void => { + let params = res + if (props.successBefore) { + params = props.successBefore(res) + } message.success('上传成功') - emit('update:modelValue', res.data) + emit('update:modelValue', params.data) } // 图片上传错误提示 diff --git a/src/components/UploadFile/src/useUpload.ts b/src/components/UploadFile/src/useUpload.ts index 2981e12..f718888 100644 --- a/src/components/UploadFile/src/useUpload.ts +++ b/src/components/UploadFile/src/useUpload.ts @@ -10,7 +10,7 @@ export const getUploadUrl = (): string => { return import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/infra/file/upload' } -export const useUpload = () => { +export const useUpload = (defaultParams?: { customApi: any }) => { // 后端上传地址 const uploadUrl = getUploadUrl() // 是否使用前端直连上传 @@ -40,7 +40,8 @@ export const useUpload = () => { // 模式二:后端上传 // 重写 el-upload httpRequest 文件上传成功会走成功的钩子,失败走失败的钩子 return new Promise((resolve, reject) => { - FileApi.updateFile({ file: options.file }) + const Api = defaultParams?.customApi || FileApi.updateFile + Api({ file: options.file }) .then((res) => { if (res.code === 0) { resolve(res) diff --git a/src/config/axios/service.ts b/src/config/axios/service.ts index 618f14a..d64f755 100644 --- a/src/config/axios/service.ts +++ b/src/config/axios/service.ts @@ -149,7 +149,7 @@ service.interceptors.response.use( }) } } else if (code === 500) { - ElMessage.error(t('sys.api.errMsg500')) + ElMessage.error(msg || t('sys.api.errMsg500')) return Promise.reject(new Error(msg)) } else if (code === 901) { ElMessage.error({ diff --git a/src/styles/highligt.css b/src/styles/highligt.css new file mode 100644 index 0000000..f0d9740 --- /dev/null +++ b/src/styles/highligt.css @@ -0,0 +1,142 @@ +/* VSCode Dark+ Theme for highlight.js */ + +.hljs { + background: #1e1e1e !important; + color: #d4d4d4 !important; + --el-scrollbar-opacity: 0.3; + --el-scrollbar-bg-color: var(--el-text-color-secondary); + --el-scrollbar-hover-opacity: 0.5; + --el-scrollbar-hover-bg-color: var(--el-text-color-secondary); +} + +/* 滚动条样式 */ +.hljs::-webkit-scrollbar { + width: 6px !important; +} + +.hljs::-webkit-scrollbar-thumb { + background-color: var(--el-scrollbar-bg-color) !important; + opacity: var(--el-scrollbar-opacity) !important; + border-radius: 3px !important; +} + +.hljs::-webkit-scrollbar-thumb:hover { + background-color: var(--el-scrollbar-hover-bg-color) !important; + opacity: var(--el-scrollbar-hover-opacity) !important; +} + +.hljs::-webkit-scrollbar-track { + background-color: transparent !important; +} + +.hljs-keyword { + color: #569cd6 !important; +} + +.hljs-built_in { + color: #4ec9b0 !important; +} + +.hljs-type { + color: #4ec9b0 !important; +} + +.hljs-literal { + color: #569cd6 !important; +} + +.hljs-number { + color: #b5cea8 !important; +} + +.hljs-regexp { + color: #d16969 !important; +} + +.hljs-string { + color: #ce9178 !important; +} + +.hljs-subst { + color: #d4d4d4 !important; +} + +.hljs-symbol { + color: #d4d4d4 !important; +} + +.hljs-class { + color: #4ec9b0 !important; +} + +.hljs-function { + color: #dcdcaa !important; +} + +.hljs-title { + color: #dcdcaa !important; +} + +.hljs-params { + color: #d4d4d4 !important; +} + +.hljs-comment { + color: #6a9955 !important; +} + +.hljs-doctag { + color: #608b4e !important; +} + +.hljs-meta, +.hljs-meta .hljs-keyword { + color: #9b9b9b !important; +} + +.hljs-meta .hljs-string { + color: #ce9178 !important; +} + +.hljs-attr { + color: #9cdcfe !important; +} + +.hljs-attribute { + color: #9cdcfe !important; +} + +.hljs-name { + color: #569cd6 !important; +} + +.hljs-section { + color: #d4d4d4 !important; +} + +.hljs-tag { + color: #569cd6 !important; +} + +.hljs-variable { + color: #9cdcfe !important; +} + +.hljs-template-variable { + color: #9cdcfe !important; +} + +.hljs-template-tag { + color: #569cd6 !important; +} + +/* 添加代码块样式 */ +pre code.hljs { + display: block !important; + padding: 1em !important; + overflow-x: auto !important; + border-radius: 6px !important; + font-family: 'Consolas', 'Monaco', 'Courier New', monospace !important; + font-size: 14px !important; + line-height: 1.5 !important; +} diff --git a/src/styles/index.scss b/src/styles/index.scss index 7607941..b6988e8 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -2,7 +2,7 @@ @use './FormCreate/index.scss'; @use './theme.scss'; @use 'element-plus/theme-chalk/dark/css-vars.css'; - +@import './highligt.css'; .reset-margin [class*='el-icon'] + span { margin-left: 2px !important; } diff --git a/src/views/ai/app/base/index.vue b/src/views/ai/app/base/index.vue index cd66c6d..b4c6879 100644 --- a/src/views/ai/app/base/index.vue +++ b/src/views/ai/app/base/index.vue @@ -43,7 +43,6 @@ async function fetchData() { try { const data = await getAppInfo({ appId: id, - conversationId: null }) form.value = data appStore.info = data diff --git a/src/views/ai/app/base/prompt/index.vue b/src/views/ai/app/base/prompt/index.vue index e167c3c..19c67be 100644 --- a/src/views/ai/app/base/prompt/index.vue +++ b/src/views/ai/app/base/prompt/index.vue @@ -1,18 +1,4 @@ - + - + diff --git a/src/views/ai/app/edit.vue b/src/views/ai/app/edit.vue index 0e38a29..d865b66 100644 --- a/src/views/ai/app/edit.vue +++ b/src/views/ai/app/edit.vue @@ -4,12 +4,15 @@ import { nextTick, ref } from 'vue' import { FormSchema } from '@/types/form' import { AppApi } from '@/api/new-ai/app' import { ElMessage } from 'element-plus' - +import { OssApi } from '@/api/new-ai/oss' +import type { UploadFile, UploadRequestOptions } from 'element-plus' +import { Plus } from '@element-plus/icons-vue' +import ModelSelect from '@/views/common/ModelSelect.vue' const emit = defineEmits(['reload']) const visible = ref(false) const formData = ref({}) const formRef = ref() -const schemas = ref([ +const schemas = ref>([ { field: 'name', label: '应用名称', @@ -17,14 +20,32 @@ const schemas = ref([ formItemProps: { required: true, rules: [ - { required: true, message: '请输入应用名称' }, - { min: 2, max: 20, message: '长度在2-20个字符' } - ] + { required: true, message: '请输入应用名称' }, + { min: 2, max: 20, message: '长度在2-20个字符' } + ] }, componentProps: { placeholder: '请输入应用名称' + } + }, + { + field: 'modelId', + label: '关联模型', + component: 'Input', + formItemProps: { + rules: [{ required: true, message: '请选择关联模型' }] + } + }, + { + field: 'cover', + label: '应用图标', + component: 'Input', + formItemProps: { + required: false }, - + componentProps: { + placeholder: '请输入应用图标' + } }, { field: 'description', @@ -33,37 +54,14 @@ const schemas = ref([ formItemProps: { required: true, rules: [ - { required: true, message: '请输入应用描述' }, - { min: 2, max: 200, message: '长度在2-200个字符' } - ] + { required: true, message: '请输入应用描述' }, + { min: 2, max: 200, message: '长度在2-200个字符' } + ] }, componentProps: { type: 'textarea', rows: 4, placeholder: '请输入应用描述' - }, - - }, - { - field: 'icon', - label: '应用图标', - component: 'Input', - formItemProps: { - required: false, - }, - componentProps: { - placeholder: '请输入应用图标' - } - }, - { - field: 'modelId', - label: '关联模型', - component: 'Input', - formItemProps: { - required: false, - }, - componentProps: { - placeholder: '请选择关联模型' } } ]) @@ -95,29 +93,22 @@ const show = async (data: any = {}) => { } const handleSubmit = async () => { - try { - const form = formRef.value.getElFormRef() - await form.validate() - const values = formRef.value.formModel - loading.value = true - - if (isEdit.value) { - await AppApi.updateApp(values) - ElMessage.success('更新应用成功') - } else { - await AppApi.createApp(values) - ElMessage.success('创建应用成功') - } - close() - emit('reload') - } catch (error) { - console.error('Failed to save app:', error) - ElMessage.error(isEdit.value ? '更新应用失败' : '创建应用失败') - } finally { - loading.value = false + const form = formRef.value.getElFormRef() + await form.validate() + const values = formRef.value.formModel + const Api = isEdit.value ? AppApi.updateApp : AppApi.createApp + loading.value = true + values.modelId = values.modelId?.[1] + await Api(values).finally(() => (loading.value = false)) + ElMessage.success(isEdit.value ? '更新应用成功' : '创建应用成功') + close() + emit('reload') +} +const handleImport = (params: Record) => { + return { + data: params.data.url } } - defineExpose({ show, close @@ -125,21 +116,23 @@ defineExpose({