diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index d70a5c3b4..000000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "MaxKB", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/ui/package.json b/ui/package.json index 3d5b609ad..cc4f521d5 100644 --- a/ui/package.json +++ b/ui/package.json @@ -13,7 +13,9 @@ "format": "prettier --write src/" }, "dependencies": { + "axios": "^1.8.4", "element-plus": "^2.9.7", + "nprogress": "^0.2.0", "pinia": "^3.0.1", "vue": "^3.5.13", "vue-i18n": "^11.1.3", @@ -22,6 +24,7 @@ "devDependencies": { "@tsconfig/node22": "^22.0.1", "@types/node": "^22.14.0", + "@types/nprogress": "^0.2.3", "@vitejs/plugin-vue": "^5.2.3", "@vitejs/plugin-vue-jsx": "^4.1.2", "@vue/eslint-config-prettier": "^10.2.0", diff --git a/ui/src/api/type/login.ts b/ui/src/api/type/login.ts index 34d2243c0..d2c41a8b2 100644 --- a/ui/src/api/type/login.ts +++ b/ui/src/api/type/login.ts @@ -7,9 +7,9 @@ interface LoginRequest { * 密码 */ password: string - /** + /** * 验证码 */ - code: string + captcha: string } export type { LoginRequest } diff --git a/ui/src/api/type/user.ts b/ui/src/api/type/user.ts new file mode 100644 index 000000000..a45267354 --- /dev/null +++ b/ui/src/api/type/user.ts @@ -0,0 +1,121 @@ +interface User { + /** + * 用户id + */ + id: string + /** + * 用户名 + */ + username: string + /** + * 邮箱 + */ + email: string + /** + * 用户角色 + */ + role: string + /** + * 用户权限 + */ + permissions: Array + /** + * 是否需要修改密码 + */ + is_edit_password?: boolean + IS_XPACK?: boolean + XPACK_LICENSE_IS_VALID?: boolean + language: string +} + +interface LoginRequest { + /** + * 用户名 + */ + username: string + /** + * 密码 + */ + password: string +} + +interface RegisterRequest { + /** + * 用户名 + */ + username: string + /** + * 密码 + */ + password: string + /** + * 确定密码 + */ + re_password: string + /** + * 邮箱 + */ + email: string + /** + * 验证码 + */ + code: string +} + +interface CheckCodeRequest { + /** + * 邮箱 + */ + email: string + /** + *验证码 + */ + code: string + /** + * 类型 + */ + type: 'register' | 'reset_password' +} + +interface ResetCurrentUserPasswordRequest { + /** + * 验证码 + */ + code: string + /** + *密码 + */ + password: string + /** + * 确认密码 + */ + re_password: string +} + +interface ResetPasswordRequest { + /** + * 邮箱 + */ + email?: string + /** + * 验证码 + */ + code?: string + /** + * 密码 + */ + password: string + /** + * 确认密码 + */ + re_password: string +} + +export type { + LoginRequest, + RegisterRequest, + CheckCodeRequest, + ResetPasswordRequest, + User, + ResetCurrentUserPasswordRequest +} diff --git a/ui/src/api/user/login.ts b/ui/src/api/user/login.ts index e69de29bb..5ca2ab99f 100644 --- a/ui/src/api/user/login.ts +++ b/ui/src/api/user/login.ts @@ -0,0 +1,30 @@ +import { Result } from '@/request/Result' +import { get, post } from '@/request/index' +import type { LoginRequest } from '@/api/type/login' +import type { Ref } from 'vue' + +/** + * 登录 + * @param request 登录接口请求表单 + * @param loading 接口加载器 + * @returns 认证数据 + */ +const login: (request: LoginRequest, loading?: Ref) => Promise> = ( + request, + loading, +) => { + return post('/user/login', request, undefined, loading) +} + +/** + * 获取验证码 + * @param loading 接口加载器 + */ +const getCaptcha: (loading?: Ref) => Promise> = (loading) => { + return get('/user/captcha', undefined, loading) +} + +export default { + login, + getCaptcha, +} diff --git a/ui/src/api/user/user.ts b/ui/src/api/user/user.ts new file mode 100644 index 000000000..647d34e62 --- /dev/null +++ b/ui/src/api/user/user.ts @@ -0,0 +1,24 @@ +import { Result } from '@/request/Result' +import { get, post } from '@/request/index' +import type { User } from '@/api/type/user' +import type { Ref } from 'vue' + +/** + * 获取用户基本信息 + * @param loading 接口加载器 + * @returns 用户基本信息 + */ +const getUserProfile: (loading?: Ref) => Promise> = (loading) => { + return get('/user/profile', undefined, loading) +} + +/** + * 获取版本profile + */ +// const getProfile: (loading?: Ref) => Promise> = (loading) => { +// return get('/profile', undefined, loading) +// } + +export default { + getUserProfile, +} diff --git a/ui/src/locales/lang/en-US/index.ts b/ui/src/locales/lang/en-US/index.ts index bf56593e2..d35aa09cc 100644 --- a/ui/src/locales/lang/en-US/index.ts +++ b/ui/src/locales/lang/en-US/index.ts @@ -2,6 +2,7 @@ import en from 'element-plus/es/locale/lang/en' import components from './components' import layout from './layout' import views from './views' +import theme from './theme' import common from './common' import dynamicsForm from './dynamics-form' import chat from './ai-chat' @@ -9,6 +10,7 @@ export default { lang: 'English', layout, views, + theme, components, en, common, diff --git a/ui/src/locales/lang/en-US/theme.ts b/ui/src/locales/lang/en-US/theme.ts new file mode 100644 index 000000000..f86663b4b --- /dev/null +++ b/ui/src/locales/lang/en-US/theme.ts @@ -0,0 +1,43 @@ +export default { + title: 'Appearance Settings', + defaultSlogan: 'Ready-to-use, flexible RAG Chatbot', + platformDisplayTheme: 'Platform Display Theme', + customTheme: 'Custom Theme', + platformLoginSettings: 'Platform Login Settings', + custom: 'Custom', + pagePreview: 'Page Preview', + default: 'Default', + restoreDefaults: 'Restore Defaults', + orange: 'Orange', + green: 'Green', + purple: 'Purple', + red: 'Red', + loginBackground: 'Login Background Image', + loginLogo: 'Login Logo', + websiteLogo: 'Website Logo', + replacePicture: 'Replace Image', + websiteLogoTip: + 'Logo displayed at the top of the website. Recommended size: 48x48. Supports JPG, PNG, GIF. Maximum size: 10MB', + loginLogoTip: + 'Logo on the right side of the login page. Recommended size: 204x52. Supports JPG, PNG, GIF. Maximum size: 10MB', + loginBackgroundTip: + 'Left-side background image. Vector graphics recommended size: 576x900; Bitmap recommended size: 1152x1800. Supports JPG, PNG, GIF. Maximum size: 10MB', + websiteName: 'Website Name', + websiteNamePlaceholder: 'Please enter the website name', + websiteNameTip: 'The platform name displayed in the web page tab', + websiteSlogan: 'Welcome Slogan', + websiteSloganPlaceholder: 'Please enter the welcome slogan', + websiteSloganTip: 'The welcome slogan below the product logo', + + defaultTip: 'The default is the MaxKB platform interface, supports custom settings', + logoDefaultTip: 'The default is the MaxKB login interface, supports custom settings', + platformSetting: 'Platform Settings', + showUserManual: 'Show User Manual', + showForum: 'Show Forum Support', + showProject: 'Show Project Address', + urlPlaceholder: 'Please enter the URL address', + abandonUpdate: 'Abandon Update', + saveAndApply: 'Save and Apply', + fileMessageError: 'File size exceeds 10MB', + saveSuccess: 'Appearance settings successfully applied', +} diff --git a/ui/src/locales/lang/en-US/views/login.ts b/ui/src/locales/lang/en-US/views/login.ts index dc2edba57..a0c1bb262 100644 --- a/ui/src/locales/lang/en-US/views/login.ts +++ b/ui/src/locales/lang/en-US/views/login.ts @@ -1,5 +1,25 @@ export default { title: 'Login', + loginForm: { + username: { + label: 'Username', + placeholder: 'Please enter username', + requiredMessage: 'Please enter username', + lengthMessage: 'Length must be between 6 and 20 words', + }, + password: { + label: 'Login Password', + placeholder: 'Please enter password', + requiredMessage: 'Please enter password', + lengthMessage: 'Length must be between 6 and 20 words', + }, + captcha: { + label: 'Verification Code', + placeholder: 'Please enter verification code', + requiredMessage: 'Please enter verification code', + validatorMessage: 'Verification code is incorrect', + }, + }, jump_tip: 'You will be redirected to the authentication source page for authentication', jump: 'Redirect', resetPassword: 'Change Password', @@ -9,7 +29,7 @@ export default { login: 'Login', register: 'Register', backLogin: 'Back to Login', - checkCode: 'Verify Now' + checkCode: 'Verify Now', }, newPassword: 'New Password', enterPassword: 'Please enter your new password', @@ -19,6 +39,6 @@ export default { placeholder: 'Please enter the verification code', getVerificationCode: 'Get Verification Code', successMessage: 'Verification code sent successfully', - resend: 'Resend' - } + resend: 'Resend', + }, } diff --git a/ui/src/locales/lang/en-US/views/system.ts b/ui/src/locales/lang/en-US/views/system.ts index 303d1175d..46866e9f9 100644 --- a/ui/src/locales/lang/en-US/views/system.ts +++ b/ui/src/locales/lang/en-US/views/system.ts @@ -93,48 +93,6 @@ export default { access: 'Access' } }, - theme: { - title: 'Appearance Settings', - platformDisplayTheme: 'Platform Display Theme', - customTheme: 'Custom Theme', - platformLoginSettings: 'Platform Login Settings', - custom: 'Custom', - pagePreview: 'Page Preview', - default: 'Default', - restoreDefaults: 'Restore Defaults', - orange: 'Orange', - green: 'Green', - purple: 'Purple', - red: 'Red', - loginBackground: 'Login Background Image', - loginLogo: 'Login Logo', - websiteLogo: 'Website Logo', - replacePicture: 'Replace Image', - websiteLogoTip: - 'Logo displayed at the top of the website. Recommended size: 48x48. Supports JPG, PNG, GIF. Maximum size: 10MB', - loginLogoTip: - 'Logo on the right side of the login page. Recommended size: 204x52. Supports JPG, PNG, GIF. Maximum size: 10MB', - loginBackgroundTip: - 'Left-side background image. Vector graphics recommended size: 576x900; Bitmap recommended size: 1152x1800. Supports JPG, PNG, GIF. Maximum size: 10MB', - websiteName: 'Website Name', - websiteNamePlaceholder: 'Please enter the website name', - websiteNameTip: 'The platform name displayed in the web page tab', - websiteSlogan: 'Welcome Slogan', - websiteSloganPlaceholder: 'Please enter the welcome slogan', - websiteSloganTip: 'The welcome slogan below the product logo', - defaultSlogan: 'Ready-to-use, flexible RAG Chatbot', - defaultTip: 'The default is the MaxKB platform interface, supports custom settings', - logoDefaultTip: 'The default is the MaxKB login interface, supports custom settings', - platformSetting: 'Platform Settings', - showUserManual: 'Show User Manual', - showForum: 'Show Forum Support', - showProject: 'Show Project Address', - urlPlaceholder: 'Please enter the URL address', - abandonUpdate: 'Abandon Update', - saveAndApply: 'Save and Apply', - fileMessageError: 'File size exceeds 10MB', - saveSuccess: 'Appearance settings successfully applied' - }, email: { title: 'Email Settings', smtpHost: 'SMTP Host', diff --git a/ui/src/locales/lang/en-US/views/user.ts b/ui/src/locales/lang/en-US/views/user.ts index ae41fd564..7105e3cd9 100644 --- a/ui/src/locales/lang/en-US/views/user.ts +++ b/ui/src/locales/lang/en-US/views/user.ts @@ -3,68 +3,57 @@ export default { createUser: 'Create User', editUser: 'Edit User', setting: { - updatePwd: 'Change Password' + updatePwd: 'Change Password', }, tip: { professionalMessage: 'The community edition supports up to 2 users. For more users, please upgrade to the professional edition.', - updatePwdSuccess: 'User password updated successfully' + updatePwdSuccess: 'User password updated successfully', }, delete: { confirmTitle: 'Confirm deletion of user:', confirmMessage: - 'Deleting this user will also delete all resources (APP, knowledge, models) created by this user. Please proceed with caution.' + 'Deleting this user will also delete all resources (APP, knowledge, models) created by this user. Please proceed with caution.', }, disabled: { confirmTitle: 'Confirm disable function:', confirmMessage: - 'Disabling this function will cause errors when APP that reference it are queried. Please proceed with caution.' + 'Disabling this function will cause errors when APP that reference it are queried. Please proceed with caution.', }, userForm: { form: { - username: { - label: 'Username', - placeholder: 'Please enter username', - requiredMessage: 'Please enter username', - lengthMessage: 'Length must be between 6 and 20 words' - }, nick_name: { label: 'Name', - placeholder: 'Please enter name' + placeholder: 'Please enter name', }, email: { label: 'Email', placeholder: 'Please enter email', - requiredMessage: 'Please enter email' + requiredMessage: 'Please enter email', }, phone: { label: 'Phone', - placeholder: 'Please enter phone' - }, - password: { - label: 'Login Password', - placeholder: 'Please enter password', - requiredMessage: 'Please enter password', - lengthMessage: 'Length must be between 6 and 20 words' + placeholder: 'Please enter phone', }, + new_password: { label: 'New Password', placeholder: 'Please enter new password', - requiredMessage: 'Please enter new password' + requiredMessage: 'Please enter new password', }, re_password: { label: 'Confirm Password', placeholder: 'Please enter confirm password', requiredMessage: 'Please enter confirm password', - validatorMessage: 'Passwords do not match' - } - } + validatorMessage: 'Passwords do not match', + }, + }, }, source: { label: 'User Type', local: 'System User', wecom: 'WeCom', lark: 'Lark', - dingtalk: 'DingTalk' - } + dingtalk: 'DingTalk', + }, } diff --git a/ui/src/locales/lang/zh-CN/ai-chat.ts b/ui/src/locales/lang/zh-CN/ai-chat.ts deleted file mode 100644 index 9277762c8..000000000 --- a/ui/src/locales/lang/zh-CN/ai-chat.ts +++ /dev/null @@ -1,96 +0,0 @@ -export default { - noHistory: '暂无历史记录', - createChat: '新建对话', - history: '历史记录', - only20history: '仅显示最近 20 条对话', - question_count: '条提问', - exportRecords: '导出聊天记录', - chatId: '对话 ID', - userInput: '用户输入', - quote: '引用', - download: '点击下载文件', - passwordValidator: { - title: '请输入密码打开链接', - errorMessage1: '密码不能为空', - errorMessage2: '密码错误' - }, - operation: { - play: '点击播放', - pause: '停止', - regeneration: '换个答案', - like: '赞同', - cancelLike: '取消赞同', - oppose: '反对', - cancelOppose: '取消反对', - continue: '继续', - stopChat: '停止回答', - startChat: '开始回答', - }, - tip: { - error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!', - errorIdentifyMessage: '无法识别用户身份', - errorLimitMessage: '抱歉,您的提问已达到最大限制,请明天再来吧!', - answerMessage: '抱歉,没有查找到相关内容,请重新描述您的问题或提供更多信息。', - stopAnswer: '已停止回答', - answerLoading: '回答中', - recorderTip: `

该功能需要使用麦克风,浏览器禁止不安全页面录音,解决方案如下:
-1、可开启 https 解决;
-2、若无 https 配置则需要修改浏览器安全配置,Chrome 设置如下:
-(1) 地址栏输入chrome://flags/#unsafely-treat-insecure-origin-as-secure;
-(2) 将 http 站点配置在文本框中,例如: http://127.0.0.1:8080。

`, - recorderError: '录音失败', - confirm: '我知道了', - requiredMessage: '请填写所有必填字段', - inputParamMessage1: '请在URL中填写参数', - inputParamMessage2: '的值', - prologueMessage: '抱歉,当前正在维护,无法提供服务,请稍后再试!' - }, - inputPlaceholder: { - speaking: '说话中', - recorderLoading: '转文字中', - default: '请输入问题' - }, - uploadFile: { - label: '上传文件', - most: '最多', - limit: '个,每个文件限制', - fileType: '文件类型', - tipMessage: '请在文件上传配置中选择文件类型', - limitMessage1: '最多上传', - limitMessage2: '个文件', - sizeLimit: '单个文件大小不能超过', - imageMessage: '请解析图片内容', - errorMessage: '上传失败' - }, - executionDetails: { - title: '执行详情', - paramOutputTooltip: '每个文档仅支持预览500字', - audioFile: '语音文件', - searchContent: '检索内容', - searchResult: '检索结果', - conditionResult: '判断结果', - currentChat: '本次对话', - answer: 'AI 回答', - replyContent: '回复内容', - textContent: '文本内容', - input: '输入', - output: '输出', - rerankerContent: '重排内容', - rerankerResult: '重排结果', - paragraph: '分段', - noSubmit: '用户未提交', - errMessage: '错误日志' - }, - KnowledgeSource: { - title: '知识来源', - referenceParagraph: '引用分段', - consume: '消耗tokens', - consumeTime: '耗时' - }, - paragraphSource: { - title: '知识库引用', - question: '用户问题', - optimizationQuestion: '优化后问题' - }, - editTitle: '编辑标题', -} diff --git a/ui/src/locales/lang/zh-CN/common.ts b/ui/src/locales/lang/zh-CN/common.ts deleted file mode 100644 index ba790f282..000000000 --- a/ui/src/locales/lang/zh-CN/common.ts +++ /dev/null @@ -1,63 +0,0 @@ -export default { - create: '创建', - createSuccess: '创建成功', - copy: '复制', - copySuccess: '复制成功', - copyError: '复制失败', - save: '保存', - saveSuccess: '保存成功', - delete: '删除', - deleteSuccess: '删除成功', - setting: '设置', - settingSuccess: '设置成功', - submit: '提交', - submitSuccess: '提交成功', - edit: '编辑', - editSuccess: '编辑成功', - modify: '修改', - modifySuccess: '修改成功', - cancel: '取消', - confirm: '确定', - tip: '提示', - add: '添加', - refresh: '刷新', - search: '搜索', - clear: '清空', - professional: '购买专业版', - createDate: '创建日期', - createTime: '创建时间', - operation: '操作', - character: '字符', - export: '导出', - exportSuccess: '导出成功', - unavailable: '(不可用)', - public: '公有', - private: '私有', - paramSetting: '参数设置', - creator: '创建者', - author: '作者', - debug: '调试', - required: '必填', - noData: '暂无数据', - result: '结果', - fileUpload: { - document: '文档', - image: '图片', - audio: '音频', - video: '视频' - }, - status: { - label: '状态', - enableSuccess: '启用成功', - disableSuccess: '禁用成功' - }, - inputPlaceholder: '请输入', - title: '标题', - content: '内容', - param: { - outputParam: '输出参数', - inputParam: '输入参数', - initParam: '启动参数', - }, - rename:'重命名' -} diff --git a/ui/src/locales/lang/zh-CN/components.ts b/ui/src/locales/lang/zh-CN/components.ts deleted file mode 100644 index 5b871daf1..000000000 --- a/ui/src/locales/lang/zh-CN/components.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default { - quickCreatePlaceholder: '快速创建空白文档', - quickCreateName: '文档名称', - noData: '无匹配数据', - loading: '加载中', - noMore: '到底啦!', - selectParagraph: { - title: '选择分段', - error: '仅执行未成功分段', - all: '全部分段' - } -} diff --git a/ui/src/locales/lang/zh-CN/dynamics-form.ts b/ui/src/locales/lang/zh-CN/dynamics-form.ts deleted file mode 100644 index 9814c06eb..000000000 --- a/ui/src/locales/lang/zh-CN/dynamics-form.ts +++ /dev/null @@ -1,102 +0,0 @@ -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 3df42d640..4de1e8609 100644 --- a/ui/src/locales/lang/zh-CN/index.ts +++ b/ui/src/locales/lang/zh-CN/index.ts @@ -1,17 +1,13 @@ import zhCn from 'element-plus/es/locale/lang/zh-cn' -import components from './components' -import layout from './layout' +// import components from './components' import views from './views' -import common from './common' -import dynamicsForm from './dynamics-form' -import chat from './ai-chat' +import theme from './theme' +// import common from './common' +// import dynamicsForm from './dynamics-form' +// import chat from './ai-chat' export default { lang: '简体中文', - layout, - views, - components, zhCn, - common, - dynamicsForm, - chat + views, + theme } diff --git a/ui/src/locales/lang/zh-CN/layout.ts b/ui/src/locales/lang/zh-CN/layout.ts deleted file mode 100644 index fbf8e7e93..000000000 --- a/ui/src/locales/lang/zh-CN/layout.ts +++ /dev/null @@ -1,33 +0,0 @@ -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/theme.ts b/ui/src/locales/lang/zh-CN/theme.ts new file mode 100644 index 000000000..5ed6a82f5 --- /dev/null +++ b/ui/src/locales/lang/zh-CN/theme.ts @@ -0,0 +1,40 @@ +export default { + title: '外观设置', + defaultSlogan: '欢迎使用 MaxKB 开源 AI 助手', + platformDisplayTheme: '平台显示主题', + customTheme: '自定义主题', + platformLoginSettings: '平台登录设置', + custom: '自定义', + pagePreview: '页面预览', + default: '默认', + restoreDefaults: '恢复默认', + orange: '活力橙', + green: '松石绿', + purple: '神秘紫', + red: '胭脂红', + loginBackground: '登录背景图', + loginLogo: '登录 Logo', + websiteLogo: '网站 Logo', + replacePicture: '替换图片', + websiteLogoTip: '顶部网站显示的 Logo,建议尺寸 48*48,支持 JPG、PNG、GIF,大小不超过 10MB', + loginLogoTip: '登录页面右侧 Logo,建议尺寸 204*52,支持 JPG、PNG、GIF,大小不超过 10 MB', + loginBackgroundTip: + '左侧背景图,矢量图建议尺寸 576*900,位图建议尺寸 1152*1800;支持 JPG、PNG、GIF,大小不超过 10 MB', + websiteName: '网站名称', + websiteNamePlaceholder: '请输入网站名称', + websiteNameTip: '显示在网页 Tab 的平台名称', + websiteSlogan: '欢迎语', + websiteSloganPlaceholder: '请输入欢迎语', + websiteSloganTip: '产品 Logo 下的欢迎语', + logoDefaultTip: '默认为 MaxKB 登录界面,支持自定义设置', + defaultTip: '默认为 MaxKB 平台界面,支持自定义设置', + platformSetting: '平台设置', + showUserManual: '显示用户手册', + showForum: '显示论坛求助', + showProject: '显示项目地址', + urlPlaceholder: '请输入 URL 地址', + abandonUpdate: '放弃更新', + saveAndApply: '保存并应用', + fileMessageError: '文件大小超过 10M', + saveSuccess: '外观设置成功', +} diff --git a/ui/src/locales/lang/zh-CN/views/404.ts b/ui/src/locales/lang/zh-CN/views/404.ts deleted file mode 100644 index a65dcbbd0..000000000 --- a/ui/src/locales/lang/zh-CN/views/404.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default { - title: "404", - message: "无法访问应用", - operate: "返回首页", -}; diff --git a/ui/src/locales/lang/zh-CN/views/application-overview.ts b/ui/src/locales/lang/zh-CN/views/application-overview.ts deleted file mode 100644 index 5c23f9ee3..000000000 --- a/ui/src/locales/lang/zh-CN/views/application-overview.ts +++ /dev/null @@ -1,112 +0,0 @@ -export default { - title: '概览', - appInfo: { - header: '应用信息', - publicAccessLink: '公开访问链接', - openText: '开', - closeText: '关', - copyLinkText: '复制链接', - refreshLinkText: '刷新链接', - demo: '演示', - embedInWebsite: '嵌入第三方', - accessControl: '访问限制', - displaySetting: '显示设置', - apiAccessCredentials: 'API 访问凭据', - apiKey: 'API Key', - refreshToken: { - msgConfirm1: '是否重新生成公开访问链接?', - msgConfirm2: - '重新生成公开访问链接会影响嵌入第三方脚本变更,需要将新脚本重新嵌入第三方,请谨慎操作!', - refreshSuccess: '刷新成功' - }, - - APIKeyDialog: { - saveSettings: '保存设置', - msgConfirm1: '是否删除API Key', - msgConfirm2: '删除API Key后将无法恢复,请确认是否删除?', - enabledSuccess: '已启用', - disabledSuccess: '已禁用' - }, - EditAvatarDialog: { - title: '应用头像', - customizeUpload: '自定义上传', - upload: '上传', - default: '默认logo', - custom: '自定义', - sizeTip: '建议尺寸 32*32,支持 JPG、PNG、GIF,大小不超过 10 MB', - fileSizeExceeded: '文件大小超过 10 MB', - uploadImagePrompt: '请上传一张图片' - }, - EmbedDialog: { - fullscreenModeTitle: '全屏模式', - copyInstructions: '复制以下代码进行嵌入', - floatingModeTitle: '浮窗模式', - mobileModeTitle: '移动端模式' - }, - LimitDialog: { - showSourceLabel: '显示知识来源', - clientQueryLimitLabel: '每个客户端提问限制', - timesDays: '次/天', - authentication: '身份验证', - authenticationValue: '验证密码', - whitelistLabel: '白名单', - whitelistPlaceholder: - '请输入允许嵌入第三方的源地址,一行一个,如:\nhttp://127.0.0.1:5678\nhttps://dataease.io' - }, - SettingAPIKeyDialog: { - dialogTitle: '设置', - allowCrossDomainLabel: '允许跨域地址', - crossDomainPlaceholder: - '请输入允许的跨域地址,开启后不输入跨域地址则不限制。\n跨域地址一行一个,如:\nhttp://127.0.0.1:5678 \nhttps://dataease.io' - }, - SettingDisplayDialog: { - dialogTitle: '显示设置', - languageLabel: '语言', - showSourceLabel: '显示知识来源', - showExecutionDetail: '显示执行详情', - restoreDefault: '恢复默认', - customThemeColor: '自定义主题色', - headerTitleFontColor: '头部标题字体颜色', - default: '默认', - askUserAvatar: '提问用户头像', - replace: '替换', - imageMessage: '建议尺寸 32*32,支持 JPG、PNG、GIF,大小不超过 10 MB', - AIAvatar: 'AI 回复头像', - floatIcon: '浮窗入口图标', - iconDefaultPosition: '图标默认位置', - iconPosition: { - left: '左', - right: '右', - bottom: '下', - top: '上' - }, - draggablePosition: '可拖拽位置', - showHistory: '显示历史记录', - displayGuide: '显示引导图(浮窗模式)', - disclaimer: '免责声明', - disclaimerValue: '「以上内容均由 AI 生成,仅供参考和借鉴」' - } - }, - monitor: { - monitoringStatistics: '监控统计', - customRange: '自定义范围', - startDatePlaceholder: '开始时间', - endDatePlaceholder: '结束时间', - pastDayOptions: { - past7Days: '过去7天', - past30Days: '过去30天', - past90Days: '过去90天', - past183Days: '过去半年', - other: '自定义' - }, - charts: { - customerTotal: '用户总数', - customerNew: '用户新增数', - queryCount: '提问次数', - tokensTotal: 'Tokens 总数', - userSatisfaction: '用户满意度', - approval: '赞同', - disapproval: '反对' - } - } -} diff --git a/ui/src/locales/lang/zh-CN/views/application-workflow.ts b/ui/src/locales/lang/zh-CN/views/application-workflow.ts deleted file mode 100644 index 010964bb0..000000000 --- a/ui/src/locales/lang/zh-CN/views/application-workflow.ts +++ /dev/null @@ -1,287 +0,0 @@ -export default { - node: '节点', - nodeName: '节点名称', - baseComponent: '基础组件', - nodeSetting: '节点设置', - workflow: '工作流', - searchBar: { - placeholder: '按名称搜索' - }, - info: { - previewVersion: '预览版本:', - saveTime: '保存时间:' - }, - setting: { - restoreVersion: '恢复版本', - restoreCurrentVersion: '恢复此版本', - addComponent: '添加组件', - public: '发布', - releaseHistory: '发布历史', - autoSave: '自动保存', - latestRelease: '最近发布', - copyParam: '复制参数', - debug: '调试', - exit: '直接退出', - exitSave: '保存并退出', - }, - tip: { - publicSuccess: '发布成功', - noData: '没有找到相关结果', - nameMessage: '名字不能为空!', - onlyRight: '只允许从右边的锚点连出', - notRecyclable: '不可循环连线', - onlyLeft: '只允许连接左边的锚点', - applicationNodeError: '该应用不可用', - functionNodeError: '该函数不可用', - repeatedNodeError: '节点名称已存在!', - cannotCopy: '不能被复制', - copyError: '已复制节点', - paramErrorMessage: '参数已存在: ', - saveMessage: '当前的更改尚未保存,是否保存后退出?', - }, - delete: { - confirmTitle: '确定删除该节点?', - deleteMessage: '节点不允许删除' - }, - control: { - zoomOut: '缩小', - zoomIn: '放大', - fitView: '适应', - retract: '收起全部节点', - extend: '展开全部节点', - beautify: '一键美化' - }, - variable: { - label: '变量', - global: '全局变量', - Referencing: '引用变量', - ReferencingRequired: '引用变量必填', - ReferencingError: '引用变量错误', - NoReferencing: '不存在的引用变量', - placeholder: '请选择变量' - }, - condition: { - title: '执行条件', - front: '前置', - AND: '所有', - OR: '任一', - text: '连线节点执行完,执行当前节点' - }, - validate: { - startNodeRequired: '开始节点必填', - startNodeOnly: '开始节点只能有一个', - baseNodeRequired: '基本信息节点必填', - baseNodeOnly: '基本信息节点只能有一个', - notInWorkFlowNode: '未在流程中的节点', - noNextNode: '不存在的下一个节点', - nodeUnavailable: '节点不可用', - needConnect1: '节点的', - needConnect2: '分支需要连接', - cannotEndNode: '节点不能当做结束节点' - }, - nodes: { - startNode: { - label: '开始', - question: '用户问题', - currentTime: '当前时间' - }, - baseNode: { - label: '基本信息', - appName: { - label: '应用名称' - }, - appDescription: { - label: '应用描述' - }, - fileUpload: { - label: '文件上传', - tooltip: '开启后,问答页面会显示上传文件的按钮。' - }, - FileUploadSetting: { - title: '文件上传设置', - maxFiles: '单次上传最多文件数', - fileLimit: '每个文件最大(MB)', - fileUploadType: { - label: '上传的文件类型', - documentText: '需要使用“文档内容提取”节点解析文档内容', - imageText: '需要使用“视觉模型”节点解析图片内容', - audioText: '需要使用“语音转文本”节点解析音频内容' - } - } - }, - aiChatNode: { - label: 'AI 对话', - text: '与 AI 大模型进行对话', - answer: 'AI 回答内容', - returnContent: { - label: '返回内容', - tooltip: `关闭后该节点的内容则不输出给用户。 - 如果你想让用户看到该节点的输出内容,请打开开关。` - }, - defaultPrompt: '已知信息', - think: '思考过程' - }, - searchDatasetNode: { - label: '知识库检索', - text: '关联知识库,查找与问题相关的分段', - paragraph_list: '检索结果的分段列表', - is_hit_handling_method_list: '满足直接回答的分段列表', - result: '检索结果', - directly_return: '满足直接回答的分段内容', - searchParam: '检索参数', - searchQuestion: { - label: '检索问题', - placeholder: '请选择检索问题', - requiredMessage: '请选择检索问题' - } - }, - questionNode: { - label: '问题优化', - text: '根据历史聊天记录优化完善当前问题,更利于匹配知识库分段', - result: '问题优化结果', - defaultPrompt1: `根据上下文优化和完善用户问题`, - defaultPrompt2: `请输出一个优化后的问题。`, - systemDefault: '你是一个问题优化大师' - }, - conditionNode: { - label: '判断器', - text: '根据不同条件执行不同的节点', - branch_name: '分支名称', - conditions: { - label: '条件', - info: '符合以下', - requiredMessage: '请选择条件' - }, - valueMessage: '请输入值', - addCondition: '添加条件', - addBranch: '添加分支' - }, - replyNode: { - label: '指定回复', - text: '指定回复内容,引用变量会转换为字符串进行输出', - content: '内容', - replyContent: { - label: '回复内容', - custom: '自定义', - reference: '引用变量' - } - }, - rerankerNode: { - label: '多路召回', - text: '使用重排模型对多个知识库的检索结果进行二次召回', - result_list: '重排结果列表', - result: '重排结果', - rerankerContent: { - label: '重排内容', - requiredMessage: '请选择重排内容' - }, - higher: '高于', - ScoreTooltip: 'Score越高相关性越强。', - max_paragraph_char_number: '最大引用字符数', - reranker_model: { - label: '重排模型', - placeholder: '请选择重排模型' - } - }, - formNode: { - label: '表单收集', - text: '在问答过程中用于收集用户信息,可以根据收集到表单数据执行后续流程', - form_content_format1: '你好,请先填写下面表单内容:', - form_content_format2: '填写后请点击【提交】按钮进行提交。', - form_data: '表单全部内容', - formContent: { - label: '表单输出内容', - requiredMessage: '请表单输出内容', - tooltip: '设置执行该节点输出的内容,{ form } 为表单的占位符。' - }, - formAllContent: '表单全部内容', - formSetting: '表单配置' - }, - documentExtractNode: { - label: '文档内容提取', - text: '提取文档中的内容', - content: '文档内容' - }, - imageUnderstandNode: { - label: '图片理解', - text: '识别出图片中的对象、场景等信息回答用户问题', - answer: 'AI 回答内容', - model: { - label: '视觉模型', - requiredMessage: '请选择视觉模型' - }, - image: { - label: '选择图片', - requiredMessage: '请选择图片' - } - }, - variableAssignNode: { - label: '变量赋值', - text: '更新全局变量的值', - assign: '赋值' - }, - imageGenerateNode: { - label: '图片生成', - text: '根据提供的文本内容生成图片', - answer: 'AI 回答内容', - model: { - label: '图片生成模型', - requiredMessage: '请选择图片生成模型' - }, - prompt: { - label: '提示词(正向)', - tooltip: '正向提示词,用来描述生成图像中期望包含的元素和视觉特点' - }, - negative_prompt: { - label: '提示词(负向)', - tooltip: '反向提示词,用来描述不希望在画面中看到的内容,可以对画面进行限制。', - placeholder: '请描述不想生成的图片内容,比如:颜色、血腥内容' - } - }, - speechToTextNode: { - label: '语音转文本', - text: '将音频通过语音识别模型转换为文本', - stt_model: { - label: '语音识别模型' - }, - audio: { - label: '选择语音文件', - placeholder: '请选择语音文件' - } - }, - textToSpeechNode: { - label: '文本转语音', - text: '将文本通过语音合成模型转换为音频', - tts_model: { - label: '语音识别模型' - }, - content: { - label: '选择文本内容' - } - }, - functionNode: { - label: '自定义函数', - text: '通过执行自定义脚本,实现数据处理' - }, - applicationNode: { - label: '应用节点' - } - }, - compare: { - is_null: '为空', - is_not_null: '不为空', - contain: '包含', - not_contain: '不包含', - eq: '等于', - ge: '大于等于', - gt: '大于', - le: '小于等于', - lt: '小于', - len_eq: '长度等于', - len_ge: '长度大于等于', - len_gt: '长度大于', - len_le: '长度小于等于', - len_lt: '长度小于' - }, - FileUploadSetting: {} -} diff --git a/ui/src/locales/lang/zh-CN/views/application.ts b/ui/src/locales/lang/zh-CN/views/application.ts deleted file mode 100644 index b818827e3..000000000 --- a/ui/src/locales/lang/zh-CN/views/application.ts +++ /dev/null @@ -1,215 +0,0 @@ -export default { - title: '应用', - createApplication: '创建应用', - importApplication: '导入应用', - copyApplication: '复制应用', - workflow: '高级编排', - simple: '简单配置', - searchBar: { - placeholder: '按名称搜索' - }, - setting: { - demo: '演示' - }, - delete: { - confirmTitle: '是否删除应用:', - confirmMessage: '删除后该应用将不再提供服务,请谨慎操作。' - }, - tip: { - ExportError: '导出失败', - professionalMessage: '社区版最多支持 5 个应用,如需拥有更多应用,请升级为专业版。', - saveErrorMessage: '保存失败,请检查输入或稍后再试', - loadingErrorMessage: '加载配置失败,请检查输入或稍后再试' - }, - applicationForm: { - title: { - appTest: '调试预览', - copy: '副本' - }, - form: { - appName: { - label: '名称', - placeholder: '请输入应用名称', - requiredMessage: '请输入应用名称' - }, - appDescription: { - label: '描述', - placeholder: '描述该应用的应用场景及用途,如:XXX 小助手回答用户提出的 XXX 产品使用问题' - }, - appType: { - label: '类型', - simplePlaceholder: '适合新手创建小助手', - workflowPlaceholder: '适合高级用户自定义小助手的工作流' - }, - appTemplate: { - blankApp: '空白应用', - assistantApp: '知识库问答助手' - }, - aiModel: { - label: 'AI 模型', - placeholder: '请选择 AI 模型' - }, - roleSettings: { - label: '系统角色', - placeholder: '你是 xxx 小助手' - }, - prompt: { - label: '提示词', - noReferences: ' (无引用知识库)', - references: ' (引用知识库)', - placeholder: '请输入提示词', - requiredMessage: '请输入提示词', - tooltip: - '通过调整提示词内容,可以引导大模型聊天方向,该提示词会被固定在上下文的开头,可以使用变量。', - noReferencesTooltip: - '通过调整提示词内容,可以引导大模型聊天方向,该提示词会被固定在上下文的开头。可以使用变量:{question} 是用户提出问题的占位符。', - referencesTooltip: - '通过调整提示词内容,可以引导大模型聊天方向,该提示词会被固定在上下文的开头。可以使用变量:{data} 是引用知识库中分段的占位符;{question} 是用户提出问题的占位符。', - defaultPrompt: `已知信息:{data} -用户问题:{question} -回答要求: - - 请使用中文回答用户问题` - }, - historyRecord: { - label: '历史聊天记录' - }, - relatedKnowledge: { - label: '关联知识库', - placeholder: '关联的知识库展示在这里' - }, - multipleRoundsDialogue: '多轮对话', - - prologue: '开场白', - defaultPrologue: - '您好,我是 XXX 小助手,您可以向我提出 XXX 使用问题。\n- XXX 主要功能有什么?\n- XXX 如何收费?\n- 需要转人工服务', - - problemOptimization: { - label: '问题优化', - tooltip: '根据历史聊天优化完善当前问题,更利于匹配知识点。' - }, - voiceInput: { - label: '语音输入', - placeholder: '请选择语音识别模型', - requiredMessage: '请选择语音输入模型', - autoSend: '自动发送' - }, - voicePlay: { - label: '语音播放', - placeholder: '请选择语音合成模型', - requiredMessage: '请选择语音播放模型', - autoPlay: '自动播放', - browser: '浏览器播放(免费)', - tts: 'TTS模型', - listeningTest: '试听' - }, - reasoningContent: { - label: '输出思考', - tooltip: '请根据模型返回的思考标签设置,标签中间的内容将会认定为思考过程', - start: '开始', - end: '结束' - } - }, - buttons: { - publish: '保存并发布', - - addModel: '添加模型' - }, - - dialog: { - addDataset: '添加关联知识库', - addDatasetPlaceholder: '所选知识库必须使用相同的 Embedding 模型', - selected: '已选', - countDataset: '个知识库', - - selectSearchMode: '检索模式', - vectorSearch: '向量检索', - vectorSearchTooltip: '向量检索是一种基于向量相似度的检索方式,适用于知识库中的大数据量场景。', - fullTextSearch: '全文检索', - fullTextSearchTooltip: - '全文检索是一种基于文本相似度的检索方式,适用于知识库中的小数据量场景。', - hybridSearch: '混合检索', - hybridSearchTooltip: - '混合检索是一种基于向量和文本相似度的检索方式,适用于知识库中的中等数据量场景。', - similarityThreshold: '相似度高于', - similarityTooltip: '相似度越高相关性越强。', - topReferences: '引用分段数 TOP', - maxCharacters: '最多引用字符数', - noReferencesAction: '无引用知识库分段时', - continueQuestioning: '继续向 AI 模型提问', - provideAnswer: '指定回答内容', - designated_answer: - '你好,我是 XXX 小助手,我的知识库只包含了 XXX 产品相关知识,请重新描述您的问题。', - defaultPrompt1: - '()里面是用户问题,根据上下文回答揣测用户问题({question}) 要求: 输出一个补全问题,并且放在', - defaultPrompt2: '标签中' - } - }, - applicationAccess: { - title: '应用接入', - wecom: '企业微信应用', - wecomTip: '打造企业微信智能应用', - dingtalk: '钉钉应用', - dingtalkTip: '打造钉钉智能应用', - wechat: '公众号', - wechatTip: '打造公众号智能应用', - lark: '飞书应用', - larkTip: '打造飞书智能应用', - slack: 'Slack', - slackTip: '打造 Slack 智能应用', - setting: '配置', - callback: '回调地址', - callbackTip: '请输入回调地址', - wecomPlatform: '企业微信后台', - wechatPlatform: '微信公众平台', - dingtalkPlatform: '钉钉开放平台', - larkPlatform: '飞书开放平台', - wecomSetting: { - title: '企业微信应用配置', - cropId: '企业 ID', - cropIdPlaceholder: '请输入企业 ID', - agentIdPlaceholder: '请输入Agent ID', - secretPlaceholder: '请输入Secret', - tokenPlaceholder: '请输入Token', - encodingAesKeyPlaceholder: '请输入EncodingAESKey', - authenticationSuccessful: '认证成功', - urlInfo: '-应用管理-自建-创建的应用-接收消息-设置 API 接收的 "URL" 中' - }, - dingtalkSetting: { - title: '钉钉应用配置', - clientIdPlaceholder: '请输入Client ID', - clientSecretPlaceholder: '请输入Client Secret', - urlInfo: '-机器人页面,设置 "消息接收模式" 为 HTTP模式 ,并把上面URL填写到"消息接收地址"中' - }, - wechatSetting: { - title: '公众号应用配置', - appId: '开发者ID (APP ID)', - appIdPlaceholder: '请输入开发者ID (APP ID)', - appSecret: '开发者密钥 (APP SECRET)', - appSecretPlaceholder: '请输入开发者密钥 (APP SECRET)', - token: '令牌 (TOKEN)', - tokenPlaceholder: '请输入令牌 (TOKEN)', - aesKey: '消息加解密密钥', - aesKeyPlaceholder: '请输入消息加解密密钥', - urlInfo: '-设置与开发-基本配置-服务器配置的 "服务器地址URL" 中' - }, - larkSetting: { - title: '飞书应用配置', - appIdPlaceholder: '请输入App ID', - appSecretPlaceholder: '请输入App Secret', - verificationTokenPlaceholder: '请输入Verification Token', - urlInfo: '-事件与回调-事件配置-配置订阅方式的 "请求地址" 中' - }, - slackSetting: { - title: 'Slack 应用配置', - signingSecretPlaceholder: '请输入 Signing Secret', - botUserTokenPlaceholder: '请输入 Bot User Token' - }, - copyUrl: '复制链接填入到' - }, - hitTest: { - title: '命中测试', - text: '针对用户提问调试段落匹配情况,保障回答效果。', - emptyMessage1: '命中段落显示在这里', - emptyMessage2: '没有命中的分段' - } -} diff --git a/ui/src/locales/lang/zh-CN/views/dataset.ts b/ui/src/locales/lang/zh-CN/views/dataset.ts deleted file mode 100644 index 5ca010525..000000000 --- a/ui/src/locales/lang/zh-CN/views/dataset.ts +++ /dev/null @@ -1,84 +0,0 @@ -export default { - title: '知识库', - createDataset: '创建知识库', - general: '通用型', - web: 'web 站点', - relatedApplications: '关联应用', - document_count: '文档数', - relatedApp_count: '关联应用', - searchBar: { - placeholder: '按名称搜索' - }, - setting: { - vectorization: '向量化', - sync: '同步' - }, - tip: { - professionalMessage: '社区版最多支持 50 个知识库,如需拥有更多知识库,请升级为专业版。', - syncSuccess: '同步任务发送成功', - updateModeMessage: '修改知识库向量模型后,需要对知识库向量化,是否继续保存?' - }, - delete: { - confirmTitle: '是否删除知识库:', - confirmMessage1: '此知识库关联', - confirmMessage2: '个应用,删除后无法恢复,请谨慎操作。' - }, - - datasetForm: { - title: { - info: '基本信息' - }, - form: { - datasetName: { - label: '知识库名称', - placeholder: '请输入知识库名称', - requiredMessage: '请输入应用名称' - }, - datasetDescription: { - label: '知识库描述', - placeholder: - '描述知识库的内容,详尽的描述将帮助AI能深入理解该知识库的内容,能更准确的检索到内容,提高该知识库的命中率。', - requiredMessage: '请输入知识库描述' - }, - EmbeddingModel: { - label: '向量模型', - placeholder: '请选择向量模型', - requiredMessage: '请输入Embedding模型' - }, - datasetType: { - label: '知识库类型', - generalInfo: '上传本地文档', - webInfo: '同步Web网站文本数据' - }, - source_url: { - label: 'Web 根地址', - placeholder: '请输入 Web 根地址', - requiredMessage: ' 请输入 Web 根地址' - }, - selector: { - label: '选择器', - placeholder: '默认为 body,可输入 .classname/#idname/tagname' - } - } - }, - ResultSuccess: { - title: '知识库创建成功', - paragraph: '分段', - paragraph_count: '个分段', - documentList: '文档列表', - loading: '导入中', - buttons: { - toDataset: '返回知识库列表', - toDocument: '前往文档' - } - }, - syncWeb: { - title: '同步知识库', - syncMethod: '同步方式', - replace: '替换同步', - replaceText: '重新获取 Web 站点文档,覆盖替换本地知识库中的文档', - complete: '整体同步', - completeText: '先删除本地知识库所有文档,重新获取 Web 站点文档', - tip: '注意:所有同步都会删除已有数据重新获取新数据,请谨慎操作。' - } -} diff --git a/ui/src/locales/lang/zh-CN/views/document.ts b/ui/src/locales/lang/zh-CN/views/document.ts deleted file mode 100644 index 154ca5745..000000000 --- a/ui/src/locales/lang/zh-CN/views/document.ts +++ /dev/null @@ -1,174 +0,0 @@ -export default { - uploadDocument: '上传文档', - importDocument: '导入文档', - syncDocument: '同步文档', - selected: '已选', - items: '项', - searchBar: { - placeholder: '按 文档名称 搜索' - }, - setting: { - migration: '迁移', - cancelGenerateQuestion: '取消生成问题', - cancelVectorization: '取消向量化', - cancelGenerate: '取消生成', - export: '导出' - }, - tip: { - saveMessage: '当前的更改尚未保存,确认退出吗?', - cancelSuccess: '批量取消成功', - sendMessage: '发送成功', - vectorizationSuccess: '批量向量化成功', - nameMessage: '文件名称不能为空!', - importMessage: '导入成功', - migrationSuccess: '迁移成功' - }, - upload: { - selectFile: '选择文件', - selectFiles: '选择文件夹', - uploadMessage: '拖拽文件至此上传或', - formats: '支持格式:', - requiredMessage: '请上传文件', - errorMessage1: '文件大小超过 100MB', - errorMessage2: '文件格式不支持', - errorMessage3: '文件不能为空', - errorMessage4: '每次最多上传50个文件', - template: '模版', - download: '下载' - }, - - fileType: { - txt: { - label: '文本文件', - tip1: '1、文件上传前,建议规范文件的分段标识', - tip2: '2、每次最多上传 50 个文件,每个文件不超过 100MB' - }, - table: { - label: '表格', - tip1: '1、点击下载对应模版并完善信息:', - tip2: '2、第一行必须是列标题,且列标题必须是有意义的术语,表中每条记录将作为一个分段', - tip3: '3、上传的表格文件中每个 sheet 会作为一个文档,sheet名称为文档名称', - tip4: '4、每次最多上传 50 个文件,每个文件不超过 100MB' - }, - QA: { - label: 'QA 问答对', - tip1: '1、点击下载对应模版并完善信息', - tip2: '2、上传的表格文件中每个 sheet 会作为一个文档,sheet名称为文档名称', - tip3: '3、每次最多上传 50 个文件,每个文件不超过 100MB' - } - }, - setRules: { - title: { - setting: '设置分段规则', - preview: '分段预览' - }, - intelligent: { - label: '智能分段(推荐)', - text: '不了解如何设置分段规则推荐使用智能分段' - }, - advanced: { - label: '高级分段', - text: '用户可根据文档规范自行设置分段标识符、分段长度以及清洗规则' - }, - patterns: { - label: '分段标识', - tooltip: '按照所选符号先后顺序做递归分割,分割结果超出分段长度将截取至分段长度。', - placeholder: '请选择' - }, - limit: { - label: '分段长度' - }, - with_filter: { - label: '自动清洗', - text: '去掉重复多余符号空格、空行、制表符' - }, - checkedConnect: { - label: '导入时添加分段标题为关联问题(适用于标题为问题的问答对)' - } - }, - buttons: { - prev: '上一步', - next: '下一步', - import: '开始导入', - preview: '生成预览' - }, - table: { - name: '文件名称', - char_length: '字符数', - paragraph: '分段', - all: '全部', - updateTime: '更新时间' - }, - fileStatus: { - label: '文件状态', - SUCCESS: '成功', - FAILURE: '失败', - EMBEDDING: '索引中', - PENDING: '排队中', - GENERATE: '生成中', - SYNC: '同步中', - REVOKE: '取消中', - finish: '完成' - }, - enableStatus: { - label: '启用状态', - enable: '开启', - close: '关闭' - }, - sync: { - label: '同步', - confirmTitle: '确认同步文档?', - confirmMessage1: '同步将删除已有数据重新获取新数据,请谨慎操作。', - confirmMessage2: '无法同步,请先去设置文档 URL地址', - successMessage: '同步文档成功' - }, - delete: { - confirmTitle1: '是否批量删除', - confirmTitle2: '个文档?', - confirmMessage: '所选文档中的分段会跟随删除,请谨慎操作。', - successMessage: '批量删除成功', - confirmTitle3: '是否删除文档:', - confirmMessage1: '此文档下的', - confirmMessage2: '个分段都会被删除,请谨慎操作。' - }, - form: { - source_url: { - label: '文档地址', - placeholder: '请输入文档地址,一行一个,地址不正确文档会导入失败。', - requiredMessage: '请输入文档地址' - }, - selector: { - label: '选择器', - placeholder: '默认为 body,可输入 .classname/#idname/tagname' - }, - hit_handling_method: { - label: '命中处理方式', - tooltip: '用户提问时,命中文档下的分段时按照设置的方式进行处理。' - }, - similarity: { - label: '相似度高于', - placeholder: '直接返回分段内容', - requiredMessage: '请输入相似度' - } - }, - hitHandlingMethod: { - optimization: '模型优化', - directly_return: '直接回答' - }, - generateQuestion: { - title: '生成问题', - successMessage: '生成问题成功', - tip1: '提示词中的 {data} 为分段内容的占位符,执行时替换为分段内容发送给 AI 模型;', - tip2: 'AI 模型根据分段内容生成相关问题,请将生成的问题放至', - tip3: '标签中,系统会自动关联标签中的问题;', - tip4: '生成效果依赖于所选模型和提示词,用户可自行调整至最佳效果。', - prompt1: `内容:{data}\n\n请总结上面的内容,并根据内容总结生成 5 个问题。\n回答要求:\n- 请只输出问题;\n- 请将每个问题放置`, - prompt2: `标签中。` - }, - feishu: { - selectDocument: '选择文档', - tip1: '仅支持文档和表格类型,文档会根据标题分段,表格会转为Markdown格式后再分段。', - tip2: '系统不存储原始文档,导入文档前,建议规范文档的分段标识。', - allCheck: '全选' - } -} diff --git a/ui/src/locales/lang/zh-CN/views/function-lib.ts b/ui/src/locales/lang/zh-CN/views/function-lib.ts deleted file mode 100644 index b0767b644..000000000 --- a/ui/src/locales/lang/zh-CN/views/function-lib.ts +++ /dev/null @@ -1,77 +0,0 @@ -export default { - title: '函数库', - internalTitle: '内置函数', - added: '已添加', - createFunction: '创建函数', - editFunction: '编辑函数', - copyFunction: '复制函数', - importFunction: '导入函数', - searchBar: { - placeholder: '按函数名称搜索' - }, - setting: { - disabled: '禁用' - }, - tip: { - saveMessage: '当前的更改尚未保存,确认退出吗?' - }, - delete: { - confirmTitle: '是否删除函数:', - confirmMessage: '删除后,引用了该函数的应用提问时会报错 ,请谨慎操作。' - }, - disabled: { - confirmTitle: '是否禁用函数:', - confirmMessage: '禁用后,引用了该函数的应用提问时会报错 ,请谨慎操作。' - }, - functionForm: { - title: { - copy: '副本', - baseInfo: '基础信息' - }, - form: { - functionName: { - label: '名称', - placeholder: '请输入函数名称', - requiredMessage: '请输入函数名称' - }, - functionDescription: { - label: '描述', - placeholder: '请输入函数的描述' - }, - permission_type: { - label: '权限', - requiredMessage: '请选择' - }, - paramName: { - label: '参数名', - placeholder: '请输入参数名', - requiredMessage: '请输入参数名' - }, - dataType: { - label: '数据类型' - }, - source: { - label: '来源', - custom: '自定义', - reference: '引用参数' - }, - required: { - label: '是否必填' - }, - param: { - paramInfo1: '使用函数时显示', - paramInfo2: '使用函数时不显示', - code: '函数内容(Python)', - selectPlaceholder: '请选择参数', - inputPlaceholder: '请输入参数值', - }, - debug: { - run: '运行', - output: '输出', - runResult: '运行结果', - runSuccess: '运行成功', - runFailed: '运行失败' - } - } - } -} diff --git a/ui/src/locales/lang/zh-CN/views/index.ts b/ui/src/locales/lang/zh-CN/views/index.ts index b8c85b031..932fad0c8 100644 --- a/ui/src/locales/lang/zh-CN/views/index.ts +++ b/ui/src/locales/lang/zh-CN/views/index.ts @@ -1,34 +1,34 @@ -import notFound from './404' -import application from './application' -import applicationOverview from './application-overview' -import dataset from './dataset' -import system from './system' -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 notFound from './404' +// import application from './application' +// import applicationOverview from './application-overview' +// import dataset from './dataset' +// import system from './system' +// 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' +// import operateLog from './operate-log' export default { - notFound, - application, - applicationOverview, - dataset, - system, - functionLib, - user, - team, - template, - document, - paragraph, - problem, - log, - applicationWorkflow, + // notFound, + // application, + // applicationOverview, + // dataset, + // system, + // functionLib, + // user, + // team, + // template, + // document, + // paragraph, + // problem, + // log, + // applicationWorkflow, login, - operateLog + // operateLog } diff --git a/ui/src/locales/lang/zh-CN/views/log.ts b/ui/src/locales/lang/zh-CN/views/log.ts deleted file mode 100644 index c866a9551..000000000 --- a/ui/src/locales/lang/zh-CN/views/log.ts +++ /dev/null @@ -1,41 +0,0 @@ -export default { - title: '对话日志', - delete: { - confirmTitle: '是否删除问题:', - confirmMessage1: '删除问题关联的', - confirmMessage2: '个分段会被取消关联,请谨慎操作。' - }, - buttons: { - clearStrategy: '清除策略', - prev: '上一条', - next: '下一条' - }, - table: { - abstract: '摘要', - chat_record_count: '对话提问数', - user: '用户', - feedback: { - label: '用户反馈', - star: '赞同', - trample: '反对' - }, - mark: '改进标注', - recenTimes: '最近对话时间' - }, - addToDataset: '添加至知识库', - daysText: '天之前的对话记录', - selectDataset: '选择知识库', - selectDatasetPlaceholder: '请选择知识库', - saveToDocument: '保存至文档', - documentPlaceholder: '请选择文档', - editContent: '修改内容', - editMark: '修改标注', - form: { - content: { - placeholder: '请输入内容' - }, - title: { - placeholder: '请给当前内容设置一个标题,以便管理查看' - } - } -} diff --git a/ui/src/locales/lang/zh-CN/views/login.ts b/ui/src/locales/lang/zh-CN/views/login.ts index c3ccf725e..fbfe3118f 100644 --- a/ui/src/locales/lang/zh-CN/views/login.ts +++ b/ui/src/locales/lang/zh-CN/views/login.ts @@ -1,5 +1,25 @@ export default { title: '普通登录', + loginForm: { + username: { + label: '用户名', + placeholder: '请输入用户名', + requiredMessage: '请输入用户名', + lengthMessage: '长度在 6 到 20 个字符', + }, + password: { + label: '登录密码', + placeholder: '请输入密码', + requiredMessage: '请输入密码', + lengthMessage: '长度在 6 到 20 个字符', + }, + captcha: { + label: '验证码', + placeholder: '请输入验证码', + requiredMessage: '请输入验证码', + validatorMessage: '验证码不正确', + }, + }, jump_tip: '即将跳转至认证源页面进行认证', jump: '跳转', resetPassword: '修改密码', @@ -9,7 +29,7 @@ export default { login: '登录', register: '注册', backLogin: '返回登录', - checkCode: '立即验证' + checkCode: '立即验证', }, newPassword: '新密码', enterPassword: '请输入修改密码', @@ -19,6 +39,6 @@ export default { placeholder: '请输入验证码', getVerificationCode: '获取验证码', successMessage: '验证码发送成功', - resend: '重新发送' - } + resend: '重新发送', + }, } diff --git a/ui/src/locales/lang/zh-CN/views/operate-log.ts b/ui/src/locales/lang/zh-CN/views/operate-log.ts deleted file mode 100644 index 880623057..000000000 --- a/ui/src/locales/lang/zh-CN/views/operate-log.ts +++ /dev/null @@ -1,30 +0,0 @@ -export default { - title: '操作日志', - table: { - menu: { - label: '操作菜单' - }, - operate: { - label: '操作' - }, - user: { - label: '操作用户' - }, - status: { - label: '状态', - success: '成功', - fail: '失败', - all: '全部' - }, - ip_address: { - label: 'IP地址' - }, - opt: { - label: 'API详情' - }, - operateTime: { - label: '操作时间' - } - }, - close: '关闭' -} diff --git a/ui/src/locales/lang/zh-CN/views/paragraph.ts b/ui/src/locales/lang/zh-CN/views/paragraph.ts deleted file mode 100644 index cf38b908f..000000000 --- a/ui/src/locales/lang/zh-CN/views/paragraph.ts +++ /dev/null @@ -1,32 +0,0 @@ -export default { - title: '段落', - paragraph_count: '段落', - editParagraph: '编辑分段', - addParagraph: '添加分段', - paragraphDetail: '分段详情', - character_count: '个字符', - setting: { - batchSelected: '批量选择', - cancelSelected: '取消选择' - }, - delete: { - confirmTitle: '是否删除段落:', - confirmMessage: '删除后无法恢复,请谨慎操作。' - }, - relatedProblem: { - title: '关联问题', - placeholder: '请选择问题' - }, - form: { - paragraphTitle: { - label: '分段标题', - placeholder: '请输入分段标题' - }, - content: { - label: '分段内容', - placeholder: '请输入分段内容', - requiredMessage1: '请输入分段内容', - requiredMessage2: '内容最多不超过 100000 个字' - } - } -} diff --git a/ui/src/locales/lang/zh-CN/views/problem.ts b/ui/src/locales/lang/zh-CN/views/problem.ts deleted file mode 100644 index bb53275aa..000000000 --- a/ui/src/locales/lang/zh-CN/views/problem.ts +++ /dev/null @@ -1,37 +0,0 @@ -export default { - title: '问题', - createProblem: '创建问题', - detailProblem: '问题详情', - quickCreateProblem: '快速创建问题', - quickCreateName: '问题', - tip: { - placeholder: '请输入问题,支持输入多个,一行一个。', - errorMessage: '问题不能为空!', - requiredMessage: '请输入问题', - relatedSuccess:'批量关联分段成功' - }, - - setting: { - batchDelete: '批量删除', - cancelRelated: '取消关联' - }, - searchBar: { - placeholder: '按名称搜索' - }, - table: { - paragraph_count: '关联分段数', - updateTime: '更新时间' - }, - delete: { - confirmTitle: '是否删除问题:', - confirmMessage1: '删除问题关联的', - confirmMessage2: '个分段会被取消关联,请谨慎操作。' - }, - relateParagraph: { - title: '关联分段', - selectDocument: '选择文档', - placeholder: '按 文档名称 搜索', - selectedParagraph: '已选分段', - count: '个' - }, -} diff --git a/ui/src/locales/lang/zh-CN/views/system.ts b/ui/src/locales/lang/zh-CN/views/system.ts deleted file mode 100644 index 9ce23d90d..000000000 --- a/ui/src/locales/lang/zh-CN/views/system.ts +++ /dev/null @@ -1,151 +0,0 @@ -export default { - title: '系统设置', - test: '测试连接', - testSuccess: '测试连接成功', - testFailed: '测试连接失败', - password: '密码', - authentication: { - title: '登录认证', - ldap: { - title: 'LDAP', - address: 'LDAP 地址', - serverPlaceholder: '请输入LDAP 地址', - bindDN: '绑定DN', - bindDNPlaceholder: '请输入绑定 DN', - ou: '用户OU', - ouPlaceholder: '请输入用户 OU', - ldap_filter: '用户过滤器', - ldap_filterPlaceholder: '请输入用户过滤器', - ldap_mapping: 'LDAP 属性映射', - ldap_mappingPlaceholder: '请输入 LDAP 属性映射', - enableAuthentication: '启用 LDAP 认证' - }, - cas: { - title: 'CAS', - ldpUri: 'ldpUri', - ldpUriPlaceholder: '请输入ldpUri', - validateUrl: '验证地址', - validateUrlPlaceholder: '请输入验证地址', - redirectUrl: '回调地址', - redirectUrlPlaceholder: '请输入回调地址', - enableAuthentication: '启用 CAS 认证' - }, - oidc: { - title: 'OIDC', - authEndpoint: '授权端地址', - authEndpointPlaceholder: '请输入授权端地址', - tokenEndpoint: 'Token端地址', - tokenEndpointPlaceholder: '请输入 Token 端地址', - userInfoEndpoint: '用户信息端地址', - userInfoEndpointPlaceholder: '请输入用户信息端地址', - scopePlaceholder: '请输入连接范围', - clientId: '客户端 ID', - clientIdPlaceholder: '请输入客户端 ID', - clientSecret: '客户端密钥', - clientSecretPlaceholder: '请输入客户端密钥', - logoutEndpoint: '注销端地址', - logoutEndpointPlaceholder: '请输入注销端地址', - redirectUrl: '回调地址', - redirectUrlPlaceholder: '请输入回调地址', - enableAuthentication: '启用 OIDC 认证' - }, - - oauth2: { - title: 'OAuth2', - authEndpoint: '授权端地址', - authEndpointPlaceholder: '请输入授权端地址', - tokenEndpoint: 'Token 端地址', - tokenEndpointPlaceholder: '请输入 Token 端地址', - userInfoEndpoint: '用户信息端地址', - userInfoEndpointPlaceholder: '请输入用户信息端地址', - scope: '连接范围', - scopePlaceholder: '请输入连接范围', - clientId: '客户端 ID', - clientIdPlaceholder: '请输入客户端 ID', - clientSecret: '客户端密钥', - clientSecretPlaceholder: '请输入客户端密钥', - redirectUrl: '回调地址', - redirectUrlPlaceholder: '请输入回调地址', - filedMapping: '字段映射', - filedMappingPlaceholder: '请输入字段映射', - enableAuthentication: '启用 OAuth2 认证' - }, - scanTheQRCode: { - title: '扫码登录', - wecom: '企业微信', - dingtalk: '钉钉', - lark: '飞书', - effective: '有效', - alreadyTurnedOn: '已开启', - notEnabled: '未开启', - validate: '校验', - validateSuccess: '校验成功', - validateFailed: '校验失败', - validateFailedTip: '请填写所有必填项并确保格式正确', - appKeyPlaceholder: '请输入 App Key', - appSecretPlaceholder: '请输入 App Secret', - corpIdPlaceholder: '请输入 Corp Id', - agentIdPlaceholder: '请输入 Agent Id', - callbackWarning: '请输入有效的 URL 地址', - larkQrCode: '飞书扫码登录', - dingtalkQrCode: '钉钉扫码登录', - setting: '设置', - access: '接入' - } - }, - theme: { - title: '外观设置', - platformDisplayTheme: '平台显示主题', - customTheme: '自定义主题', - platformLoginSettings: '平台登录设置', - custom: '自定义', - pagePreview: '页面预览', - default: '默认', - restoreDefaults: '恢复默认', - orange: '活力橙', - green: '松石绿', - purple: '神秘紫', - red: '胭脂红', - loginBackground: '登录背景图', - loginLogo: '登录 Logo', - websiteLogo: '网站 Logo', - replacePicture: '替换图片', - websiteLogoTip: '顶部网站显示的 Logo,建议尺寸 48*48,支持 JPG、PNG、GIF,大小不超过 10MB', - loginLogoTip: '登录页面右侧 Logo,建议尺寸 204*52,支持 JPG、PNG、GIF,大小不超过 10 MB', - loginBackgroundTip: - '左侧背景图,矢量图建议尺寸 576*900,位图建议尺寸 1152*1800;支持 JPG、PNG、GIF,大小不超过 10 MB', - websiteName: '网站名称', - websiteNamePlaceholder: '请输入网站名称', - websiteNameTip: '显示在网页 Tab 的平台名称', - websiteSlogan: '欢迎语', - websiteSloganPlaceholder: '请输入欢迎语', - websiteSloganTip: '产品 Logo 下的欢迎语', - defaultSlogan: '欢迎使用 MaxKB 智能知识库问答系统', - logoDefaultTip: '默认为 MaxKB 登录界面,支持自定义设置', - defaultTip: '默认为 MaxKB 平台界面,支持自定义设置', - platformSetting: '平台设置', - showUserManual: '显示用户手册', - showForum: '显示论坛求助', - showProject: '显示项目地址', - urlPlaceholder: '请输入 URL 地址', - abandonUpdate: '放弃更新', - saveAndApply: '保存并应用', - fileMessageError: '文件大小超过 10M', - saveSuccess: '外观设置成功' - }, - email: { - title: '邮箱设置', - smtpHost: 'SMTP Host', - smtpHostPlaceholder: '请输入 SMTP Host', - smtpPort: 'SMTP Port', - smtpPortPlaceholder: '请输入 SMTP Port', - smtpUser: 'SMTP 账户', - smtpUserPlaceholder: '请输入 SMTP 账户', - sendEmail: '发件人邮箱', - sendEmailPlaceholder: '请输入发件人邮箱', - smtpPassword: '发件人密码', - smtpPasswordPlaceholder: '请输入发件人密码', - enableSSL: '启用 SSL(如果 SMTP 端口是 465,通常需要启用 SSL)', - enableTLS: '启用 TLS(如果 SMTP 端口是 587,通常需要启用 TLS)' - } -} diff --git a/ui/src/locales/lang/zh-CN/views/team.ts b/ui/src/locales/lang/zh-CN/views/team.ts deleted file mode 100644 index 58a2bc30c..000000000 --- a/ui/src/locales/lang/zh-CN/views/team.ts +++ /dev/null @@ -1,31 +0,0 @@ -export default { - title: '团队成员', - member: '成员', - manage: '所有者', - permissionSetting: '权限设置', - addMember: '添加成员', - addSubTitle: '成员登录后可以访问到您授权的数据。', - searchBar: { - placeholder: '请输入用户名搜索' - }, - delete: { - button: '移除', - confirmTitle: '是否移除成员:', - confirmMessage: '移除后将会取消成员拥有的知识库和应用权限。' - }, - setting: { - management: '管理', - check: '查看' - }, - teamForm: { - form: { - userName: { - label: '用户名/邮箱', - placeholder: '请输入成员的用户名或邮箱', - requiredMessage: '请输入用户名/邮箱' - }, - - }, - - } -} diff --git a/ui/src/locales/lang/zh-CN/views/template.ts b/ui/src/locales/lang/zh-CN/views/template.ts deleted file mode 100644 index 84241990d..000000000 --- a/ui/src/locales/lang/zh-CN/views/template.ts +++ /dev/null @@ -1,83 +0,0 @@ -export default { - title: '模型设置', - provider: '供应商', - providerPlaceholder: '选择供应商', - addModel: '添加模型', - searchBar: { - placeholder: '按名称搜索' - }, - delete: { - confirmTitle: '删除模型', - confirmMessage: '是否删除模型:' - }, - tip: { - createSuccessMessage: '创建模型成功', - createErrorMessage: '基础信息有填写错误', - errorMessage: '变量已存在: ', - emptyMessage1: '请先选择基础信息的模型类型和基础模型', - emptyMessage2: '所选模型不支持参数设置', - updateSuccessMessage: '修改模型成功', - saveSuccessMessage: '模型参数保存成功', - downloadError: '下载失败', - noModel: '模型在Ollama不存在' - }, - model: { - allModel: '全部模型', - publicModel: '公有模型', - privateModel: '私有模型', - LLM: '大语言模型', - EMBEDDING: '向量模型', - RERANKER: '重排模型', - STT: '语音识别', - TTS: '语音合成', - IMAGE: '视觉模型', - TTI: '图片生成' - }, - templateForm: { - 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-CN/views/user.ts b/ui/src/locales/lang/zh-CN/views/user.ts deleted file mode 100644 index 4e2a8760f..000000000 --- a/ui/src/locales/lang/zh-CN/views/user.ts +++ /dev/null @@ -1,68 +0,0 @@ -export default { - title: '用户管理', - createUser: '创建用户', - editUser: '编辑用户', - setting: { - updatePwd: '修改用户密码' - }, - tip: { - professionalMessage: '社区版最多支持 2 个用户,如需拥有更多用户,请升级为专业版。', - updatePwdSuccess: '修改用户密码成功' - }, - delete: { - confirmTitle: '是否删除用户:', - confirmMessage: '删除用户,该用户创建的资源(应用、知识库、模型)都会删除,请谨慎操作。' - }, - disabled: { - confirmTitle: '是否禁用函数:', - confirmMessage: '禁用后,引用了该函数的应用提问时会报错 ,请谨慎操作。' - }, - userForm: { - form: { - username: { - label: '用户名', - placeholder: '请输入用户名', - requiredMessage: '请输入用户名', - lengthMessage: '长度在 6 到 20 个字符' - }, - nick_name: { - label: '姓名', - placeholder: '请输入姓名' - }, - email: { - label: '邮箱', - placeholder: '请输入邮箱', - requiredMessage: '请输入邮箱', - validatorEmail: '请输入有效邮箱格式!', - }, - phone: { - label: '手机号', - placeholder: '请输入手机号' - }, - password: { - label: '登录密码', - placeholder: '请输入密码', - requiredMessage: '请输入密码', - lengthMessage: '长度在 6 到 20 个字符' - }, - new_password: { - label: '新密码', - placeholder: '请输入新密码', - requiredMessage: '请输入新密码', - }, - re_password: { - label: '确认密码', - placeholder: '请输入确认密码', - requiredMessage: '请输入确认密码', - validatorMessage: '密码不一致', - } - } - }, - source: { - label: '用户类型', - local: '系统用户', - wecom: '企业微信', - lark: '飞书', - dingtalk: '钉钉' - } -} diff --git a/ui/src/locales/lang/zh-Hant/index.ts b/ui/src/locales/lang/zh-Hant/index.ts index eb809475d..4cdbff893 100644 --- a/ui/src/locales/lang/zh-Hant/index.ts +++ b/ui/src/locales/lang/zh-Hant/index.ts @@ -2,16 +2,18 @@ import zhTw from 'element-plus/es/locale/lang/zh-tw' import components from './components' import layout from './layout' import views from './views' +import theme from './theme' import common from './common' import dynamicsForm from './dynamics-form' import chat from './ai-chat' export default { lang: '繁體中文', layout, - common, views, + theme, + common, components, zhTw, dynamicsForm, - chat + chat, } diff --git a/ui/src/locales/lang/zh-Hant/theme.ts b/ui/src/locales/lang/zh-Hant/theme.ts new file mode 100644 index 000000000..7fc806a63 --- /dev/null +++ b/ui/src/locales/lang/zh-Hant/theme.ts @@ -0,0 +1,41 @@ +export default { + title: '外觀設置', + defaultSlogan: '歡迎使用 MaxKB 智能知識庫問答系統', + platformDisplayTheme: '平台顯示主題', + customTheme: '自定義主題', + platformLoginSettings: '平台登錄設置', + custom: '自定義', + pagePreview: '頁面預覽', + default: '默認', + restoreDefaults: '恢復默認', + orange: '活力橙', + green: '松石綠', + purple: '神秘紫', + red: '胭脂紅', + loginBackground: '登錄背景圖', + loginLogo: '登錄 Logo', + websiteLogo: '網站 Logo', + replacePicture: '替換圖片', + websiteLogoTip: '頂部網站顯示的 Logo,建議尺寸 48*48,支持 JPG、PNG、GIF,大小不超過 10MB', + loginLogoTip: '登錄頁面右側 Logo,建議尺寸 204*52,支持 JPG、PNG、GIF,大小不超過 10 MB', + loginBackgroundTip: + '左側背景圖,矢量圖建議尺寸 576*900,位圖建議尺寸 1152*1800;支持 JPG、PNG、GIF,大小不超過 10 MB', + websiteName: '網站名稱', + websiteNamePlaceholder: '請輸入網站名稱', + websiteNameTip: '顯示在網頁 Tab 的平台名稱', + websiteSlogan: '歡迎語', + websiteSloganPlaceholder: '請輸入歡迎語', + websiteSloganTip: '產品 Logo 下的歡迎語', + logoDefaultTip: '默认为 MaxKB 登錄界面,支持自定义设置', + + defaultTip: '默認為 MaxKB 平台界面,支持自定義設置', + platformSetting: '平台設置', + showUserManual: '顯示用戶手冊', + showForum: '顯示論壇求助', + showProject: '顯示項目地址', + urlPlaceholder: '請輸入 URL 地址', + abandonUpdate: '放棄更新', + saveAndApply: '保存並應用', + fileMessageError: '文件大小超過 10M', + saveSuccess: '外觀設置成功', +} diff --git a/ui/src/locales/lang/zh-Hant/views/login.ts b/ui/src/locales/lang/zh-Hant/views/login.ts index dded54730..0cd984e34 100644 --- a/ui/src/locales/lang/zh-Hant/views/login.ts +++ b/ui/src/locales/lang/zh-Hant/views/login.ts @@ -1,5 +1,25 @@ export default { title: '普通登錄', + loginForm: { + username: { + label: '使用者名稱', + placeholder: '請輸入使用者名稱', + requiredMessage: '請輸入使用者名稱', + lengthMessage: '長度須介於 6 到 20 個字元之間' + }, + password: { + label: '登入密碼', + placeholder: '請輸入密碼', + requiredMessage: '請輸入密碼', + lengthMessage: '長度須介於 6 到 20 個字元之間' + }, + captcha: { + label: '驗證碼', + placeholder: '請輸入驗證碼', + requiredMessage: '請輸入驗證碼', + validatorMessage: '驗證碼不正確', + }, + }, jump_tip: '即將跳轉至認證源頁面進行認證', jump: '跳轉', resetPassword: '修改密碼', diff --git a/ui/src/locales/lang/zh-Hant/views/system.ts b/ui/src/locales/lang/zh-Hant/views/system.ts index 10259390b..c5215e9f9 100644 --- a/ui/src/locales/lang/zh-Hant/views/system.ts +++ b/ui/src/locales/lang/zh-Hant/views/system.ts @@ -19,7 +19,7 @@ export default { ldap_filterPlaceholder: '請輸入使用者過濾器', ldap_mapping: 'LDAP 屬性對應', ldap_mappingPlaceholder: '請輸入 LDAP 屬性對應', - enableAuthentication: '啟用 LDAP 認證' + enableAuthentication: '啟用 LDAP 認證', }, cas: { title: 'CAS', @@ -29,7 +29,7 @@ export default { validateUrlPlaceholder: '請輸入驗證位址', redirectUrl: '回呼位址', redirectUrlPlaceholder: '請輸入回呼位址', - enableAuthentication: '啟用 CAS 認證' + enableAuthentication: '啟用 CAS 認證', }, oidc: { title: 'OIDC', @@ -48,7 +48,7 @@ export default { logoutEndpointPlaceholder: '請輸入登出端位址', redirectUrl: '回呼位址', redirectUrlPlaceholder: '請輸入回呼位址', - enableAuthentication: '啟用 OIDC 認證' + enableAuthentication: '啟用 OIDC 認證', }, oauth2: { @@ -69,7 +69,7 @@ export default { redirectUrlPlaceholder: '請輸入回呼位址', filedMapping: '欄位對應', filedMappingPlaceholder: '請輸入欄位對應', - enableAuthentication: '啟用 OAuth2 認證' + enableAuthentication: '啟用 OAuth2 認證', }, scanTheQRCode: { title: '掃碼登入', @@ -91,49 +91,10 @@ export default { larkQrCode: '飛書掃碼登錄', dingtalkQrCode: '釘釘掃碼登錄', setting: '設置', - access: '接入' - } - }, - theme: { - title: '外觀設置', - platformDisplayTheme: '平台顯示主題', - customTheme: '自定義主題', - platformLoginSettings: '平台登錄設置', - custom: '自定義', - pagePreview: '頁面預覽', - default: '默認', - restoreDefaults: '恢復默認', - orange: '活力橙', - green: '松石綠', - purple: '神秘紫', - red: '胭脂紅', - loginBackground: '登錄背景圖', - loginLogo: '登錄 Logo', - websiteLogo: '網站 Logo', - replacePicture: '替換圖片', - websiteLogoTip: '頂部網站顯示的 Logo,建議尺寸 48*48,支持 JPG、PNG、GIF,大小不超過 10MB', - loginLogoTip: '登錄頁面右側 Logo,建議尺寸 204*52,支持 JPG、PNG、GIF,大小不超過 10 MB', - loginBackgroundTip: - '左側背景圖,矢量圖建議尺寸 576*900,位圖建議尺寸 1152*1800;支持 JPG、PNG、GIF,大小不超過 10 MB', - websiteName: '網站名稱', - websiteNamePlaceholder: '請輸入網站名稱', - websiteNameTip: '顯示在網頁 Tab 的平台名稱', - websiteSlogan: '歡迎語', - websiteSloganPlaceholder: '請輸入歡迎語', - websiteSloganTip: '產品 Logo 下的歡迎語', - logoDefaultTip: '默认为 MaxKB 登錄界面,支持自定义设置', - defaultSlogan: '歡迎使用 MaxKB 智能知識庫問答系統', - defaultTip: '默認為 MaxKB 平台界面,支持自定義設置', - platformSetting: '平台設置', - showUserManual: '顯示用戶手冊', - showForum: '顯示論壇求助', - showProject: '顯示項目地址', - urlPlaceholder: '請輸入 URL 地址', - abandonUpdate: '放棄更新', - saveAndApply: '保存並應用', - fileMessageError: '文件大小超過 10M', - saveSuccess: '外觀設置成功' + access: '接入', + }, }, + email: { title: '郵箱設置', smtpHost: 'SMTP Host', @@ -147,6 +108,6 @@ export default { smtpPassword: '發件人密碼', smtpPasswordPlaceholder: '請輸入發件人密碼', enableSSL: '啟用 SSL(如果 SMTP 端口是 465,通常需要啟用 SSL)', - enableTLS: '啟用 TLS(如果 SMTP 端口是 587,通常需要啟用 TLS)' - } + enableTLS: '啟用 TLS(如果 SMTP 端口是 587,通常需要啟用 TLS)', + }, } diff --git a/ui/src/request/Result.ts b/ui/src/request/Result.ts new file mode 100644 index 000000000..f76b82c0b --- /dev/null +++ b/ui/src/request/Result.ts @@ -0,0 +1,19 @@ +export class Result { + message: string + code: number + data: T + constructor(message: string, code: number, data: T) { + this.message = message + this.code = code + this.data = data + } + + static success(data: any) { + return new Result('请求成功', 200, data) + } + static error(message: string, code: number) { + return new Result(message, code, null) + } +} + +export default Result diff --git a/ui/src/request/index.ts b/ui/src/request/index.ts new file mode 100644 index 000000000..77b8bc3e2 --- /dev/null +++ b/ui/src/request/index.ts @@ -0,0 +1,349 @@ +import axios, { type InternalAxiosRequestConfig, AxiosHeaders } from 'axios' +import { MsgError } from '@/utils/message' +import type { NProgress } from 'nprogress' +import type { Ref } from 'vue' +import type { Result } from '@/request/Result' +import useStore from '@/stores' +import router from '@/router' + +import { ref, type WritableComputedRef } from 'vue' + +const axiosConfig = { + baseURL: '/api', + withCredentials: false, + timeout: 600000, + headers: {}, +} + +const instance = axios.create(axiosConfig) + +/* 设置请求拦截器 */ +instance.interceptors.request.use( + (config: InternalAxiosRequestConfig) => { + if (config.headers === undefined) { + config.headers = new AxiosHeaders() + } + const { user, login } = useStore() + const token = login.getToken() + const language = user.getLanguage() + config.headers['Accept-Language'] = `${language}` + if (token) { + config.headers['AUTHORIZATION'] = `${token}` + } + return config + }, + (err: any) => { + return Promise.reject(err) + }, +) + +//设置响应拦截器 +instance.interceptors.response.use( + (response: any) => { + if (response.data) { + if (response.data.code !== 200 && !(response.data instanceof Blob)) { + if (response.config.url.includes('/application/authentication')) { + return Promise.reject(response.data) + } + if ( + !response.config.url.includes('/valid') && + !response.config.url.includes('/function_lib/debug') + ) { + MsgError(response.data.message) + return Promise.reject(response.data) + } + } + } + return response + }, + (err: any) => { + if (err.code === 'ECONNABORTED') { + MsgError(err.message) + console.error(err) + } + if (err.response?.status === 404) { + if (!err.response.config.url.includes('/application/authentication')) { + router.push('/404 ') + } + } + if (err.response?.status === 401) { + if ( + !err.response.config.url.includes('chat/open') && + !err.response.config.url.includes('application/profile') + ) { + router.push({ name: 'login' }) + } + } + + if (err.response?.status === 403 && !err.response.config.url.includes('chat/open')) { + MsgError( + err.response.data && err.response.data.message ? err.response.data.message : '没有权限访问', + ) + } + return Promise.reject(err) + }, +) + +export const request = instance + +/* 简化请求方法,统一处理返回结果,并增加loading处理,这里以{success,data,message}格式的返回值为例,具体项目根据实际需求修改 */ +const promise: ( + request: Promise, + loading?: NProgress | Ref | WritableComputedRef, +) => Promise> = (request, loading = ref(false)) => { + return new Promise((resolve, reject) => { + if ((loading as NProgress).start) { + ;(loading as NProgress).start() + } else { + ;(loading as Ref).value = true + } + request + .then((response) => { + // blob类型的返回状态是response.status + if (response.status === 200) { + resolve(response?.data || response) + } else { + reject(response?.data || response) + } + }) + .catch((error) => { + reject(error) + }) + .finally(() => { + if ((loading as NProgress).start) { + ;(loading as NProgress).done() + } else { + ;(loading as Ref).value = false + } + }) + }) +} + +/** + * 发送get请求 一般用来请求资源 + * @param url 资源url + * @param params 参数 + * @param loading loading + * @returns 异步promise对象 + */ +export const get: ( + url: string, + params?: unknown, + loading?: NProgress | Ref, + timeout?: number, +) => Promise> = ( + url: string, + params: unknown, + loading?: NProgress | Ref, + timeout?: number, +) => { + return promise(request({ url: url, method: 'get', params, timeout: timeout }), loading) +} + +/** + * faso post请求 一般用来添加资源 + * @param url 资源url + * @param params 参数 + * @param data 添加数据 + * @param loading loading + * @returns 异步promise对象 + */ +export const post: ( + url: string, + data?: unknown, + params?: unknown, + loading?: NProgress | Ref, + timeout?: number, +) => Promise | any> = (url, data, params, loading, timeout) => { + return promise(request({ url: url, method: 'post', data, params, timeout }), loading) +} + +/**| + * 发送put请求 用于修改服务器资源 + * @param url 资源地址 + * @param params params参数地址 + * @param data 需要修改的数据 + * @param loading 进度条 + * @returns + */ +export const put: ( + url: string, + data?: unknown, + params?: unknown, + loading?: NProgress | Ref, + timeout?: number, +) => Promise> = (url, data, params, loading, timeout) => { + return promise(request({ url: url, method: 'put', data, params, timeout }), loading) +} + +/** + * 删除 + * @param url 删除url + * @param params params参数 + * @param loading 进度条 + * @returns + */ +export const del: ( + url: string, + params?: unknown, + data?: unknown, + loading?: NProgress | Ref, + timeout?: number, +) => Promise> = (url, params, data, loading, timeout) => { + return promise(request({ url: url, method: 'delete', params, data, timeout }), loading) +} + +/** + * 流处理 + * @param url url地址 + * @param data 请求body + * @returns + */ +export const postStream: (url: string, data?: unknown) => Promise | any> = ( + url, + data, +) => { + const { user, login } = useStore() + const token = login.getToken() + const language = user.getLanguage() + const headers: HeadersInit = { 'Content-Type': 'application/json' } + if (token) { + headers['AUTHORIZATION'] = `${token}` + } + headers['Accept-Language'] = `${language}` + return fetch(url, { + method: 'POST', + body: data ? JSON.stringify(data) : undefined, + headers: headers, + }) +} + +export const exportExcel: ( + fileName: string, + url: string, + params: any, + loading?: NProgress | Ref, +) => Promise = ( + fileName: string, + url: string, + params: any, + loading?: NProgress | Ref, +) => { + return promise(request({ url: url, method: 'get', params, responseType: 'blob' }), loading).then( + (res: any) => { + if (res) { + const blob = new Blob([res], { + type: 'application/vnd.ms-excel', + }) + const link = document.createElement('a') + link.href = window.URL.createObjectURL(blob) + link.download = fileName + link.click() + //释放内存 + window.URL.revokeObjectURL(link.href) + } + return true + }, + ) +} + +export const exportFile: ( + fileName: string, + url: string, + params: any, + loading?: NProgress | Ref, +) => Promise = ( + fileName: string, + url: string, + params: any, + loading?: NProgress | Ref, +) => { + return promise(request({ url: url, method: 'get', params, responseType: 'blob' }), loading).then( + (res: any) => { + if (res) { + const blob = new Blob([res], { + type: 'application/octet-stream', + }) + const link = document.createElement('a') + link.href = window.URL.createObjectURL(blob) + link.download = fileName + link.click() + //释放内存 + window.URL.revokeObjectURL(link.href) + } + return true + }, + ) +} + +export const exportExcelPost: ( + fileName: string, + url: string, + params: any, + data: any, + loading?: NProgress | Ref, +) => Promise = ( + fileName: string, + url: string, + params: any, + data: any, + loading?: NProgress | Ref, +) => { + return promise( + request({ + url: url, + method: 'post', + params, // 查询字符串参数 + data, // 请求体数据 + responseType: 'blob', + }), + loading, + ).then((res: any) => { + if (res) { + const blob = new Blob([res], { + type: 'application/vnd.ms-excel', + }) + const link = document.createElement('a') + link.href = window.URL.createObjectURL(blob) + link.download = fileName + link.click() + // 释放内存 + window.URL.revokeObjectURL(link.href) + } + return true + }) +} + +export const download: ( + url: string, + method: string, + data?: any, + params?: any, + loading?: NProgress | Ref, +) => Promise = ( + url: string, + method: string, + data?: any, + params?: any, + loading?: NProgress | Ref, +) => { + return promise(request({ url: url, method: method, data, params, responseType: 'blob' }), loading) +} + +/** + * 与服务器建立ws链接 + * @param url websocket路径 + * @returns 返回一个websocket实例 + */ +export const socket = (url: string) => { + let protocol = 'ws://' + if (window.location.protocol === 'https:') { + protocol = 'wss://' + } + let uri = protocol + window.location.host + url + if (!import.meta.env.DEV) { + uri = protocol + window.location.host + import.meta.env.VITE_BASE_PATH + url + } + return new WebSocket(uri) +} +export default instance diff --git a/ui/src/router/index.ts b/ui/src/router/index.ts index 40f33d09e..8283e332a 100644 --- a/ui/src/router/index.ts +++ b/ui/src/router/index.ts @@ -1,9 +1,82 @@ -import { createRouter, createWebHistory } from 'vue-router' +import { hasPermission } from '@/utils/permission/index' +import NProgress from 'nprogress' +import { + createRouter, + createWebHistory, + type NavigationGuardNext, + type RouteLocationNormalized, + type RouteRecordRaw, + type RouteRecordName, +} from 'vue-router' +import useStore from '@/stores' import { routes } from '@/router/routes' - +NProgress.configure({ showSpinner: false, speed: 500, minimum: 0.3 }) const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: routes, }) +// 路由前置拦截器 +router.beforeEach( + async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => { + NProgress.start() + if (to.name === '404') { + next() + return + } + const { user, login } = useStore() + const notAuthRouteNameList = ['register', 'login', 'forgot_password', 'reset_password', 'Chat'] + + if (!notAuthRouteNameList.includes(to.name ? to.name.toString() : '')) { + if (to.query && to.query.token) { + localStorage.setItem('token', to.query.token.toString()) + } + const token = login.getToken() + if (!token) { + next({ + path: '/login', + }) + return + } + if (!user.userInfo) { + await user.profile() + } + } + // 判断是否有菜单权限 + if (to.meta.permission ? hasPermission(to.meta.permission as any, 'OR') : true) { + next() + } else { + // 如果没有权限则直接取404页面 + next('404') + } + }, +) +router.afterEach(() => { + NProgress.done() +}) + +export const getChildRouteListByPathAndName = (path: any, name?: RouteRecordName | any) => { + return getChildRouteList(routes, path, name) +} + +export const getChildRouteList: ( + routeList: Array, + path: string, + name?: RouteRecordName | null | undefined, +) => Array = (routeList, path, name) => { + for (let index = 0; index < routeList.length; index++) { + const route = routeList[index] + if (name === route.name && path === route.path) { + return route.children || [] + } + if (route.children && route.children.length > 0) { + const result = getChildRouteList(route.children, path, name) + if (result && result?.length > 0) { + return result + } + } + } + return [] +} + export default router diff --git a/ui/src/stores/modules/login.ts b/ui/src/stores/modules/login.ts index c116db2c9..94628ada5 100644 --- a/ui/src/stores/modules/login.ts +++ b/ui/src/stores/modules/login.ts @@ -1,210 +1,43 @@ import { defineStore } from 'pinia' import { type Ref } from 'vue' -// import type { User } from '@/api/type/user' -// import { cloneDeep } from 'lodash' -// import UserApi from '@/api/user' -// import ThemeApi from '@/api/theme' -// import { useElementPlusTheme } from 'use-element-plus-theme' -// import { defaultPlatformSetting } from '@/utils/theme' -import { useLocalStorage } from '@vueuse/core' -import { localeConfigKey, getBrowserLang } from '@/locales/index' -export interface userStateTypes { - userType: number // 1 系统操作者 2 对话用户 - // userInfo: User | null - token: any - version?: string - userAccessToken?: string - XPACK_LICENSE_IS_VALID: false - isXPack: false - themeInfo: any -} +import loginApi from '@/api/user/login' +import type { LoginRequest } from '@/api/type/login' +import useUserStore from './user' -const useLoginStore = defineStore('login',{ - state: (): userStateTypes => ({ - userType: 1, - // userInfo: null, +const useLoginStore = defineStore('login', { + state: () => ({ token: '', - version: '', userAccessToken: '', - XPACK_LICENSE_IS_VALID: false, - isXPack: false, - themeInfo: null }), actions: { - // getLanguage() { - // return this.userType === 1 - // ? localStorage.getItem('MaxKB-locale') || getBrowserLang() - // : sessionStorage.getItem('language') || getBrowserLang() - // }, - // showXpack() { - // return this.isXPack - // }, - // isDefaultTheme() { - // return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF' - // }, - // setTheme(data: any) { - // const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme) - // changeTheme(data?.['theme']) - // this.themeInfo = cloneDeep(data) - // }, - // isExpire() { - // return this.isXPack && !this.XPACK_LICENSE_IS_VALID - // }, - // isEnterprise() { - // return this.isXPack && this.XPACK_LICENSE_IS_VALID - // }, - // getToken(): String | null { - // if (this.token) { - // return this.token - // } - // return this.userType === 1 ? localStorage.getItem('token') : this.getAccessToken() - // }, - // getAccessToken() { - // const token = sessionStorage.getItem(`${this.userAccessToken}-accessToken`) - // if (token) { - // return token - // } - // const local_token = localStorage.getItem(`${token}-accessToken`) - // if (local_token) { - // return local_token - // } - // return localStorage.getItem(`accessToken`) - // }, + getToken(): String | null { + if (this.token) { + return this.token + } + const user = useUserStore() + return user.userType === 1 ? localStorage.getItem('token') : this.getAccessToken() + }, + getAccessToken() { + const token = sessionStorage.getItem(`${this.userAccessToken}-accessToken`) + if (token) { + return token + } + const local_token = localStorage.getItem(`${token}-accessToken`) + if (local_token) { + return local_token + } + return localStorage.getItem(`accessToken`) + }, - // getPermissions() { - // if (this.userInfo) { - // return this.isXPack && this.XPACK_LICENSE_IS_VALID - // ? [...this.userInfo?.permissions, 'x-pack'] - // : this.userInfo?.permissions - // } else { - // return [] - // } - // }, - // getRole() { - // if (this.userInfo) { - // return this.userInfo?.role - // } else { - // return '' - // } - // }, - // changeUserType(num: number, token?: string) { - // this.userType = num - // this.userAccessToken = token - // }, - - // async asyncGetProfile() { - // return new Promise((resolve, reject) => { - // UserApi.getProfile() - // .then(async (ok) => { - // this.version = ok.data?.version || '-' - // this.isXPack = ok.data?.IS_XPACK - // this.XPACK_LICENSE_IS_VALID = ok.data?.XPACK_LICENSE_IS_VALID - - // if (this.isEnterprise()) { - // await this.theme() - // } else { - // this.themeInfo = { - // ...defaultPlatformSetting - // } - // } - // resolve(ok) - // }) - // .catch((error) => { - // reject(error) - // }) - // }) - // }, - - // async theme(loading?: Ref) { - // return await ThemeApi.getThemeInfo(loading).then((ok) => { - // this.setTheme(ok.data) - // // window.document.title = this.themeInfo['title'] || 'MaxKB' - // // const link = document.querySelector('link[rel="icon"]') as any - // // if (link) { - // // link['href'] = this.themeInfo['icon'] || '/favicon.ico' - // // } - // }) - // }, - - // async profile() { - // return UserApi.profile().then(async (ok) => { - // this.userInfo = ok.data - // useLocalStorage(localeConfigKey, 'en-US').value = ok.data?.language || this.getLanguage() - // return this.asyncGetProfile() - // }) - // }, - - // async login(auth_type: string, username: string, password: string) { - // return UserApi.login(auth_type, { username, password }).then((ok) => { - // this.token = ok.data - // localStorage.setItem('token', ok.data) - // return this.profile() - // }) - // }, - // async dingCallback(code: string) { - // return UserApi.getDingCallback(code).then((ok) => { - // this.token = ok.data - // localStorage.setItem('token', ok.data) - // return this.profile() - // }) - // }, - // async dingOauth2Callback(code: string) { - // return UserApi.getDingOauth2Callback(code).then((ok) => { - // this.token = ok.data - // localStorage.setItem('token', ok.data) - // return this.profile() - // }) - // }, - // async wecomCallback(code: string) { - // return UserApi.getWecomCallback(code).then((ok) => { - // this.token = ok.data - // localStorage.setItem('token', ok.data) - // return this.profile() - // }) - // }, - // async larkCallback(code: string) { - // return UserApi.getlarkCallback(code).then((ok) => { - // this.token = ok.data - // localStorage.setItem('token', ok.data) - // return this.profile() - // }) - // }, - - // async logout() { - // return UserApi.logout().then(() => { - // localStorage.removeItem('token') - // return true - // }) - // }, - // async getAuthType() { - // return UserApi.getAuthType().then((ok) => { - // return ok.data - // }) - // }, - // async getQrType() { - // return UserApi.getQrType().then((ok) => { - // return ok.data - // }) - // }, - // async getQrSource() { - // return UserApi.getQrSource().then((ok) => { - // return ok.data - // }) - // }, - // async postUserLanguage(lang: string, loading?: Ref) { - // return new Promise((resolve, reject) => { - // UserApi.postLanguage({ language: lang }, loading) - // .then(async (ok) => { - // useLocalStorage(localeConfigKey, 'en-US').value = lang - // window.location.reload() - // resolve(ok) - // }) - // .catch((error) => { - // reject(error) - // }) - // }) - // } - } + async asyncLogin(data: LoginRequest, loading?: Ref) { + return loginApi.login(data).then((ok) => { + this.token = ok.data + localStorage.setItem('token', ok.data) + const user = useUserStore() + return user.profile() + }) + }, + }, }) export default useLoginStore diff --git a/ui/src/stores/modules/user.ts b/ui/src/stores/modules/user.ts index 08ce5910b..0691a081e 100644 --- a/ui/src/stores/modules/user.ts +++ b/ui/src/stores/modules/user.ts @@ -1,8 +1,8 @@ import { defineStore } from 'pinia' import { type Ref } from 'vue' -// import type { User } from '@/api/type/user' +import type { User } from '@/api/type/user' import { cloneDeep } from 'lodash' -// import UserApi from '@/api/user' +import UserApi from '@/api/user/user' // import ThemeApi from '@/api/theme' // import { useElementPlusTheme } from 'use-element-plus-theme' // import { defaultPlatformSetting } from '@/utils/theme' @@ -10,10 +10,8 @@ import { useLocalStorage } from '@vueuse/core' import { localeConfigKey, getBrowserLang } from '@/locales/index' export interface userStateTypes { userType: number // 1 系统操作者 2 对话用户 - // userInfo: User | null - token: any + userInfo: User | null version?: string - userAccessToken?: string XPACK_LICENSE_IS_VALID: false isXPack: false themeInfo: any @@ -21,14 +19,12 @@ export interface userStateTypes { const useLoginStore = defineStore('user', { state: (): userStateTypes => ({ - userType: 1, - // userInfo: null, - token: '', + userType: 1, // 1 系统操作者 2 对话用户 + userInfo: null, version: '', - userAccessToken: '', XPACK_LICENSE_IS_VALID: false, isXPack: false, - themeInfo: null + themeInfo: null, }), actions: { getLanguage() { @@ -36,62 +32,17 @@ const useLoginStore = defineStore('user', { ? localStorage.getItem('MaxKB-locale') || getBrowserLang() : sessionStorage.getItem('language') || getBrowserLang() }, - // showXpack() { - // return this.isXPack - // }, isDefaultTheme() { return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF' }, - // setTheme(data: any) { - // const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme) - // changeTheme(data?.['theme']) - // this.themeInfo = cloneDeep(data) - // }, - // isExpire() { - // return this.isXPack && !this.XPACK_LICENSE_IS_VALID - // }, - // isEnterprise() { - // return this.isXPack && this.XPACK_LICENSE_IS_VALID - // }, - // getToken(): String | null { - // if (this.token) { - // return this.token - // } - // return this.userType === 1 ? localStorage.getItem('token') : this.getAccessToken() - // }, - // getAccessToken() { - // const token = sessionStorage.getItem(`${this.userAccessToken}-accessToken`) - // if (token) { - // return token - // } - // const local_token = localStorage.getItem(`${token}-accessToken`) - // if (local_token) { - // return local_token - // } - // return localStorage.getItem(`accessToken`) - // }, - - // getPermissions() { - // if (this.userInfo) { - // return this.isXPack && this.XPACK_LICENSE_IS_VALID - // ? [...this.userInfo?.permissions, 'x-pack'] - // : this.userInfo?.permissions - // } else { - // return [] - // } - // }, - // getRole() { - // if (this.userInfo) { - // return this.userInfo?.role - // } else { - // return '' - // } - // }, - // changeUserType(num: number, token?: string) { - // this.userType = num - // this.userAccessToken = token - // }, - + async profile() { + return UserApi.getUserProfile().then((ok: { data: User }) => { + this.userInfo = ok.data + useLocalStorage(localeConfigKey, 'en-US').value = + ok.data?.language || this.getLanguage() + // return this.asyncGetProfile() + }) + }, // async asyncGetProfile() { // return new Promise((resolve, reject) => { // UserApi.getProfile() @@ -115,6 +66,43 @@ const useLoginStore = defineStore('user', { // }) // }, + getPermissions() { + if (this.userInfo) { + return this.isXPack && this.XPACK_LICENSE_IS_VALID + ? [...this.userInfo?.permissions, 'x-pack'] + : this.userInfo?.permissions + } else { + return [] + } + }, + getRole() { + if (this.userInfo) { + return this.userInfo?.role + } else { + return '' + } + }, + // showXpack() { + // return this.isXPack + // }, + + // setTheme(data: any) { + // const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme) + // changeTheme(data?.['theme']) + // this.themeInfo = cloneDeep(data) + // }, + // isExpire() { + // return this.isXPack && !this.XPACK_LICENSE_IS_VALID + // }, + // isEnterprise() { + // return this.isXPack && this.XPACK_LICENSE_IS_VALID + // }, + + // changeUserType(num: number, token?: string) { + // this.userType = num + // this.userAccessToken = token + // }, + // async theme(loading?: Ref) { // return await ThemeApi.getThemeInfo(loading).then((ok) => { // this.setTheme(ok.data) @@ -126,21 +114,6 @@ const useLoginStore = defineStore('user', { // }) // }, - // async profile() { - // return UserApi.profile().then(async (ok) => { - // this.userInfo = ok.data - // useLocalStorage(localeConfigKey, 'en-US').value = ok.data?.language || this.getLanguage() - // return this.asyncGetProfile() - // }) - // }, - - // async login(auth_type: string, username: string, password: string) { - // return UserApi.login(auth_type, { username, password }).then((ok) => { - // this.token = ok.data - // localStorage.setItem('token', ok.data) - // return this.profile() - // }) - // }, // async dingCallback(code: string) { // return UserApi.getDingCallback(code).then((ok) => { // this.token = ok.data @@ -204,7 +177,7 @@ const useLoginStore = defineStore('user', { // }) // }) // } - } + }, }) export default useLoginStore diff --git a/ui/src/styles/index.scss b/ui/src/styles/index.scss index 43afaf395..7cb7783e5 100644 --- a/ui/src/styles/index.scss +++ b/ui/src/styles/index.scss @@ -2,3 +2,4 @@ @use './element-plus.scss'; @use './variables.scss'; @use './app.scss'; +@import 'nprogress/nprogress.css'; diff --git a/ui/src/utils/message.ts b/ui/src/utils/message.ts new file mode 100644 index 000000000..fb20c5c47 --- /dev/null +++ b/ui/src/utils/message.ts @@ -0,0 +1,61 @@ +import { ElMessageBox, ElMessage } from 'element-plus' +import { t } from '@/locales' + +export const MsgSuccess = (message: string) => { + ElMessage.success({ + message: message, + type: 'success', + showClose: true, + duration: 3000 + }) +} + +export const MsgInfo = (message: string) => { + ElMessage.info({ + message: message, + type: 'info', + showClose: true, + duration: 3000 + }) +} + +export const MsgWarning = (message: string) => { + ElMessage.warning({ + message: message, + type: 'warning', + showClose: true, + duration: 3000 + }) +} + +export const MsgError = (message: string) => { + ElMessage.error({ + message: message, + type: 'error', + showClose: true, + duration: 3000 + }) +} + +export const MsgAlert = (title: string, description: string, options?: any) => { + const defaultOptions: Object = { + confirmButtonText: t('common.confirm'), + ...options + } + return ElMessageBox.alert(description, title, defaultOptions) +} + +/** + * 删除知识库 + * @param 参数 message: {title, description,type} + */ + +export const MsgConfirm = (title: string, description: string, options?: any) => { + const defaultOptions: Object = { + showCancelButton: true, + confirmButtonText: t('common.confirm'), + cancelButtonText: t('common.cancel'), + ...options + } + return ElMessageBox.confirm(description, title, defaultOptions) +} diff --git a/ui/src/utils/permission/index.ts b/ui/src/utils/permission/index.ts new file mode 100644 index 000000000..37313f90e --- /dev/null +++ b/ui/src/utils/permission/index.ts @@ -0,0 +1,55 @@ +import useStore from '@/stores'; +import { Role, Permission, ComplexPermission } from '@/utils/permission/type' +/** + * 是否包含当前权限 + * @param permission 当前权限 + * @returns True 包含 false 不包含 + */ +const hasPermissionChild = (permission: Role | string | Permission | ComplexPermission) => { + const { user } = useStore(); + const permissions = user.getPermissions() + const role = user.getRole() + if (!permission) { + return true + } + if (permission instanceof Role) { + return role === permission.role + } + if (permission instanceof Permission) { + return permissions.includes(permission.permission) + } + if (permission instanceof ComplexPermission) { + const permissionOk = permission.permissionList.some((p) => permissions.includes(p)) + const roleOk = permission.roleList.includes(role) + return permission.compare === 'AND' ? permissionOk && roleOk : permissionOk || roleOk + } + if (typeof permission === 'string') { + return permissions.includes(permission) + } + + return false +} +/** + * 判断是否有角色和权限 + * @param role 角色 + * @param permissions 权限 + * @param requiredPermissions 权限 + * @returns + */ +export const hasPermission = ( + permission: + | Array + | Role + | string + | Permission + | ComplexPermission, + compare: 'OR' | 'AND' +): boolean => { + if (permission instanceof Array) { + return compare === 'OR' + ? permission.some((p) => hasPermissionChild(p)) + : permission.every((p) => hasPermissionChild(p)) + } else { + return hasPermissionChild(permission) + } +} diff --git a/ui/src/utils/permission/type.ts b/ui/src/utils/permission/type.ts new file mode 100644 index 000000000..874fc830b --- /dev/null +++ b/ui/src/utils/permission/type.ts @@ -0,0 +1,36 @@ +/** + * 角色对象 + */ +export class Role { + role: string + + constructor(role: string) { + this.role = role + } +} +/** + * 权限对象 + */ +export class Permission { + permission: string + + constructor(permission: string) { + this.permission = permission + } +} +/** + * 复杂权限对象 + */ +export class ComplexPermission { + roleList: Array + + permissionList: Array + + compare: 'OR' | 'AND' + + constructor(roleList: Array, permissionList: Array, compare: 'OR' | 'AND') { + this.roleList = roleList + this.permissionList = permissionList + this.compare = compare + } +} diff --git a/ui/src/utils/theme.ts b/ui/src/utils/theme.ts index 067bf3a4a..1c6edd250 100644 --- a/ui/src/utils/theme.ts +++ b/ui/src/utils/theme.ts @@ -2,27 +2,27 @@ import { t } from '@/locales' export const themeList = [ { - label: t('views.system.theme.default'), + label: t('theme.default'), value: '#3370FF', loginBackground: 'default', }, { - label: t('views.system.theme.orange'), + label: t('theme.orange'), value: '#FF8800', loginBackground: 'orange', }, { - label: t('views.system.theme.green'), + label: t('theme.green'), value: '#00B69D', loginBackground: 'green', }, { - label: t('views.system.theme.purple'), + label: t('theme.purple'), value: '#7F3BF5', loginBackground: 'purple', }, { - label: t('views.system.theme.red'), + label: t('theme.red'), value: '#F01D94', loginBackground: 'red', }, @@ -38,7 +38,7 @@ export const defaultSetting = { loginLogo: '', loginImage: '', title: 'MaxKB', - slogan: t('views.system.theme.defaultSlogan'), + slogan: t('theme.defaultSlogan'), } export const defaultPlatformSetting = { diff --git a/ui/src/views/login/ForgetPassword.vue b/ui/src/views/login/ForgetPassword.vue index 2c2ff0257..5826a7e38 100644 --- a/ui/src/views/login/ForgetPassword.vue +++ b/ui/src/views/login/ForgetPassword.vue @@ -1,6 +1,6 @@ - - - diff --git a/ui/src/views/login/index.vue b/ui/src/views/login/index.vue index 28adc1502..10f6cb713 100644 --- a/ui/src/views/login/index.vue +++ b/ui/src/views/login/index.vue @@ -1,6 +1,6 @@