diff --git a/ui/package.json b/ui/package.json index cc4f521d5..a4587a39e 100644 --- a/ui/package.json +++ b/ui/package.json @@ -13,11 +13,14 @@ "format": "prettier --write src/" }, "dependencies": { + "@codemirror/lang-json": "^6.0.1", + "@codemirror/theme-one-dark": "^6.1.2", "axios": "^1.8.4", "element-plus": "^2.9.7", "nprogress": "^0.2.0", "pinia": "^3.0.1", "vue": "^3.5.13", + "vue-codemirror": "^6.1.1", "vue-i18n": "^11.1.3", "vue-router": "^4.5.0" }, diff --git a/ui/src/api/model/model.ts b/ui/src/api/model/model.ts new file mode 100644 index 000000000..20b0a3dde --- /dev/null +++ b/ui/src/api/model/model.ts @@ -0,0 +1,209 @@ +import { request } from '../../request/index' +import { Result } from '@/request/Result' +import { get, post, del, put } from '@/request/index' +import { type Ref } from 'vue' +import type { + modelRequest, + Provider, + ListModelRequest, + Model, + BaseModel, + CreateModelRequest, + EditModelRequest +} from '@/api/type/model' +import type { FormField } from '@/components/dynamics-form/type' +import type { KeyValue } from '../type/common' +const prefix = '/model' +const prefix_provider = '/provider' + +/** + * 获得模型列表 + * @params 参数 name, model_type, model_name + */ +const getModel: ( + request?: ListModelRequest, + loading?: Ref +) => Promise>> = (data, loading) => { + return get(`${prefix}`, data, loading) +} + +/** + * 获得供应商列表 + */ +const getProvider: (loading?: Ref) => Promise>> = (loading) => { + return get(`${prefix_provider}`, {}, loading) +} + +/** + * 获得供应商列表 + */ +const getProviderByModelType: (model_type: string, loading?: Ref) => Promise>> = (model_type, loading) => { + return get(`${prefix_provider}`, {model_type}, loading) +} + +/** + * 获取模型创建表单 + * @param provider + * @param model_type + * @param model_name + * @param loading + * @returns + */ +const getModelCreateForm: ( + provider: string, + model_type: string, + model_name: string, + loading?: Ref +) => Promise>> = (provider, model_type, model_name, loading) => { + return get(`${prefix_provider}/model_form`, { provider, model_type, model_name }, loading) +} + +/** + * 获取模型参数表单 + * @param model_id 模型id + * @param loading + * @returns + */ +const getModelParamsForm: ( + model_id: string, + loading?: Ref +) => Promise>> = (model_id, loading) => { + return get(`model/${model_id}/model_params_form`, {}, loading) +} +/** + * 获取模型类型列表 + * @param provider 供应商 + * @param loading 加载器 + * @returns 模型类型列表 + */ +const listModelType: ( + provider: string, + loading?: Ref +) => Promise>>> = (provider, loading?: Ref) => { + return get(`${prefix_provider}/model_type_list`, { provider }, loading) +} + +/** + * 获取基础模型列表 + * @param provider + * @param model_type + * @param loading + * @returns + */ +const listBaseModel: ( + provider: string, + model_type: string, + loading?: Ref +) => Promise>> = (provider, model_type, loading) => { + return get(`${prefix_provider}/model_list`, { provider, model_type }, loading) +} + +const listBaseModelParamsForm: ( + provider: string, + model_type: string, + model_name: string, + loading?: Ref +) => Promise>> = (provider, model_type, model_name, loading) => { + return get(`${prefix_provider}/model_params_form`, { provider, model_type, model_name}, loading) +} + +/** + * 创建模型 + * @param request 请求对象 + * @param loading 加载器 + * @returns + */ +const createModel: ( + request: CreateModelRequest, + loading?: Ref +) => Promise> = (request, loading) => { + return post(`${prefix}`, request, {}, loading) +} + +/** + * 修改模型 + * @param request 請求對象 + * @param loading 加載器 + * @returns + */ +const updateModel: ( + model_id: string, + request: EditModelRequest, + loading?: Ref +) => Promise> = (model_id, request, loading) => { + return put(`${prefix}/${model_id}`, request, {}, loading) +} + +/** + * 修改模型参数配置 + * @param request 請求對象 + * @param loading 加載器 + * @returns + */ +const updateModelParamsForm: ( + model_id: string, + request: any[], + loading?: Ref +) => Promise> = (model_id, request, loading) => { + return put(`${prefix}/${model_id}/model_params_form`, request, {}, loading) +} + +/** + * 获取模型详情根据模型id 包括认证信息 + * @param model_id 模型id + * @param loading 加载器 + * @returns + */ +const getModelById: (model_id: string, loading?: Ref) => Promise> = ( + model_id, + loading +) => { + return get(`${prefix}/${model_id}`, {}, loading) +} +/** + * 获取模型信息不包括认证信息根据模型id + * @param model_id 模型id + * @param loading 加载器 + * @returns + */ +const getModelMetaById: (model_id: string, loading?: Ref) => Promise> = ( + model_id, + loading +) => { + return get(`${prefix}/${model_id}/meta`, {}, loading) +} +/** + * 暂停下载 + * @param model_id 模型id + * @param loading 加载器 + * @returns + */ +const pauseDownload: (model_id: string, loading?: Ref) => Promise> = ( + model_id, + loading +) => { + return put(`${prefix}/${model_id}/pause_download`, undefined, {}, loading) +} +const deleteModel: (model_id: string, loading?: Ref) => Promise> = ( + model_id, + loading +) => { + return del(`${prefix}/${model_id}`, undefined, {}, loading) +} +export default { + getModel, + getProvider, + getModelCreateForm, + listModelType, + listBaseModel, + listBaseModelParamsForm, + createModel, + updateModel, + deleteModel, + getModelById, + getModelMetaById, + pauseDownload, + getModelParamsForm, + updateModelParamsForm, + getProviderByModelType +} diff --git a/ui/src/api/model/provider.ts b/ui/src/api/model/provider.ts new file mode 100644 index 000000000..2099658c1 --- /dev/null +++ b/ui/src/api/model/provider.ts @@ -0,0 +1,12 @@ +import { Result } from '@/request/Result' +import { get, post } from '@/request/index' +import type { Ref } from 'vue' +const trigger: ( + provider: string, + method: string, + request_body: any, + loading?: Ref +) => Promise | string>> = (provider, method, request_body, loading) => { + return post(`provider/${provider}/${method}`, {}, request_body, loading) +} +export default { trigger, get } diff --git a/ui/src/api/type/common.ts b/ui/src/api/type/common.ts new file mode 100644 index 000000000..1912b77f8 --- /dev/null +++ b/ui/src/api/type/common.ts @@ -0,0 +1,14 @@ +interface KeyValue { + key: K + value: V +} +interface Dict { + [propName: string]: V +} + +interface pageRequest { + current_page: number + page_size: number +} + +export type { KeyValue, Dict, pageRequest } diff --git a/ui/src/api/type/model.ts b/ui/src/api/type/model.ts new file mode 100644 index 000000000..b912cae90 --- /dev/null +++ b/ui/src/api/type/model.ts @@ -0,0 +1,147 @@ +import type { Dict } from './common' +interface modelRequest { + name: string + model_type: string + model_name: string +} + +interface Provider { + /** + * 供应商代号 + */ + provider: string + /** + * 供应商名称 + */ + name: string + /** + * 供应商icon + */ + icon: string +} + +interface ListModelRequest { + /** + * 模型名称 + */ + name?: string + /** + * 模型类型 + */ + model_type?: string + /** + * 基础模型名称 + */ + model_name?: string + /** + * 供应商 + */ + provider?: string +} + +interface Model { + /** + * 主键id + */ + id: string + /** + * 模型名 + */ + name: string + /** + * 模型类型 + */ + model_type: string + user_id: string + username: string + permission_type: 'PUBLIC' | 'PRIVATE' + /** + * 基础模型 + */ + model_name: string + /** + * 认证信息 + */ + credential: any + /** + * 供应商 + */ + provider: string + /** + * 状态 + */ + status: 'SUCCESS' | 'DOWNLOAD' | 'ERROR' | 'PAUSE_DOWNLOAD' + /** + * 元数据 + */ + meta: Dict + /** + * 模型参数配置 + */ + model_params_form: Dict[] +} +interface CreateModelRequest { + /** + * 模型名 + */ + name: string + /** + * 模型类型 + */ + model_type: string + /** + * 基础模型 + */ + model_name: string + /** + * 认证信息 + */ + credential: any + /** + * 供应商 + */ + provider: string +} + +interface EditModelRequest { + /** + * 模型名 + */ + name: string + /** + * 模型类型 + */ + model_type: string + /** + * 基础模型 + */ + model_name: string + /** + * 认证信息 + */ + credential: any +} + +interface BaseModel { + /** + * 基础模型名称 + */ + name: string + /** + * 基础模型描述 + */ + desc: string + /** + * 基础模型类型 + */ + model_type: string +} +export type { + modelRequest, + Provider, + ListModelRequest, + Model, + BaseModel, + CreateModelRequest, + EditModelRequest +} diff --git a/ui/src/api/type/user.ts b/ui/src/api/type/user.ts index a45267354..11ca55dc7 100644 --- a/ui/src/api/type/user.ts +++ b/ui/src/api/type/user.ts @@ -7,6 +7,7 @@ interface User { * 用户名 */ username: string + nick_name: string /** * 邮箱 */ @@ -14,7 +15,7 @@ interface User { /** * 用户角色 */ - role: string + role: Array /** * 用户权限 */ @@ -25,7 +26,7 @@ interface User { is_edit_password?: boolean IS_XPACK?: boolean XPACK_LICENSE_IS_VALID?: boolean - language: string + language?: string } interface LoginRequest { @@ -117,5 +118,5 @@ export type { CheckCodeRequest, ResetPasswordRequest, User, - ResetCurrentUserPasswordRequest + ResetCurrentUserPasswordRequest, } diff --git a/ui/src/assets/user-icon.svg b/ui/src/assets/user-icon.svg new file mode 100644 index 000000000..5dd0f63c0 --- /dev/null +++ b/ui/src/assets/user-icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/ui/src/components/app-icon/AppIcon.vue b/ui/src/components/app-icon/AppIcon.vue new file mode 100644 index 000000000..ddf22d06e --- /dev/null +++ b/ui/src/components/app-icon/AppIcon.vue @@ -0,0 +1,32 @@ + + + + diff --git a/ui/src/components/app-icon/icons/about.ts b/ui/src/components/app-icon/icons/about.ts new file mode 100644 index 000000000..24f81e7bf --- /dev/null +++ b/ui/src/components/app-icon/icons/about.ts @@ -0,0 +1,70 @@ +import { h } from 'vue' +export default { + 'app-github': { + iconReader: () => { + return h('i', [ + h( + 'svg', + { + style: { height: '100%', width: '100%' }, + viewBox: '0 0 1024 1024', + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', + }, + [ + h('path', { + d: 'M511.6 76.3C264.3 76.2 64 276.4 64 523.5 64 718.9 189.3 885 363.8 946c23.5 5.9 19.9-10.8 19.9-22.2v-77.5c-135.7 15.9-141.2-73.9-150.3-88.9C215 726 171.5 718 184.5 703c30.9-15.9 62.4 4 98.9 57.9 26.4 39.1 77.9 32.5 104 26 5.7-23.5 17.9-44.5 34.7-60.8-140.6-25.2-199.2-111-199.2-213 0-49.5 16.3-95 48.3-131.7-20.4-60.5 1.9-112.3 4.9-120 58.1-5.2 118.5 41.6 123.2 45.3 33-8.9 70.7-13.6 112.9-13.6 42.4 0 80.2 4.9 113.5 13.9 11.3-8.6 67.3-48.8 121.3-43.9 2.9 7.7 24.7 58.3 5.5 118 32.4 36.8 48.9 82.7 48.9 132.3 0 102.2-59 188.1-200 212.9 23.5 23.2 38.1 55.4 38.1 91v112.5c0.8 9 0 17.9 15 17.9 177.1-59.7 304.6-227 304.6-424.1 0-247.2-200.4-447.3-447.5-447.3z', + fill: 'currentColor', + }), + ], + ), + ]) + }, + }, + 'app-help': { + iconReader: () => { + return h('i', [ + h( + 'svg', + { + style: { height: '100%', width: '100%' }, + viewBox: '0 0 1024 1024', + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', + }, + [ + h('path', { + d: 'M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768z m0 85.333333C252.8 981.333333 42.666667 771.2 42.666667 512S252.8 42.666667 512 42.666667s469.333333 210.133333 469.333333 469.333333-210.133333 469.333333-469.333333 469.333333z m-21.333333-298.666666h42.666666a21.333333 21.333333 0 0 1 21.333334 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333334 21.333333h-42.666666a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333zM343.466667 396.032c0.554667-4.778667 1.109333-8.746667 1.664-11.946667 8.32-46.293333 29.397333-80.341333 63.189333-102.144 26.453333-17.28 59.008-25.941333 97.621333-25.941333 50.730667 0 92.842667 12.288 126.378667 36.864 33.578667 24.533333 50.346667 60.928 50.346667 109.141333 0 29.568-7.253333 54.485333-21.888 74.752-8.533333 12.245333-24.917333 27.946667-49.152 47.061334l-23.893334 18.773333c-13.013333 10.24-21.632 22.186667-25.898666 35.84-1.152 3.712-2.176 10.624-3.072 20.736a21.333333 21.333333 0 0 1-21.248 19.498667h-47.786667a21.333333 21.333333 0 0 1-21.248-23.296c2.773333-29.696 5.717333-48.469333 8.832-56.362667 5.845333-14.677333 20.906667-31.573333 45.141333-50.688l24.533334-19.413333c8.106667-6.144 49.749333-35.456 49.749333-61.44 0-25.941333-4.522667-35.498667-17.578667-49.749334-13.013333-14.208-42.368-18.773333-68.864-18.773333-26.026667 0-48.256 6.869333-59.136 24.405333-5.034667 8.106667-9.173333 16.768-12.117333 25.6a89.472 89.472 0 0 0-3.114667 13.098667 21.333333 21.333333 0 0 1-21.034666 17.706667H364.672a21.333333 21.333333 0 0 1-21.205333-23.722667z', + fill: 'currentColor', + }), + ], + ), + ]) + }, + }, + 'app-user-manual': { + iconReader: () => { + return h('i', [ + h( + 'svg', + { + style: { height: '100%', width: '100%' }, + viewBox: '0 0 1024 1024', + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', + }, + [ + h('path', { + d: 'M768 128H256a85.333333 85.333333 0 0 0-85.333333 85.333333v426.666667h512V64h85.333333v640a21.333333 21.333333 0 0 1-21.333333 21.333333H256a85.333333 85.333333 0 0 0-0.128 170.666667H832a21.333333 21.333333 0 0 0 21.333333-21.333333V341.333333h85.333334v597.333334a42.666667 42.666667 0 0 1-42.666667 42.666666H256c-94.293333 0-170.666667-76.16-170.666667-170.410666V213.248C85.333333 119.04 161.706667 42.666667 256 42.666667h469.333333a42.666667 42.666667 0 0 1 42.666667 42.666666v42.666667z', + fill: 'currentColor', + }), + h('path', { + d: 'M277.333333 768a21.333333 21.333333 0 0 0-21.333333 21.333333v42.666667a21.333333 21.333333 0 0 0 21.333333 21.333333h469.333334a21.333333 21.333333 0 0 0 21.333333-21.333333v-42.666667a21.333333 21.333333 0 0 0-21.333333-21.333333h-469.333334z', + fill: 'currentColor', + }), + ], + ), + ]) + }, + }, +} diff --git a/ui/src/components/app-icon/index.ts b/ui/src/components/app-icon/index.ts new file mode 100644 index 000000000..c18798afa --- /dev/null +++ b/ui/src/components/app-icon/index.ts @@ -0,0 +1,80 @@ +import { h } from 'vue' +const iconsImport: any = import.meta.glob('./icons/*.ts', { eager: true, import: 'default' }) +const dynamicIcons = Object.values(iconsImport).reduce( + (acc: Record, module) => ({ + ...acc, + ...(typeof module === 'object' && module !== null ? module : {}), + }), + {} as Record, +) +export const iconMap: any = { + 'app-warning': { + iconReader: () => { + return h('i', [ + h( + 'svg', + { + style: { height: '100%', width: '100%' }, + viewBox: '0 0 1024 1024', + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', + }, + [ + h('path', { + d: 'M512 234.666667A53.333333 53.333333 0 1 1 512 341.333333a53.333333 53.333333 0 0 1 0-106.666666zM522.666667 384h-64a21.333333 21.333333 0 0 0-21.333334 21.333333v42.666667a21.333333 21.333333 0 0 0 21.333334 21.333333h21.333333v213.333334H426.666667a21.333333 21.333333 0 0 0-21.333334 21.333333v42.666667a21.333333 21.333333 0 0 0 21.333334 21.333333h192a21.333333 21.333333 0 0 0 21.333333-21.333333v-42.666667a21.333333 21.333333 0 0 0-21.333333-21.333333h-53.333334v-256a42.666667 42.666667 0 0 0-42.666666-42.666667z', + fill: 'currentColor', + }), + h('path', { + d: 'M512 981.333333C252.8 981.333333 42.666667 771.2 42.666667 512S252.8 42.666667 512 42.666667s469.333333 210.133333 469.333333 469.333333-210.133333 469.333333-469.333333 469.333333z m0-85.333333a384 384 0 1 0 0-768 384 384 0 0 0 0 768z', + fill: 'currentColor', + }), + ], + ), + ]) + }, + }, + 'app-warning-colorful': { + iconReader: () => { + return h('i', [ + h( + 'svg', + { + style: { height: '100%', width: '100%' }, + viewBox: '0 0 1024 1024', + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', + }, + [ + h('path', { + d: 'M42.666667 512c0 259.2 210.133333 469.333333 469.333333 469.333333s469.333333-210.133333 469.333333-469.333333S771.2 42.666667 512 42.666667 42.666667 252.8 42.666667 512z m469.333333-277.333333A53.333333 53.333333 0 1 1 512 341.333333a53.333333 53.333333 0 0 1 0-106.666666zM458.666667 384h64a42.666667 42.666667 0 0 1 42.666666 42.666667v256h53.333334a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333H426.666667a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333h53.333333v-213.333334h-21.333333a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333z', + fill: '#3370FF', + }), + ], + ), + ]) + }, + }, + 'app-copy': { + iconReader: () => { + return h('i', [ + h( + 'svg', + { + style: { height: '100%', width: '100%' }, + viewBox: '0 0 1024 1024', + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', + }, + [ + h('path', { + d: 'M213.333333 341.333333v512h426.666667V341.333333H213.333333z m512-42.666666v602.069333c0 20.949333-17.834667 37.930667-39.808 37.930667H167.808C145.834667 938.666667 128 921.685333 128 900.736V293.973333C128 272.981333 145.834667 256 167.808 256H682.666667a42.666667 42.666667 0 0 1 42.666666 42.666667z m158.165334-200.832A42.538667 42.538667 0 0 1 896 128v533.333333a21.333333 21.333333 0 0 1-21.333333 21.333334h-42.666667a21.333333 21.333333 0 0 1-21.333333-21.333334V170.666667H405.333333a21.333333 21.333333 0 0 1-21.333333-21.333334v-42.666666a21.333333 21.333333 0 0 1 21.333333-21.333334H853.333333c11.776 0 22.442667 4.778667 30.165334 12.501334z', + fill: 'currentColor', + }), + ], + ), + ]) + }, + }, + // 动态加载的图标 + ...dynamicIcons, +} diff --git a/ui/src/components/dynamics-form/Demo.vue b/ui/src/components/dynamics-form/Demo.vue new file mode 100644 index 000000000..9e179c3ce --- /dev/null +++ b/ui/src/components/dynamics-form/Demo.vue @@ -0,0 +1,299 @@ + + + diff --git a/ui/src/components/dynamics-form/DemoConstructor.vue b/ui/src/components/dynamics-form/DemoConstructor.vue new file mode 100644 index 000000000..b8e0b6082 --- /dev/null +++ b/ui/src/components/dynamics-form/DemoConstructor.vue @@ -0,0 +1,55 @@ + + + diff --git a/ui/src/components/dynamics-form/FormItem.vue b/ui/src/components/dynamics-form/FormItem.vue new file mode 100644 index 000000000..a547ebaa0 --- /dev/null +++ b/ui/src/components/dynamics-form/FormItem.vue @@ -0,0 +1,184 @@ + + + diff --git a/ui/src/components/dynamics-form/FormItemLabel.vue b/ui/src/components/dynamics-form/FormItemLabel.vue new file mode 100644 index 000000000..b84dc1eda --- /dev/null +++ b/ui/src/components/dynamics-form/FormItemLabel.vue @@ -0,0 +1,11 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/data.ts b/ui/src/components/dynamics-form/constructor/data.ts new file mode 100644 index 000000000..98ee4b0f6 --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/data.ts @@ -0,0 +1,44 @@ +import { t } from '@/locales' +const input_type_list = [ + { + label: t('dynamicsForm.input_type_list.TextInput'), + value: 'TextInput' + }, + { + label: t('dynamicsForm.input_type_list.PasswordInput'), + value: 'PasswordInput' + }, + { + label: t('dynamicsForm.input_type_list.Slider'), + value: 'Slider' + }, + { + label: t('dynamicsForm.input_type_list.SwitchInput'), + value: 'SwitchInput' + }, + { + label: t('dynamicsForm.input_type_list.SingleSelect'), + value: 'SingleSelect' + }, + { + label: t('dynamicsForm.input_type_list.MultiSelect'), + value: 'MultiSelect' + }, + { + label: t('dynamicsForm.input_type_list.DatePicker'), + value: 'DatePicker' + }, + { + label: t('dynamicsForm.input_type_list.JsonInput'), + value: 'JsonInput' + }, + { + label: t('dynamicsForm.input_type_list.RadioCard'), + value: 'RadioCard' + }, + { + label: t('dynamicsForm.input_type_list.RadioRow'), + value: 'RadioRow' + } +] +export { input_type_list } diff --git a/ui/src/components/dynamics-form/constructor/index.vue b/ui/src/components/dynamics-form/constructor/index.vue new file mode 100644 index 000000000..09127ee6d --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/index.vue @@ -0,0 +1,144 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/DatePickerConstructor.vue b/ui/src/components/dynamics-form/constructor/items/DatePickerConstructor.vue new file mode 100644 index 000000000..366885fce --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/DatePickerConstructor.vue @@ -0,0 +1,138 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/JsonInputConstructor.vue b/ui/src/components/dynamics-form/constructor/items/JsonInputConstructor.vue new file mode 100644 index 000000000..ba4ea8963 --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/JsonInputConstructor.vue @@ -0,0 +1,84 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/MultiSelectConstructor.vue b/ui/src/components/dynamics-form/constructor/items/MultiSelectConstructor.vue new file mode 100644 index 000000000..8dc7a186d --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/MultiSelectConstructor.vue @@ -0,0 +1,156 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/PasswordInputConstructor.vue b/ui/src/components/dynamics-form/constructor/items/PasswordInputConstructor.vue new file mode 100644 index 000000000..fd533607c --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/PasswordInputConstructor.vue @@ -0,0 +1,194 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/RadioCardConstructor.vue b/ui/src/components/dynamics-form/constructor/items/RadioCardConstructor.vue new file mode 100644 index 000000000..51ca7ca29 --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/RadioCardConstructor.vue @@ -0,0 +1,149 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/RadioRowConstructor.vue b/ui/src/components/dynamics-form/constructor/items/RadioRowConstructor.vue new file mode 100644 index 000000000..0b91d6acd --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/RadioRowConstructor.vue @@ -0,0 +1,151 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/SingleSelectConstructor.vue b/ui/src/components/dynamics-form/constructor/items/SingleSelectConstructor.vue new file mode 100644 index 000000000..eb671ee84 --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/SingleSelectConstructor.vue @@ -0,0 +1,150 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/SliderConstructor.vue b/ui/src/components/dynamics-form/constructor/items/SliderConstructor.vue new file mode 100644 index 000000000..942e11445 --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/SliderConstructor.vue @@ -0,0 +1,162 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/SwitchInputConstructor.vue b/ui/src/components/dynamics-form/constructor/items/SwitchInputConstructor.vue new file mode 100644 index 000000000..96cdea6ab --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/SwitchInputConstructor.vue @@ -0,0 +1,48 @@ + + + diff --git a/ui/src/components/dynamics-form/constructor/items/TextInputConstructor.vue b/ui/src/components/dynamics-form/constructor/items/TextInputConstructor.vue new file mode 100644 index 000000000..c557a9e07 --- /dev/null +++ b/ui/src/components/dynamics-form/constructor/items/TextInputConstructor.vue @@ -0,0 +1,183 @@ + + + diff --git a/ui/src/components/dynamics-form/index.ts b/ui/src/components/dynamics-form/index.ts new file mode 100644 index 000000000..f4d69a0c1 --- /dev/null +++ b/ui/src/components/dynamics-form/index.ts @@ -0,0 +1,25 @@ +import type { App } from 'vue' +import type { Dict } from '@/api/type/common' +import DynamicsForm from '@/components/dynamics-form/index.vue' +let components: Dict = import.meta.glob('@/components/dynamics-form/**/**.vue', { + eager: true +}) +components = { + ...components, + ...import.meta.glob('@/components/dynamics-form/**/**/**.vue', { + eager: true + }) +} + +const install = (app: App) => { + Object.keys(components).forEach((key: string) => { + const commentName: string = key + .substring(key.lastIndexOf('/') + 1, key.length) + .replace('.vue', '') + if (key !== '/src/components/dynamics-form/constructor/index.vue') { + app.component(commentName, components[key].default) + } + }) + app.component('DynamicsForm', DynamicsForm) +} +export default { install } diff --git a/ui/src/components/dynamics-form/index.vue b/ui/src/components/dynamics-form/index.vue new file mode 100644 index 000000000..cb4c6e58e --- /dev/null +++ b/ui/src/components/dynamics-form/index.vue @@ -0,0 +1,228 @@ + + + diff --git a/ui/src/components/dynamics-form/items/DatePicker.vue b/ui/src/components/dynamics-form/items/DatePicker.vue new file mode 100644 index 000000000..291978c9c --- /dev/null +++ b/ui/src/components/dynamics-form/items/DatePicker.vue @@ -0,0 +1,5 @@ + + + diff --git a/ui/src/components/dynamics-form/items/JsonInput.vue b/ui/src/components/dynamics-form/items/JsonInput.vue new file mode 100644 index 000000000..19b68a901 --- /dev/null +++ b/ui/src/components/dynamics-form/items/JsonInput.vue @@ -0,0 +1,143 @@ + + + diff --git a/ui/src/components/dynamics-form/items/PasswordInput.vue b/ui/src/components/dynamics-form/items/PasswordInput.vue new file mode 100644 index 000000000..2111d2461 --- /dev/null +++ b/ui/src/components/dynamics-form/items/PasswordInput.vue @@ -0,0 +1,5 @@ + + + diff --git a/ui/src/components/dynamics-form/items/TextInput.vue b/ui/src/components/dynamics-form/items/TextInput.vue new file mode 100644 index 000000000..46ca9b4e9 --- /dev/null +++ b/ui/src/components/dynamics-form/items/TextInput.vue @@ -0,0 +1,5 @@ + + + diff --git a/ui/src/components/dynamics-form/items/complex/ArrayObjectCard.vue b/ui/src/components/dynamics-form/items/complex/ArrayObjectCard.vue new file mode 100644 index 000000000..eae016df4 --- /dev/null +++ b/ui/src/components/dynamics-form/items/complex/ArrayObjectCard.vue @@ -0,0 +1,156 @@ + + + diff --git a/ui/src/components/dynamics-form/items/complex/ObjectCard.vue b/ui/src/components/dynamics-form/items/complex/ObjectCard.vue new file mode 100644 index 000000000..a007b00f8 --- /dev/null +++ b/ui/src/components/dynamics-form/items/complex/ObjectCard.vue @@ -0,0 +1,75 @@ + + + diff --git a/ui/src/components/dynamics-form/items/complex/TabCard.vue b/ui/src/components/dynamics-form/items/complex/TabCard.vue new file mode 100644 index 000000000..ff5ba793a --- /dev/null +++ b/ui/src/components/dynamics-form/items/complex/TabCard.vue @@ -0,0 +1,123 @@ + + + diff --git a/ui/src/components/dynamics-form/items/label/TooltipLabel.vue b/ui/src/components/dynamics-form/items/label/TooltipLabel.vue new file mode 100644 index 000000000..035b6bd6f --- /dev/null +++ b/ui/src/components/dynamics-form/items/label/TooltipLabel.vue @@ -0,0 +1,20 @@ + + + diff --git a/ui/src/components/dynamics-form/items/radio/Radio.vue b/ui/src/components/dynamics-form/items/radio/Radio.vue new file mode 100644 index 000000000..9c94a3f0b --- /dev/null +++ b/ui/src/components/dynamics-form/items/radio/Radio.vue @@ -0,0 +1,38 @@ + + + diff --git a/ui/src/components/dynamics-form/items/radio/RadioButton.vue b/ui/src/components/dynamics-form/items/radio/RadioButton.vue new file mode 100644 index 000000000..874d61dfc --- /dev/null +++ b/ui/src/components/dynamics-form/items/radio/RadioButton.vue @@ -0,0 +1,38 @@ + + + diff --git a/ui/src/components/dynamics-form/items/radio/RadioCard.vue b/ui/src/components/dynamics-form/items/radio/RadioCard.vue new file mode 100644 index 000000000..5aabdd9f4 --- /dev/null +++ b/ui/src/components/dynamics-form/items/radio/RadioCard.vue @@ -0,0 +1,106 @@ + + + diff --git a/ui/src/components/dynamics-form/items/radio/RadioRow.vue b/ui/src/components/dynamics-form/items/radio/RadioRow.vue new file mode 100644 index 000000000..007fab18c --- /dev/null +++ b/ui/src/components/dynamics-form/items/radio/RadioRow.vue @@ -0,0 +1,92 @@ + + + diff --git a/ui/src/components/dynamics-form/items/select/MultiSelect.vue b/ui/src/components/dynamics-form/items/select/MultiSelect.vue new file mode 100644 index 000000000..f397b37cb --- /dev/null +++ b/ui/src/components/dynamics-form/items/select/MultiSelect.vue @@ -0,0 +1,64 @@ + + + diff --git a/ui/src/components/dynamics-form/items/select/SingleSelect.vue b/ui/src/components/dynamics-form/items/select/SingleSelect.vue new file mode 100644 index 000000000..a4d765676 --- /dev/null +++ b/ui/src/components/dynamics-form/items/select/SingleSelect.vue @@ -0,0 +1,77 @@ + + + diff --git a/ui/src/components/dynamics-form/items/slider/Slider.vue b/ui/src/components/dynamics-form/items/slider/Slider.vue new file mode 100644 index 000000000..3892f1563 --- /dev/null +++ b/ui/src/components/dynamics-form/items/slider/Slider.vue @@ -0,0 +1,11 @@ + + + diff --git a/ui/src/components/dynamics-form/items/switch/SwitchInput.vue b/ui/src/components/dynamics-form/items/switch/SwitchInput.vue new file mode 100644 index 000000000..c787945f3 --- /dev/null +++ b/ui/src/components/dynamics-form/items/switch/SwitchInput.vue @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/ui/src/components/dynamics-form/items/table/ProgressTableItem.vue b/ui/src/components/dynamics-form/items/table/ProgressTableItem.vue new file mode 100644 index 000000000..baf9e3e14 --- /dev/null +++ b/ui/src/components/dynamics-form/items/table/ProgressTableItem.vue @@ -0,0 +1,70 @@ + + + diff --git a/ui/src/components/dynamics-form/items/table/TableCheckbox.vue b/ui/src/components/dynamics-form/items/table/TableCheckbox.vue new file mode 100644 index 000000000..8285689f1 --- /dev/null +++ b/ui/src/components/dynamics-form/items/table/TableCheckbox.vue @@ -0,0 +1,214 @@ + + + diff --git a/ui/src/components/dynamics-form/items/table/TableColumn.vue b/ui/src/components/dynamics-form/items/table/TableColumn.vue new file mode 100644 index 000000000..9b6989e1f --- /dev/null +++ b/ui/src/components/dynamics-form/items/table/TableColumn.vue @@ -0,0 +1,22 @@ + + + diff --git a/ui/src/components/dynamics-form/items/table/TableRadio.vue b/ui/src/components/dynamics-form/items/table/TableRadio.vue new file mode 100644 index 000000000..1bc055b3b --- /dev/null +++ b/ui/src/components/dynamics-form/items/table/TableRadio.vue @@ -0,0 +1,202 @@ + + + diff --git a/ui/src/components/dynamics-form/type.ts b/ui/src/components/dynamics-form/type.ts new file mode 100644 index 000000000..e0da49be2 --- /dev/null +++ b/ui/src/components/dynamics-form/type.ts @@ -0,0 +1,176 @@ +import type { Dict } from '@/api/type/common' + +interface ViewCardItem { + /** + * 类型 + */ + type: 'eval' | 'default' + /** + * 标题 + */ + title: string + /** + * 值 根据类型不一样 取值也不一样 default= row[value_field] eval `${parseFloat(row.number).toLocaleString("zh-CN",{style: "decimal",maximumFractionDigits:1})}%   ` + */ + value_field: string +} + +interface TableColumn { + /** + * 字段|组件名称|可计算的模板字符串 + */ + property: string + /** + *表头 + */ + label: string + /** + * 表数据字段 + */ + value_field?: string + + attrs?: Attrs + /** + * 类型 + */ + type: 'eval' | 'component' | 'default' + + props_info?: PropsInfo +} +interface ColorItem { + /** + * 颜色#f56c6c + */ + color: string + /** + * 进度 + */ + percentage: number +} +interface Attrs { + /** + * 提示语 + */ + placeholder?: string + /** + * 标签的长度,例如 '50px'。 作为 Form 直接子元素的 form-item 会继承该值。 可以使用 auto。 + */ + labelWidth?: string + /** + * 表单域标签的后缀 + */ + labelSuffix?: string + /** + * 星号的位置。 + */ + requireAsteriskPosition?: 'left' | 'right' + + color?: Array + + [propName: string]: any +} +interface PropsInfo { + /** + * 表格选择的card + */ + view_card?: Array + /** + * 表格选择 + */ + table_columns?: Array + /** + * 选中 message + */ + active_msg?: string + + /** + * 组件样式 + */ + style?: Dict + + /** + * el-form-item 样式 + */ + item_style?: Dict + /** + * 表单校验 这个和element校验一样 + */ + rules?: Dict + /** + * 默认 不为空校验提示 + */ + err_msg?: string + /** + *tabs的时候使用 + */ + tabs_label?: string + + [propName: string]: any +} + +interface FormField { + field: string + /** + * 输入框类型 + */ + input_type: string + /** + * 提示 + */ + label?: string | any + /** + * 是否 必填 + */ + required?: boolean + /** + * 默认值 + */ + default_value?: any + /** + * 是否显示默认值 + */ + show_default_value?: boolean + /** + * {field:field_value_list} 表示在 field有值 ,并且值在field_value_list中才显示 + */ + relation_show_field_dict?: Dict> + /** + * {field:field_value_list} 表示在 field有值 ,并且值在field_value_list中才 执行函数获取 数据 + */ + relation_trigger_field_dict?: Dict> + /** + * 执行器类型 OPTION_LIST请求Option_list数据 CHILD_FORMS请求子表单 + */ + trigger_type?: 'OPTION_LIST' | 'CHILD_FORMS' + /** + * 前端attr数据 + */ + attrs?: Attrs + /** + * 其他额外信息 + */ + props_info?: PropsInfo + /** + * 下拉选字段field + */ + text_field?: string + /** + * 下拉选 value + */ + value_field?: string + /** + * 下拉选数据 + */ + option_list?: Array + /** + * 供应商 + */ + provider?: string + /** + * 执行函数 + */ + method?: string + + children?: Array +} +export type { FormField } diff --git a/ui/src/components/index.ts b/ui/src/components/index.ts index c6e667fad..5cfd49ed9 100644 --- a/ui/src/components/index.ts +++ b/ui/src/components/index.ts @@ -2,10 +2,14 @@ import { type App } from 'vue' import LogoFull from './logo/LogoFull.vue' import LogoIcon from './logo/LogoIcon.vue' import SendIcon from './logo/SendIcon.vue' +import dynamicsForm from './dynamics-form' +import AppIcon from './app-icon/AppIcon.vue' export default { install(app: App) { app.component('LogoFull', LogoFull) app.component('LogoIcon', LogoIcon) app.component('SendIcon', SendIcon) + app.use(dynamicsForm) + app.component('AppIcon', AppIcon) }, } diff --git a/ui/src/layout/components/breadcrumb/index.vue b/ui/src/layout/components/breadcrumb/index.vue index 9140e8209..8b773dc55 100644 --- a/ui/src/layout/components/breadcrumb/index.vue +++ b/ui/src/layout/components/breadcrumb/index.vue @@ -129,15 +129,15 @@ - - + - + diff --git a/ui/src/layout/layout-header/avatar/index.vue b/ui/src/layout/layout-header/avatar/index.vue index ac1fcbb9e..d9735792d 100644 --- a/ui/src/layout/layout-header/avatar/index.vue +++ b/ui/src/layout/layout-header/avatar/index.vue @@ -69,19 +69,19 @@ - - - - + + + diff --git a/ui/src/layout/layout-header/top-about/index.vue b/ui/src/layout/layout-header/top-about/index.vue new file mode 100644 index 000000000..340a5c9a2 --- /dev/null +++ b/ui/src/layout/layout-header/top-about/index.vue @@ -0,0 +1,50 @@ + + diff --git a/ui/src/layout/layout-header/top-url-menu/index.vue b/ui/src/layout/layout-header/top-url-menu/index.vue deleted file mode 100644 index 1981775d9..000000000 --- a/ui/src/layout/layout-header/top-url-menu/index.vue +++ /dev/null @@ -1,48 +0,0 @@ - - diff --git a/ui/src/layout/layout-template/AppLayout.vue b/ui/src/layout/layout-template/AppLayout.vue deleted file mode 100644 index 97c6771ec..000000000 --- a/ui/src/layout/layout-template/AppLayout.vue +++ /dev/null @@ -1,19 +0,0 @@ - - - - diff --git a/ui/src/layout/layout-template/DetailLayout.vue b/ui/src/layout/layout-template/DetailLayout.vue deleted file mode 100644 index 9e1a6c201..000000000 --- a/ui/src/layout/layout-template/DetailLayout.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - - diff --git a/ui/src/layout/layout-template/SystemLayout.vue b/ui/src/layout/layout-template/MainLayout.vue similarity index 66% rename from ui/src/layout/layout-template/SystemLayout.vue rename to ui/src/layout/layout-template/MainLayout.vue index 41d6bb45d..c107a6c28 100644 --- a/ui/src/layout/layout-template/SystemLayout.vue +++ b/ui/src/layout/layout-template/MainLayout.vue @@ -1,6 +1,9 @@ diff --git a/ui/src/locales/lang/en-US/views/index.ts b/ui/src/locales/lang/en-US/views/index.ts index c63d40492..993e5fe93 100644 --- a/ui/src/locales/lang/en-US/views/index.ts +++ b/ui/src/locales/lang/en-US/views/index.ts @@ -6,7 +6,7 @@ import system from './system' import functionLib from './function-lib' import user from './user' import team from './team' -import template from './template' +import model from './model' import document from './document' import paragraph from './paragraph' import problem from './problem' @@ -22,7 +22,7 @@ export default { functionLib, user, team, - template, + model, dataset, applicationWorkflow, document, diff --git a/ui/src/locales/lang/en-US/views/template.ts b/ui/src/locales/lang/en-US/views/model.ts similarity index 99% rename from ui/src/locales/lang/en-US/views/template.ts rename to ui/src/locales/lang/en-US/views/model.ts index 0a89fcfb6..a042e3186 100644 --- a/ui/src/locales/lang/en-US/views/template.ts +++ b/ui/src/locales/lang/en-US/views/model.ts @@ -33,7 +33,7 @@ export default { IMAGE: 'Vision Model', TTI: 'Image Generation' }, - templateForm: { + modelForm: { title: { baseInfo: 'Basic Information', advancedInfo: 'Advanced Settings', diff --git a/ui/src/locales/lang/zh-CN/dynamics-form.ts b/ui/src/locales/lang/zh-CN/dynamics-form.ts new file mode 100644 index 000000000..9814c06eb --- /dev/null +++ b/ui/src/locales/lang/zh-CN/dynamics-form.ts @@ -0,0 +1,102 @@ +export default { + input_type_list: { + TextInput: '文本框', + PasswordInput: '密码框', + Slider: '滑块', + SwitchInput: '开关', + SingleSelect: '单选框', + MultiSelect: '多选框', + DatePicker: '日期', + JsonInput: 'JSON文本框', + RadioCard: '选项卡', + RadioRow: '单行选项卡' + }, + default: { + label: '默认值', + placeholder: '请输入默认值', + requiredMessage: '为必填属性', + show: '显示默认值' + }, + tip: { + requiredMessage: '不能为空', + jsonMessage: 'JSON格式不正确' + }, + searchBar: { + placeholder: '请输入关键字搜索' + }, + paramForm: { + field: { + label: '参数', + placeholder: '请输入参数', + requiredMessage: '参数 为必填属性', + requiredMessage2: '只能输入字母数字和下划线' + }, + name: { + label: '显示名称', + placeholder: '请输入显示名称', + requiredMessage: '显示名称 为必填属性' + }, + tooltip: { + label: '参数提示说明', + placeholder: '请输入参数提示说明' + }, + required: { + label: '是否必填', + requiredMessage: '是否必填 为必填属性' + }, + input_type: { + label: '组件类型', + placeholder: '请选择组件类型', + requiredMessage: '组建类型 为必填属性' + } + }, + DatePicker: { + placeholder: '选择日期', + year: '年', + month: '月', + date: '日期', + datetime: '日期时间', + dataType: { + label: '时间类型', + placeholder: '请选择时间类型' + }, + format: { + label: '格式', + placeholder: '请选择格式' + } + }, + Select: { + label: '选项值', + placeholder: '请输入选项值' + }, + tag: { + label: '标签', + placeholder: '请输入选项标签' + }, + Slider: { + showInput: { + label: '是否带输入框' + }, + valueRange: { + label: '取值范围', + minRequired: '最小值必填', + maxRequired: '最大值必填' + }, + step: { + label: '步长值', + requiredMessage1: '步长值必填', + requiredMessage2: '步长不能为0' + } + }, + TextInput: { + length: { + label: '文本长度', + minRequired: '最小长度必填', + maxRequired: '最大长度必填', + requiredMessage1: '长度在', + requiredMessage2: '到', + requiredMessage3: '个字符', + requiredMessage4: '文本长度为必填参数' + } + } +} diff --git a/ui/src/locales/lang/zh-CN/index.ts b/ui/src/locales/lang/zh-CN/index.ts index 4de1e8609..af4dd8605 100644 --- a/ui/src/locales/lang/zh-CN/index.ts +++ b/ui/src/locales/lang/zh-CN/index.ts @@ -2,12 +2,15 @@ import zhCn from 'element-plus/es/locale/lang/zh-cn' // import components from './components' import views from './views' import theme from './theme' +import layout from './layout' +import dynamicsForm from './dynamics-form' // import common from './common' -// import dynamicsForm from './dynamics-form' // import chat from './ai-chat' export default { lang: '简体中文', zhCn, views, - theme + theme, + layout, + dynamicsForm, } diff --git a/ui/src/locales/lang/zh-CN/layout.ts b/ui/src/locales/lang/zh-CN/layout.ts new file mode 100644 index 000000000..fbf8e7e93 --- /dev/null +++ b/ui/src/locales/lang/zh-CN/layout.ts @@ -0,0 +1,33 @@ +export default { + github: '项目地址', + wiki: '用户手册', + forum: '论坛求助', + logout: '退出', + apiKey: 'API Key 管理', + apiServiceAddress: 'API 服务地址', + language: '语言', + isExpire: '未上传 License 或 License 已过期。', + about: { + title: '关于', + expiredTime: '到期时间', + edition: { + label: '版本', + community: '社区版', + professional: '专业版' + }, + version: '版本号', + serialNo: '序列号', + remark: '备注', + update: '更新', + authorize: '授权给' + }, + time: { + daysLater: '天后', + hoursLater: '小时后', + expired: '已过期', + expiringSoon: '即将到期' + }, + copyright: '版权所有 © 2014-2025 杭州飞致云信息科技有限公司', + userManualUrl: 'https://maxkb.cn/docs/', + forumUrl: 'https://bbs.fit2cloud.com/c/mk/11' +} diff --git a/ui/src/locales/lang/zh-CN/views/index.ts b/ui/src/locales/lang/zh-CN/views/index.ts index 932fad0c8..dde9622cb 100644 --- a/ui/src/locales/lang/zh-CN/views/index.ts +++ b/ui/src/locales/lang/zh-CN/views/index.ts @@ -1,3 +1,5 @@ +import login from './login' +import model from './model' // import notFound from './404' // import application from './application' // import applicationOverview from './application-overview' @@ -6,15 +8,17 @@ // import functionLib from './function-lib' // import user from './user' // import team from './team' -// import template from './template' + // import document from './document' // import paragraph from './paragraph' // import problem from './problem' // import log from './log' // import applicationWorkflow from './application-workflow' -import login from './login' + // import operateLog from './operate-log' export default { + login, + model, // notFound, // application, // applicationOverview, @@ -23,12 +27,11 @@ export default { // functionLib, // user, // team, - // template, // document, // paragraph, // problem, // log, // applicationWorkflow, - login, + // operateLog } diff --git a/ui/src/locales/lang/zh-CN/views/model.ts b/ui/src/locales/lang/zh-CN/views/model.ts new file mode 100644 index 000000000..ec64bc27d --- /dev/null +++ b/ui/src/locales/lang/zh-CN/views/model.ts @@ -0,0 +1,83 @@ +export default { + title: '模型', + provider: '供应商', + providerPlaceholder: '选择供应商', + addModel: '添加模型', + searchBar: { + placeholder: '按名称搜索' + }, + delete: { + confirmTitle: '删除模型', + confirmMessage: '是否删除模型:' + }, + tip: { + createSuccessMessage: '创建模型成功', + createErrorMessage: '基础信息有填写错误', + errorMessage: '变量已存在: ', + emptyMessage1: '请先选择基础信息的模型类型和基础模型', + emptyMessage2: '所选模型不支持参数设置', + updateSuccessMessage: '修改模型成功', + saveSuccessMessage: '模型参数保存成功', + downloadError: '下载失败', + noModel: '模型在Ollama不存在' + }, + modelType: { + allModel: '全部模型', + publicModel: '公有模型', + privateModel: '私有模型', + LLM: '大语言模型', + EMBEDDING: '向量模型', + RERANKER: '重排模型', + STT: '语音识别', + TTS: '语音合成', + IMAGE: '视觉模型', + TTI: '图片生成' + }, + modelForm: { + title: { + baseInfo: '基础信息', + advancedInfo: '高级设置', + modelParams: '模型参数', + editParam: '编辑参数', + addParam: '添加参数', + paramSetting: '模型参数设置', + apiParamPassing: '接口传参' + }, + form: { + templateName: { + label: '模型名称', + placeholder: '请给基础模型设置一个名称', + tooltip: 'MaxKB 中自定义的模型名称', + requiredMessage: '模型名称不能为空' + }, + permissionType: { + label: '权限', + privateDesc: '仅当前用户使用', + publicDesc: '所有用户都可使用', + requiredMessage: '权限不能为空' + }, + model_type: { + label: '模型类型', + placeholder: '请选择模型类型', + tooltip1: '大语言模型:在应用中与AI对话的推理模型。', + tooltip2: '向量模型:在知识库中对文档内容进行向量化的模型。', + tooltip3: '语音识别:在应用中开启语音识别后用于语音转文字的模型。', + tooltip4: '语音合成:在应用中开启语音播放后用于文字转语音的模型。', + tooltip5: '重排模型:在高级编排应用中使用多路召回时,对候选分段进行重新排序的模型。', + tooltip6: '视觉模型:在高级编排应用中用于图片理解的视觉模型。', + tooltip7: '图片生成:在高级编排应用中用于图片生成的视觉模型。', + requiredMessage: '模型类型不能为空' + }, + base_model: { + label: '基础模型', + tooltip: '列表中未列出的模型,直接输入模型名称,回车即可添加', + placeholder: '自定义输入基础模型后回车即可', + requiredMessage: '基础模型不能为空' + } + } + }, + download: { + downloading: '正在下载中', + cancelDownload: '取消下载' + } +} diff --git a/ui/src/locales/lang/zh-Hant/views/index.ts b/ui/src/locales/lang/zh-Hant/views/index.ts index c63d40492..993e5fe93 100644 --- a/ui/src/locales/lang/zh-Hant/views/index.ts +++ b/ui/src/locales/lang/zh-Hant/views/index.ts @@ -6,7 +6,7 @@ import system from './system' import functionLib from './function-lib' import user from './user' import team from './team' -import template from './template' +import model from './model' import document from './document' import paragraph from './paragraph' import problem from './problem' @@ -22,7 +22,7 @@ export default { functionLib, user, team, - template, + model, dataset, applicationWorkflow, document, diff --git a/ui/src/locales/lang/zh-Hant/views/template.ts b/ui/src/locales/lang/zh-Hant/views/model.ts similarity index 98% rename from ui/src/locales/lang/zh-Hant/views/template.ts rename to ui/src/locales/lang/zh-Hant/views/model.ts index 241f9d8c5..92ee667cf 100644 --- a/ui/src/locales/lang/zh-Hant/views/template.ts +++ b/ui/src/locales/lang/zh-Hant/views/model.ts @@ -1,5 +1,5 @@ export default { - title: '模型設定', + title: '模型', provider: '供應商', providerPlaceholder: '選擇供應商', addModel: '新增模型', @@ -33,7 +33,7 @@ export default { IMAGE: '圖片理解', TTI: '圖片生成' }, - templateForm: { + modelForm: { title: { baseInfo: '基礎資訊', advancedInfo: '進階設定', diff --git a/ui/src/router/modules/model.ts b/ui/src/router/modules/model.ts index ff0f45e2b..b7b075a61 100644 --- a/ui/src/router/modules/model.ts +++ b/ui/src/router/modules/model.ts @@ -3,7 +3,7 @@ const ModelRouter = { name: 'model', meta: { title: 'views.model.title', permission: 'MODEL:READ' }, redirect: '/model', - component: () => import('@/layout/layout-template/AppLayout.vue'), + component: () => import('@/layout/layout-template/MainLayout.vue'), children: [ { path: '/model', diff --git a/ui/src/stores/modules/user.ts b/ui/src/stores/modules/user.ts index d8ff185de..8ff41f4a8 100644 --- a/ui/src/stores/modules/user.ts +++ b/ui/src/stores/modules/user.ts @@ -36,10 +36,9 @@ const useLoginStore = defineStore('user', { return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF' }, async profile(loading?: Ref) { - return UserApi.getUserProfile(loading).then((ok: { data: User }) => { - this.userInfo = ok.data - useLocalStorage(localeConfigKey, 'en-US').value = - ok.data?.language || this.getLanguage() + return UserApi.getUserProfile(loading).then((ok) => { + this.userInfo = ok + useLocalStorage(localeConfigKey, 'en-US').value = ok?.language || this.getLanguage() // return this.asyncGetProfile() }) }, diff --git a/ui/src/utils/application.ts b/ui/src/utils/application.ts new file mode 100644 index 000000000..fd7d0a201 --- /dev/null +++ b/ui/src/utils/application.ts @@ -0,0 +1,10 @@ +export const defaultIcon = '/ui/favicon.ico' + +// 是否显示字母 / icon +export function isAppIcon(url: String | undefined) { + return url === defaultIcon ? '' : url +} + +export function isWorkFlow(type: string | undefined) { + return type === 'WORK_FLOW' +} diff --git a/ui/src/utils/bus.ts b/ui/src/utils/bus.ts new file mode 100644 index 000000000..c1ab0135f --- /dev/null +++ b/ui/src/utils/bus.ts @@ -0,0 +1,8 @@ +import mitt from "mitt"; +const bus: any = {}; +const emitter = mitt(); +bus.on = emitter.on; +bus.off = emitter.off; +bus.emit = emitter.emit; + +export default bus; diff --git a/ui/src/utils/clipboard.ts b/ui/src/utils/clipboard.ts new file mode 100644 index 000000000..7ecd4f414 --- /dev/null +++ b/ui/src/utils/clipboard.ts @@ -0,0 +1,16 @@ +import Clipboard from 'vue-clipboard3' +import { MsgSuccess, MsgError } from '@/utils/message' +import { t } from '@/locales' +/* + 复制粘贴 +*/ +export async function copyClick(info: string) { + const { toClipboard } = Clipboard() + try { + await toClipboard(info) + MsgSuccess(t('common.copySuccess')) + } catch (e) { + console.error(e) + MsgError(t('common.copyError')) + } +} diff --git a/ui/src/utils/common.ts b/ui/src/utils/common.ts new file mode 100644 index 000000000..770adde26 --- /dev/null +++ b/ui/src/utils/common.ts @@ -0,0 +1,24 @@ +/** + * 拆分数组 每n个拆分为一个数组 + * @param sourceDataList 资源数据 + * @param splitNum 每多少个拆分为一个数组 + * @returns 拆分后数组 + */ +export function splitArray(sourceDataList: Array, splitNum: number) { + const count = + sourceDataList.length % splitNum == 0 + ? sourceDataList.length / splitNum + : sourceDataList.length / splitNum + 1 + const arrayList: Array> = [] + for (let i = 0; i < count; i++) { + let index = i * splitNum + const list: Array = [] + let j = 0 + while (j < splitNum && index < sourceDataList.length) { + list.push(sourceDataList[index++]) + j++ + } + arrayList.push(list) + } + return arrayList +} diff --git a/ui/src/views/model/component/AddInternalFunctionDialog.vue b/ui/src/views/model/component/AddInternalFunctionDialog.vue deleted file mode 100644 index 2f6514bc4..000000000 --- a/ui/src/views/model/component/AddInternalFunctionDialog.vue +++ /dev/null @@ -1,88 +0,0 @@ - - - diff --git a/ui/src/views/model/component/AddParamDrawer.vue b/ui/src/views/model/component/AddParamDrawer.vue new file mode 100644 index 000000000..3024bbdf9 --- /dev/null +++ b/ui/src/views/model/component/AddParamDrawer.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/ui/src/views/model/component/CreateModelDialog.vue b/ui/src/views/model/component/CreateModelDialog.vue new file mode 100644 index 000000000..88791fe87 --- /dev/null +++ b/ui/src/views/model/component/CreateModelDialog.vue @@ -0,0 +1,498 @@ + + + diff --git a/ui/src/views/model/component/EditAvatarDialog.vue b/ui/src/views/model/component/EditAvatarDialog.vue deleted file mode 100644 index 0b1c57f67..000000000 --- a/ui/src/views/model/component/EditAvatarDialog.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - diff --git a/ui/src/views/model/component/EditModel.vue b/ui/src/views/model/component/EditModel.vue new file mode 100644 index 000000000..c170aaf5a --- /dev/null +++ b/ui/src/views/model/component/EditModel.vue @@ -0,0 +1,307 @@ + + + diff --git a/ui/src/views/model/component/FieldFormDialog.vue b/ui/src/views/model/component/FieldFormDialog.vue deleted file mode 100644 index 635382a72..000000000 --- a/ui/src/views/model/component/FieldFormDialog.vue +++ /dev/null @@ -1,129 +0,0 @@ - - - diff --git a/ui/src/views/model/component/FunctionDebugDrawer.vue b/ui/src/views/model/component/FunctionDebugDrawer.vue deleted file mode 100644 index 484e4d607..000000000 --- a/ui/src/views/model/component/FunctionDebugDrawer.vue +++ /dev/null @@ -1,184 +0,0 @@ - - - - diff --git a/ui/src/views/model/component/FunctionFormDrawer.vue b/ui/src/views/model/component/FunctionFormDrawer.vue deleted file mode 100644 index 8e2fb5df6..000000000 --- a/ui/src/views/model/component/FunctionFormDrawer.vue +++ /dev/null @@ -1,518 +0,0 @@ - - - - diff --git a/ui/src/views/model/component/InitParamDrawer.vue b/ui/src/views/model/component/InitParamDrawer.vue deleted file mode 100644 index ec6db25c1..000000000 --- a/ui/src/views/model/component/InitParamDrawer.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - - diff --git a/ui/src/views/model/component/InternalDescDrawer.vue b/ui/src/views/model/component/InternalDescDrawer.vue deleted file mode 100644 index 8940471da..000000000 --- a/ui/src/views/model/component/InternalDescDrawer.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - - diff --git a/ui/src/views/model/component/ModelCard.vue b/ui/src/views/model/component/ModelCard.vue new file mode 100644 index 000000000..1b2237767 --- /dev/null +++ b/ui/src/views/model/component/ModelCard.vue @@ -0,0 +1,281 @@ + + + diff --git a/ui/src/views/model/component/ParamSettingDialog.vue b/ui/src/views/model/component/ParamSettingDialog.vue new file mode 100644 index 000000000..61f9557bf --- /dev/null +++ b/ui/src/views/model/component/ParamSettingDialog.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/ui/src/views/model/component/PermissionDialog.vue b/ui/src/views/model/component/PermissionDialog.vue deleted file mode 100644 index 829de9f07..000000000 --- a/ui/src/views/model/component/PermissionDialog.vue +++ /dev/null @@ -1,106 +0,0 @@ - - - diff --git a/ui/src/views/model/component/SelectProviderDialog.vue b/ui/src/views/model/component/SelectProviderDialog.vue new file mode 100644 index 000000000..4108f75eb --- /dev/null +++ b/ui/src/views/model/component/SelectProviderDialog.vue @@ -0,0 +1,88 @@ + + + diff --git a/ui/src/views/model/component/data.ts b/ui/src/views/model/component/data.ts new file mode 100644 index 000000000..458bcf648 --- /dev/null +++ b/ui/src/views/model/component/data.ts @@ -0,0 +1,11 @@ +import { modelType } from '@/enums/model' +import { t } from '@/locales' +export const modelTypeList = [ + { text: t(modelType['LLM']), value: 'LLM' }, + { text: t(modelType['EMBEDDING']), value: 'EMBEDDING' }, + { text: t(modelType['RERANKER']), value: 'RERANKER' }, + { text: t(modelType['STT']), value: 'STT' }, + { text: t(modelType['TTS']), value: 'TTS' }, + { text: t(modelType['IMAGE']), value: 'IMAGE' }, + { text: t(modelType['TTI']), value: 'TTI' } +] diff --git a/ui/src/views/model/index.vue b/ui/src/views/model/index.vue index d7c61fd6c..e2d9553b9 100644 --- a/ui/src/views/model/index.vue +++ b/ui/src/views/model/index.vue @@ -1,623 +1,255 @@ - +