feat: login
parent
b1d13f501f
commit
f805f6dce1
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"name": "MaxKB",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {}
|
|
||||||
}
|
|
||||||
|
|
@ -13,7 +13,9 @@
|
||||||
"format": "prettier --write src/"
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^1.8.4",
|
||||||
"element-plus": "^2.9.7",
|
"element-plus": "^2.9.7",
|
||||||
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^3.0.1",
|
"pinia": "^3.0.1",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^11.1.3",
|
"vue-i18n": "^11.1.3",
|
||||||
|
|
@ -22,6 +24,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tsconfig/node22": "^22.0.1",
|
"@tsconfig/node22": "^22.0.1",
|
||||||
"@types/node": "^22.14.0",
|
"@types/node": "^22.14.0",
|
||||||
|
"@types/nprogress": "^0.2.3",
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
||||||
"@vue/eslint-config-prettier": "^10.2.0",
|
"@vue/eslint-config-prettier": "^10.2.0",
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ interface LoginRequest {
|
||||||
* 密码
|
* 密码
|
||||||
*/
|
*/
|
||||||
password: string
|
password: string
|
||||||
/**
|
/**
|
||||||
* 验证码
|
* 验证码
|
||||||
*/
|
*/
|
||||||
code: string
|
captcha: string
|
||||||
}
|
}
|
||||||
export type { LoginRequest }
|
export type { LoginRequest }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
interface User {
|
||||||
|
/**
|
||||||
|
* 用户id
|
||||||
|
*/
|
||||||
|
id: string
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
username: string
|
||||||
|
/**
|
||||||
|
* 邮箱
|
||||||
|
*/
|
||||||
|
email: string
|
||||||
|
/**
|
||||||
|
* 用户角色
|
||||||
|
*/
|
||||||
|
role: string
|
||||||
|
/**
|
||||||
|
* 用户权限
|
||||||
|
*/
|
||||||
|
permissions: Array<string>
|
||||||
|
/**
|
||||||
|
* 是否需要修改密码
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
@ -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<boolean>) => Promise<Result<string>> = (
|
||||||
|
request,
|
||||||
|
loading,
|
||||||
|
) => {
|
||||||
|
return post('/user/login', request, undefined, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取验证码
|
||||||
|
* @param loading 接口加载器
|
||||||
|
*/
|
||||||
|
const getCaptcha: (loading?: Ref<boolean>) => Promise<Result<string>> = (loading) => {
|
||||||
|
return get('/user/captcha', undefined, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
login,
|
||||||
|
getCaptcha,
|
||||||
|
}
|
||||||
|
|
@ -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<boolean>) => Promise<Result<User>> = (loading) => {
|
||||||
|
return get('/user/profile', undefined, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取版本profile
|
||||||
|
*/
|
||||||
|
// const getProfile: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) => {
|
||||||
|
// return get('/profile', undefined, loading)
|
||||||
|
// }
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getUserProfile,
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ import en from 'element-plus/es/locale/lang/en'
|
||||||
import components from './components'
|
import components from './components'
|
||||||
import layout from './layout'
|
import layout from './layout'
|
||||||
import views from './views'
|
import views from './views'
|
||||||
|
import theme from './theme'
|
||||||
import common from './common'
|
import common from './common'
|
||||||
import dynamicsForm from './dynamics-form'
|
import dynamicsForm from './dynamics-form'
|
||||||
import chat from './ai-chat'
|
import chat from './ai-chat'
|
||||||
|
|
@ -9,6 +10,7 @@ export default {
|
||||||
lang: 'English',
|
lang: 'English',
|
||||||
layout,
|
layout,
|
||||||
views,
|
views,
|
||||||
|
theme,
|
||||||
components,
|
components,
|
||||||
en,
|
en,
|
||||||
common,
|
common,
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,25 @@
|
||||||
export default {
|
export default {
|
||||||
title: 'Login',
|
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_tip: 'You will be redirected to the authentication source page for authentication',
|
||||||
jump: 'Redirect',
|
jump: 'Redirect',
|
||||||
resetPassword: 'Change Password',
|
resetPassword: 'Change Password',
|
||||||
|
|
@ -9,7 +29,7 @@ export default {
|
||||||
login: 'Login',
|
login: 'Login',
|
||||||
register: 'Register',
|
register: 'Register',
|
||||||
backLogin: 'Back to Login',
|
backLogin: 'Back to Login',
|
||||||
checkCode: 'Verify Now'
|
checkCode: 'Verify Now',
|
||||||
},
|
},
|
||||||
newPassword: 'New Password',
|
newPassword: 'New Password',
|
||||||
enterPassword: 'Please enter your new password',
|
enterPassword: 'Please enter your new password',
|
||||||
|
|
@ -19,6 +39,6 @@ export default {
|
||||||
placeholder: 'Please enter the verification code',
|
placeholder: 'Please enter the verification code',
|
||||||
getVerificationCode: 'Get Verification Code',
|
getVerificationCode: 'Get Verification Code',
|
||||||
successMessage: 'Verification code sent successfully',
|
successMessage: 'Verification code sent successfully',
|
||||||
resend: 'Resend'
|
resend: 'Resend',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,48 +93,6 @@ export default {
|
||||||
access: 'Access'
|
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: {
|
email: {
|
||||||
title: 'Email Settings',
|
title: 'Email Settings',
|
||||||
smtpHost: 'SMTP Host',
|
smtpHost: 'SMTP Host',
|
||||||
|
|
|
||||||
|
|
@ -3,68 +3,57 @@ export default {
|
||||||
createUser: 'Create User',
|
createUser: 'Create User',
|
||||||
editUser: 'Edit User',
|
editUser: 'Edit User',
|
||||||
setting: {
|
setting: {
|
||||||
updatePwd: 'Change Password'
|
updatePwd: 'Change Password',
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
professionalMessage:
|
professionalMessage:
|
||||||
'The community edition supports up to 2 users. For more users, please upgrade to the professional edition.',
|
'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: {
|
delete: {
|
||||||
confirmTitle: 'Confirm deletion of user:',
|
confirmTitle: 'Confirm deletion of user:',
|
||||||
confirmMessage:
|
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: {
|
disabled: {
|
||||||
confirmTitle: 'Confirm disable function:',
|
confirmTitle: 'Confirm disable function:',
|
||||||
confirmMessage:
|
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: {
|
userForm: {
|
||||||
form: {
|
form: {
|
||||||
username: {
|
|
||||||
label: 'Username',
|
|
||||||
placeholder: 'Please enter username',
|
|
||||||
requiredMessage: 'Please enter username',
|
|
||||||
lengthMessage: 'Length must be between 6 and 20 words'
|
|
||||||
},
|
|
||||||
nick_name: {
|
nick_name: {
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
placeholder: 'Please enter name'
|
placeholder: 'Please enter name',
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
label: 'Email',
|
label: 'Email',
|
||||||
placeholder: 'Please enter email',
|
placeholder: 'Please enter email',
|
||||||
requiredMessage: 'Please enter email'
|
requiredMessage: 'Please enter email',
|
||||||
},
|
},
|
||||||
phone: {
|
phone: {
|
||||||
label: 'Phone',
|
label: 'Phone',
|
||||||
placeholder: 'Please enter 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'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
new_password: {
|
new_password: {
|
||||||
label: 'New Password',
|
label: 'New Password',
|
||||||
placeholder: 'Please enter new password',
|
placeholder: 'Please enter new password',
|
||||||
requiredMessage: 'Please enter new password'
|
requiredMessage: 'Please enter new password',
|
||||||
},
|
},
|
||||||
re_password: {
|
re_password: {
|
||||||
label: 'Confirm Password',
|
label: 'Confirm Password',
|
||||||
placeholder: 'Please enter confirm password',
|
placeholder: 'Please enter confirm password',
|
||||||
requiredMessage: 'Please enter confirm password',
|
requiredMessage: 'Please enter confirm password',
|
||||||
validatorMessage: 'Passwords do not match'
|
validatorMessage: 'Passwords do not match',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
source: {
|
source: {
|
||||||
label: 'User Type',
|
label: 'User Type',
|
||||||
local: 'System User',
|
local: 'System User',
|
||||||
wecom: 'WeCom',
|
wecom: 'WeCom',
|
||||||
lark: 'Lark',
|
lark: 'Lark',
|
||||||
dingtalk: 'DingTalk'
|
dingtalk: 'DingTalk',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: `<p>该功能需要使用麦克风,浏览器禁止不安全页面录音,解决方案如下:<br/>
|
|
||||||
1、可开启 https 解决;<br/>
|
|
||||||
2、若无 https 配置则需要修改浏览器安全配置,Chrome 设置如下:<br/>
|
|
||||||
(1) 地址栏输入chrome://flags/#unsafely-treat-insecure-origin-as-secure;<br/>
|
|
||||||
(2) 将 http 站点配置在文本框中,例如: http://127.0.0.1:8080。</p>`,
|
|
||||||
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: '编辑标题',
|
|
||||||
}
|
|
||||||
|
|
@ -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:'重命名'
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
export default {
|
|
||||||
quickCreatePlaceholder: '快速创建空白文档',
|
|
||||||
quickCreateName: '文档名称',
|
|
||||||
noData: '无匹配数据',
|
|
||||||
loading: '加载中',
|
|
||||||
noMore: '到底啦!',
|
|
||||||
selectParagraph: {
|
|
||||||
title: '选择分段',
|
|
||||||
error: '仅执行未成功分段',
|
|
||||||
all: '全部分段'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '文本长度为必填参数'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +1,13 @@
|
||||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||||
import components from './components'
|
// import components from './components'
|
||||||
import layout from './layout'
|
|
||||||
import views from './views'
|
import views from './views'
|
||||||
import common from './common'
|
import theme from './theme'
|
||||||
import dynamicsForm from './dynamics-form'
|
// import common from './common'
|
||||||
import chat from './ai-chat'
|
// import dynamicsForm from './dynamics-form'
|
||||||
|
// import chat from './ai-chat'
|
||||||
export default {
|
export default {
|
||||||
lang: '简体中文',
|
lang: '简体中文',
|
||||||
layout,
|
|
||||||
views,
|
|
||||||
components,
|
|
||||||
zhCn,
|
zhCn,
|
||||||
common,
|
views,
|
||||||
dynamicsForm,
|
theme
|
||||||
chat
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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'
|
|
||||||
}
|
|
||||||
|
|
@ -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: '外观设置成功',
|
||||||
|
}
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
export default {
|
|
||||||
title: "404",
|
|
||||||
message: "无法访问应用",
|
|
||||||
operate: "返回首页",
|
|
||||||
};
|
|
||||||
|
|
@ -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: '反对'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: {}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '没有命中的分段'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '注意:所有同步都会删除已有数据重新获取新数据,请谨慎操作。'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '全选'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '运行失败'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +1,34 @@
|
||||||
import notFound from './404'
|
// import notFound from './404'
|
||||||
import application from './application'
|
// import application from './application'
|
||||||
import applicationOverview from './application-overview'
|
// import applicationOverview from './application-overview'
|
||||||
import dataset from './dataset'
|
// import dataset from './dataset'
|
||||||
import system from './system'
|
// import system from './system'
|
||||||
import functionLib from './function-lib'
|
// import functionLib from './function-lib'
|
||||||
import user from './user'
|
// import user from './user'
|
||||||
import team from './team'
|
// import team from './team'
|
||||||
import template from './template'
|
// import template from './template'
|
||||||
import document from './document'
|
// import document from './document'
|
||||||
import paragraph from './paragraph'
|
// import paragraph from './paragraph'
|
||||||
import problem from './problem'
|
// import problem from './problem'
|
||||||
import log from './log'
|
// import log from './log'
|
||||||
import applicationWorkflow from './application-workflow'
|
// import applicationWorkflow from './application-workflow'
|
||||||
import login from './login'
|
import login from './login'
|
||||||
import operateLog from './operate-log'
|
// import operateLog from './operate-log'
|
||||||
export default {
|
export default {
|
||||||
notFound,
|
// notFound,
|
||||||
application,
|
// application,
|
||||||
applicationOverview,
|
// applicationOverview,
|
||||||
dataset,
|
// dataset,
|
||||||
system,
|
// system,
|
||||||
functionLib,
|
// functionLib,
|
||||||
user,
|
// user,
|
||||||
team,
|
// team,
|
||||||
template,
|
// template,
|
||||||
document,
|
// document,
|
||||||
paragraph,
|
// paragraph,
|
||||||
problem,
|
// problem,
|
||||||
log,
|
// log,
|
||||||
applicationWorkflow,
|
// applicationWorkflow,
|
||||||
login,
|
login,
|
||||||
operateLog
|
// operateLog
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: '请给当前内容设置一个标题,以便管理查看'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,25 @@
|
||||||
export default {
|
export default {
|
||||||
title: '普通登录',
|
title: '普通登录',
|
||||||
|
loginForm: {
|
||||||
|
username: {
|
||||||
|
label: '用户名',
|
||||||
|
placeholder: '请输入用户名',
|
||||||
|
requiredMessage: '请输入用户名',
|
||||||
|
lengthMessage: '长度在 6 到 20 个字符',
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
label: '登录密码',
|
||||||
|
placeholder: '请输入密码',
|
||||||
|
requiredMessage: '请输入密码',
|
||||||
|
lengthMessage: '长度在 6 到 20 个字符',
|
||||||
|
},
|
||||||
|
captcha: {
|
||||||
|
label: '验证码',
|
||||||
|
placeholder: '请输入验证码',
|
||||||
|
requiredMessage: '请输入验证码',
|
||||||
|
validatorMessage: '验证码不正确',
|
||||||
|
},
|
||||||
|
},
|
||||||
jump_tip: '即将跳转至认证源页面进行认证',
|
jump_tip: '即将跳转至认证源页面进行认证',
|
||||||
jump: '跳转',
|
jump: '跳转',
|
||||||
resetPassword: '修改密码',
|
resetPassword: '修改密码',
|
||||||
|
|
@ -9,7 +29,7 @@ export default {
|
||||||
login: '登录',
|
login: '登录',
|
||||||
register: '注册',
|
register: '注册',
|
||||||
backLogin: '返回登录',
|
backLogin: '返回登录',
|
||||||
checkCode: '立即验证'
|
checkCode: '立即验证',
|
||||||
},
|
},
|
||||||
newPassword: '新密码',
|
newPassword: '新密码',
|
||||||
enterPassword: '请输入修改密码',
|
enterPassword: '请输入修改密码',
|
||||||
|
|
@ -19,6 +39,6 @@ export default {
|
||||||
placeholder: '请输入验证码',
|
placeholder: '请输入验证码',
|
||||||
getVerificationCode: '获取验证码',
|
getVerificationCode: '获取验证码',
|
||||||
successMessage: '验证码发送成功',
|
successMessage: '验证码发送成功',
|
||||||
resend: '重新发送'
|
resend: '重新发送',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: '关闭'
|
|
||||||
}
|
|
||||||
|
|
@ -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 个字'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '个'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
@ -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)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '请输入用户名/邮箱'
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '取消下载'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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: '钉钉'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,16 +2,18 @@ import zhTw from 'element-plus/es/locale/lang/zh-tw'
|
||||||
import components from './components'
|
import components from './components'
|
||||||
import layout from './layout'
|
import layout from './layout'
|
||||||
import views from './views'
|
import views from './views'
|
||||||
|
import theme from './theme'
|
||||||
import common from './common'
|
import common from './common'
|
||||||
import dynamicsForm from './dynamics-form'
|
import dynamicsForm from './dynamics-form'
|
||||||
import chat from './ai-chat'
|
import chat from './ai-chat'
|
||||||
export default {
|
export default {
|
||||||
lang: '繁體中文',
|
lang: '繁體中文',
|
||||||
layout,
|
layout,
|
||||||
common,
|
|
||||||
views,
|
views,
|
||||||
|
theme,
|
||||||
|
common,
|
||||||
components,
|
components,
|
||||||
zhTw,
|
zhTw,
|
||||||
dynamicsForm,
|
dynamicsForm,
|
||||||
chat
|
chat,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: '外觀設置成功',
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,25 @@
|
||||||
export default {
|
export default {
|
||||||
title: '普通登錄',
|
title: '普通登錄',
|
||||||
|
loginForm: {
|
||||||
|
username: {
|
||||||
|
label: '使用者名稱',
|
||||||
|
placeholder: '請輸入使用者名稱',
|
||||||
|
requiredMessage: '請輸入使用者名稱',
|
||||||
|
lengthMessage: '長度須介於 6 到 20 個字元之間'
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
label: '登入密碼',
|
||||||
|
placeholder: '請輸入密碼',
|
||||||
|
requiredMessage: '請輸入密碼',
|
||||||
|
lengthMessage: '長度須介於 6 到 20 個字元之間'
|
||||||
|
},
|
||||||
|
captcha: {
|
||||||
|
label: '驗證碼',
|
||||||
|
placeholder: '請輸入驗證碼',
|
||||||
|
requiredMessage: '請輸入驗證碼',
|
||||||
|
validatorMessage: '驗證碼不正確',
|
||||||
|
},
|
||||||
|
},
|
||||||
jump_tip: '即將跳轉至認證源頁面進行認證',
|
jump_tip: '即將跳轉至認證源頁面進行認證',
|
||||||
jump: '跳轉',
|
jump: '跳轉',
|
||||||
resetPassword: '修改密碼',
|
resetPassword: '修改密碼',
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export default {
|
||||||
ldap_filterPlaceholder: '請輸入使用者過濾器',
|
ldap_filterPlaceholder: '請輸入使用者過濾器',
|
||||||
ldap_mapping: 'LDAP 屬性對應',
|
ldap_mapping: 'LDAP 屬性對應',
|
||||||
ldap_mappingPlaceholder: '請輸入 LDAP 屬性對應',
|
ldap_mappingPlaceholder: '請輸入 LDAP 屬性對應',
|
||||||
enableAuthentication: '啟用 LDAP 認證'
|
enableAuthentication: '啟用 LDAP 認證',
|
||||||
},
|
},
|
||||||
cas: {
|
cas: {
|
||||||
title: 'CAS',
|
title: 'CAS',
|
||||||
|
|
@ -29,7 +29,7 @@ export default {
|
||||||
validateUrlPlaceholder: '請輸入驗證位址',
|
validateUrlPlaceholder: '請輸入驗證位址',
|
||||||
redirectUrl: '回呼位址',
|
redirectUrl: '回呼位址',
|
||||||
redirectUrlPlaceholder: '請輸入回呼位址',
|
redirectUrlPlaceholder: '請輸入回呼位址',
|
||||||
enableAuthentication: '啟用 CAS 認證'
|
enableAuthentication: '啟用 CAS 認證',
|
||||||
},
|
},
|
||||||
oidc: {
|
oidc: {
|
||||||
title: 'OIDC',
|
title: 'OIDC',
|
||||||
|
|
@ -48,7 +48,7 @@ export default {
|
||||||
logoutEndpointPlaceholder: '請輸入登出端位址',
|
logoutEndpointPlaceholder: '請輸入登出端位址',
|
||||||
redirectUrl: '回呼位址',
|
redirectUrl: '回呼位址',
|
||||||
redirectUrlPlaceholder: '請輸入回呼位址',
|
redirectUrlPlaceholder: '請輸入回呼位址',
|
||||||
enableAuthentication: '啟用 OIDC 認證'
|
enableAuthentication: '啟用 OIDC 認證',
|
||||||
},
|
},
|
||||||
|
|
||||||
oauth2: {
|
oauth2: {
|
||||||
|
|
@ -69,7 +69,7 @@ export default {
|
||||||
redirectUrlPlaceholder: '請輸入回呼位址',
|
redirectUrlPlaceholder: '請輸入回呼位址',
|
||||||
filedMapping: '欄位對應',
|
filedMapping: '欄位對應',
|
||||||
filedMappingPlaceholder: '請輸入欄位對應',
|
filedMappingPlaceholder: '請輸入欄位對應',
|
||||||
enableAuthentication: '啟用 OAuth2 認證'
|
enableAuthentication: '啟用 OAuth2 認證',
|
||||||
},
|
},
|
||||||
scanTheQRCode: {
|
scanTheQRCode: {
|
||||||
title: '掃碼登入',
|
title: '掃碼登入',
|
||||||
|
|
@ -91,49 +91,10 @@ export default {
|
||||||
larkQrCode: '飛書掃碼登錄',
|
larkQrCode: '飛書掃碼登錄',
|
||||||
dingtalkQrCode: '釘釘掃碼登錄',
|
dingtalkQrCode: '釘釘掃碼登錄',
|
||||||
setting: '設置',
|
setting: '設置',
|
||||||
access: '接入'
|
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: '外觀設置成功'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
email: {
|
email: {
|
||||||
title: '郵箱設置',
|
title: '郵箱設置',
|
||||||
smtpHost: 'SMTP Host',
|
smtpHost: 'SMTP Host',
|
||||||
|
|
@ -147,6 +108,6 @@ export default {
|
||||||
smtpPassword: '發件人密碼',
|
smtpPassword: '發件人密碼',
|
||||||
smtpPasswordPlaceholder: '請輸入發件人密碼',
|
smtpPasswordPlaceholder: '請輸入發件人密碼',
|
||||||
enableSSL: '啟用 SSL(如果 SMTP 端口是 465,通常需要啟用 SSL)',
|
enableSSL: '啟用 SSL(如果 SMTP 端口是 465,通常需要啟用 SSL)',
|
||||||
enableTLS: '啟用 TLS(如果 SMTP 端口是 587,通常需要啟用 TLS)'
|
enableTLS: '啟用 TLS(如果 SMTP 端口是 587,通常需要啟用 TLS)',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
export class Result<T> {
|
||||||
|
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
|
||||||
|
|
@ -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<any>,
|
||||||
|
loading?: NProgress | Ref<boolean> | WritableComputedRef<boolean>,
|
||||||
|
) => Promise<Result<any>> = (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<boolean>,
|
||||||
|
timeout?: number,
|
||||||
|
) => Promise<Result<any>> = (
|
||||||
|
url: string,
|
||||||
|
params: unknown,
|
||||||
|
loading?: NProgress | Ref<boolean>,
|
||||||
|
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<boolean>,
|
||||||
|
timeout?: number,
|
||||||
|
) => Promise<Result<any> | 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<boolean>,
|
||||||
|
timeout?: number,
|
||||||
|
) => Promise<Result<any>> = (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<boolean>,
|
||||||
|
timeout?: number,
|
||||||
|
) => Promise<Result<any>> = (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<Result<any> | 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<boolean>,
|
||||||
|
) => Promise<any> = (
|
||||||
|
fileName: string,
|
||||||
|
url: string,
|
||||||
|
params: any,
|
||||||
|
loading?: NProgress | Ref<boolean>,
|
||||||
|
) => {
|
||||||
|
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<boolean>,
|
||||||
|
) => Promise<any> = (
|
||||||
|
fileName: string,
|
||||||
|
url: string,
|
||||||
|
params: any,
|
||||||
|
loading?: NProgress | Ref<boolean>,
|
||||||
|
) => {
|
||||||
|
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<boolean>,
|
||||||
|
) => Promise<any> = (
|
||||||
|
fileName: string,
|
||||||
|
url: string,
|
||||||
|
params: any,
|
||||||
|
data: any,
|
||||||
|
loading?: NProgress | Ref<boolean>,
|
||||||
|
) => {
|
||||||
|
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<boolean>,
|
||||||
|
) => Promise<any> = (
|
||||||
|
url: string,
|
||||||
|
method: string,
|
||||||
|
data?: any,
|
||||||
|
params?: any,
|
||||||
|
loading?: NProgress | Ref<boolean>,
|
||||||
|
) => {
|
||||||
|
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
|
||||||
|
|
@ -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'
|
import { routes } from '@/router/routes'
|
||||||
|
NProgress.configure({ showSpinner: false, speed: 500, minimum: 0.3 })
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes: routes,
|
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<RouteRecordRaw>,
|
||||||
|
path: string,
|
||||||
|
name?: RouteRecordName | null | undefined,
|
||||||
|
) => Array<RouteRecordRaw> = (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
|
export default router
|
||||||
|
|
|
||||||
|
|
@ -1,210 +1,43 @@
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { type Ref } from 'vue'
|
import { type Ref } from 'vue'
|
||||||
// import type { User } from '@/api/type/user'
|
import loginApi from '@/api/user/login'
|
||||||
// import { cloneDeep } from 'lodash'
|
import type { LoginRequest } from '@/api/type/login'
|
||||||
// import UserApi from '@/api/user'
|
import useUserStore from './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
|
|
||||||
}
|
|
||||||
|
|
||||||
const useLoginStore = defineStore('login',{
|
const useLoginStore = defineStore('login', {
|
||||||
state: (): userStateTypes => ({
|
state: () => ({
|
||||||
userType: 1,
|
|
||||||
// userInfo: null,
|
|
||||||
token: '',
|
token: '',
|
||||||
version: '',
|
|
||||||
userAccessToken: '',
|
userAccessToken: '',
|
||||||
XPACK_LICENSE_IS_VALID: false,
|
|
||||||
isXPack: false,
|
|
||||||
themeInfo: null
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
// getLanguage() {
|
getToken(): String | null {
|
||||||
// return this.userType === 1
|
if (this.token) {
|
||||||
// ? localStorage.getItem('MaxKB-locale') || getBrowserLang()
|
return this.token
|
||||||
// : sessionStorage.getItem('language') || getBrowserLang()
|
}
|
||||||
// },
|
const user = useUserStore()
|
||||||
// showXpack() {
|
return user.userType === 1 ? localStorage.getItem('token') : this.getAccessToken()
|
||||||
// return this.isXPack
|
},
|
||||||
// },
|
getAccessToken() {
|
||||||
// isDefaultTheme() {
|
const token = sessionStorage.getItem(`${this.userAccessToken}-accessToken`)
|
||||||
// return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF'
|
if (token) {
|
||||||
// },
|
return token
|
||||||
// setTheme(data: any) {
|
}
|
||||||
// const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme)
|
const local_token = localStorage.getItem(`${token}-accessToken`)
|
||||||
// changeTheme(data?.['theme'])
|
if (local_token) {
|
||||||
// this.themeInfo = cloneDeep(data)
|
return local_token
|
||||||
// },
|
}
|
||||||
// isExpire() {
|
return localStorage.getItem(`accessToken`)
|
||||||
// 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() {
|
async asyncLogin(data: LoginRequest, loading?: Ref<boolean>) {
|
||||||
// if (this.userInfo) {
|
return loginApi.login(data).then((ok) => {
|
||||||
// return this.isXPack && this.XPACK_LICENSE_IS_VALID
|
this.token = ok.data
|
||||||
// ? [...this.userInfo?.permissions, 'x-pack']
|
localStorage.setItem('token', ok.data)
|
||||||
// : this.userInfo?.permissions
|
const user = useUserStore()
|
||||||
// } else {
|
return user.profile()
|
||||||
// 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<boolean>) {
|
|
||||||
// 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<boolean>) {
|
|
||||||
// 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)
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export default useLoginStore
|
export default useLoginStore
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { type Ref } from 'vue'
|
import { type Ref } from 'vue'
|
||||||
// import type { User } from '@/api/type/user'
|
import type { User } from '@/api/type/user'
|
||||||
import { cloneDeep } from 'lodash'
|
import { cloneDeep } from 'lodash'
|
||||||
// import UserApi from '@/api/user'
|
import UserApi from '@/api/user/user'
|
||||||
// import ThemeApi from '@/api/theme'
|
// import ThemeApi from '@/api/theme'
|
||||||
// import { useElementPlusTheme } from 'use-element-plus-theme'
|
// import { useElementPlusTheme } from 'use-element-plus-theme'
|
||||||
// import { defaultPlatformSetting } from '@/utils/theme'
|
// import { defaultPlatformSetting } from '@/utils/theme'
|
||||||
|
|
@ -10,10 +10,8 @@ import { useLocalStorage } from '@vueuse/core'
|
||||||
import { localeConfigKey, getBrowserLang } from '@/locales/index'
|
import { localeConfigKey, getBrowserLang } from '@/locales/index'
|
||||||
export interface userStateTypes {
|
export interface userStateTypes {
|
||||||
userType: number // 1 系统操作者 2 对话用户
|
userType: number // 1 系统操作者 2 对话用户
|
||||||
// userInfo: User | null
|
userInfo: User | null
|
||||||
token: any
|
|
||||||
version?: string
|
version?: string
|
||||||
userAccessToken?: string
|
|
||||||
XPACK_LICENSE_IS_VALID: false
|
XPACK_LICENSE_IS_VALID: false
|
||||||
isXPack: false
|
isXPack: false
|
||||||
themeInfo: any
|
themeInfo: any
|
||||||
|
|
@ -21,14 +19,12 @@ export interface userStateTypes {
|
||||||
|
|
||||||
const useLoginStore = defineStore('user', {
|
const useLoginStore = defineStore('user', {
|
||||||
state: (): userStateTypes => ({
|
state: (): userStateTypes => ({
|
||||||
userType: 1,
|
userType: 1, // 1 系统操作者 2 对话用户
|
||||||
// userInfo: null,
|
userInfo: null,
|
||||||
token: '',
|
|
||||||
version: '',
|
version: '',
|
||||||
userAccessToken: '',
|
|
||||||
XPACK_LICENSE_IS_VALID: false,
|
XPACK_LICENSE_IS_VALID: false,
|
||||||
isXPack: false,
|
isXPack: false,
|
||||||
themeInfo: null
|
themeInfo: null,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
getLanguage() {
|
getLanguage() {
|
||||||
|
|
@ -36,62 +32,17 @@ const useLoginStore = defineStore('user', {
|
||||||
? localStorage.getItem('MaxKB-locale') || getBrowserLang()
|
? localStorage.getItem('MaxKB-locale') || getBrowserLang()
|
||||||
: sessionStorage.getItem('language') || getBrowserLang()
|
: sessionStorage.getItem('language') || getBrowserLang()
|
||||||
},
|
},
|
||||||
// showXpack() {
|
|
||||||
// return this.isXPack
|
|
||||||
// },
|
|
||||||
isDefaultTheme() {
|
isDefaultTheme() {
|
||||||
return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF'
|
return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF'
|
||||||
},
|
},
|
||||||
// setTheme(data: any) {
|
async profile() {
|
||||||
// const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme)
|
return UserApi.getUserProfile().then((ok: { data: User }) => {
|
||||||
// changeTheme(data?.['theme'])
|
this.userInfo = ok.data
|
||||||
// this.themeInfo = cloneDeep(data)
|
useLocalStorage<string>(localeConfigKey, 'en-US').value =
|
||||||
// },
|
ok.data?.language || this.getLanguage()
|
||||||
// isExpire() {
|
// return this.asyncGetProfile()
|
||||||
// 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 asyncGetProfile() {
|
// async asyncGetProfile() {
|
||||||
// return new Promise((resolve, reject) => {
|
// return new Promise((resolve, reject) => {
|
||||||
// UserApi.getProfile()
|
// 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<boolean>) {
|
// async theme(loading?: Ref<boolean>) {
|
||||||
// return await ThemeApi.getThemeInfo(loading).then((ok) => {
|
// return await ThemeApi.getThemeInfo(loading).then((ok) => {
|
||||||
// this.setTheme(ok.data)
|
// 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) {
|
// async dingCallback(code: string) {
|
||||||
// return UserApi.getDingCallback(code).then((ok) => {
|
// return UserApi.getDingCallback(code).then((ok) => {
|
||||||
// this.token = ok.data
|
// this.token = ok.data
|
||||||
|
|
@ -204,7 +177,7 @@ const useLoginStore = defineStore('user', {
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export default useLoginStore
|
export default useLoginStore
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
@use './element-plus.scss';
|
@use './element-plus.scss';
|
||||||
@use './variables.scss';
|
@use './variables.scss';
|
||||||
@use './app.scss';
|
@use './app.scss';
|
||||||
|
@import 'nprogress/nprogress.css';
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
| 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<string>
|
||||||
|
|
||||||
|
permissionList: Array<string>
|
||||||
|
|
||||||
|
compare: 'OR' | 'AND'
|
||||||
|
|
||||||
|
constructor(roleList: Array<string>, permissionList: Array<string>, compare: 'OR' | 'AND') {
|
||||||
|
this.roleList = roleList
|
||||||
|
this.permissionList = permissionList
|
||||||
|
this.compare = compare
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,27 +2,27 @@ import { t } from '@/locales'
|
||||||
|
|
||||||
export const themeList = [
|
export const themeList = [
|
||||||
{
|
{
|
||||||
label: t('views.system.theme.default'),
|
label: t('theme.default'),
|
||||||
value: '#3370FF',
|
value: '#3370FF',
|
||||||
loginBackground: 'default',
|
loginBackground: 'default',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.system.theme.orange'),
|
label: t('theme.orange'),
|
||||||
value: '#FF8800',
|
value: '#FF8800',
|
||||||
loginBackground: 'orange',
|
loginBackground: 'orange',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.system.theme.green'),
|
label: t('theme.green'),
|
||||||
value: '#00B69D',
|
value: '#00B69D',
|
||||||
loginBackground: 'green',
|
loginBackground: 'green',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.system.theme.purple'),
|
label: t('theme.purple'),
|
||||||
value: '#7F3BF5',
|
value: '#7F3BF5',
|
||||||
loginBackground: 'purple',
|
loginBackground: 'purple',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('views.system.theme.red'),
|
label: t('theme.red'),
|
||||||
value: '#F01D94',
|
value: '#F01D94',
|
||||||
loginBackground: 'red',
|
loginBackground: 'red',
|
||||||
},
|
},
|
||||||
|
|
@ -38,7 +38,7 @@ export const defaultSetting = {
|
||||||
loginLogo: '',
|
loginLogo: '',
|
||||||
loginImage: '',
|
loginImage: '',
|
||||||
title: 'MaxKB',
|
title: 'MaxKB',
|
||||||
slogan: t('views.system.theme.defaultSlogan'),
|
slogan: t('theme.defaultSlogan'),
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultPlatformSetting = {
|
export const defaultPlatformSetting = {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<login-layout>
|
<login-layout>
|
||||||
<LoginContainer :subTitle="$t('views.system.theme.defaultSlogan')">
|
<LoginContainer :subTitle="$t('theme.defaultSlogan')">
|
||||||
<h2 class="mb-24">{{ $t('views.login.resetPassword') }}</h2>
|
<h2 class="mb-24">{{ $t('views.login.resetPassword') }}</h2>
|
||||||
<el-form
|
<el-form
|
||||||
class="reset-password-form"
|
class="reset-password-form"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<login-layout>
|
<login-layout>
|
||||||
<LoginContainer :subTitle="$t('views.system.theme.defaultSlogan')">
|
<LoginContainer :subTitle="$t('theme.defaultSlogan')">
|
||||||
<h2 class="mb-24">{{ $t('views.login.resetPassword') }}</h2>
|
<h2 class="mb-24">{{ $t('views.login.resetPassword') }}</h2>
|
||||||
<el-form
|
<el-form
|
||||||
class="reset-password-form"
|
class="reset-password-form"
|
||||||
|
|
|
||||||
|
|
@ -1,172 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="VerifyCode">
|
|
||||||
<canvas
|
|
||||||
id="VerifyCode-canvas"
|
|
||||||
:width="props.contentWidth"
|
|
||||||
:height="props.contentHeight"
|
|
||||||
@click="refreshCode"
|
|
||||||
></canvas>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { onMounted, watch, computed } from 'vue'
|
|
||||||
const props = defineProps({
|
|
||||||
code: {
|
|
||||||
type: String,
|
|
||||||
default: '1234',
|
|
||||||
},
|
|
||||||
fontSizeMin: {
|
|
||||||
type: Number,
|
|
||||||
default: 25,
|
|
||||||
},
|
|
||||||
fontSizeMax: {
|
|
||||||
type: Number,
|
|
||||||
default: 35,
|
|
||||||
},
|
|
||||||
backgroundColorMin: {
|
|
||||||
type: Number,
|
|
||||||
default: 255,
|
|
||||||
},
|
|
||||||
backgroundColorMax: {
|
|
||||||
type: Number,
|
|
||||||
default: 255,
|
|
||||||
},
|
|
||||||
colorMin: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
colorMax: {
|
|
||||||
type: Number,
|
|
||||||
default: 160,
|
|
||||||
},
|
|
||||||
lineColorMin: {
|
|
||||||
type: Number,
|
|
||||||
default: 40,
|
|
||||||
},
|
|
||||||
lineColorMax: {
|
|
||||||
type: Number,
|
|
||||||
default: 180,
|
|
||||||
},
|
|
||||||
dotColorMin: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
dotColorMax: {
|
|
||||||
type: Number,
|
|
||||||
default: 255,
|
|
||||||
},
|
|
||||||
contentWidth: {
|
|
||||||
type: Number,
|
|
||||||
default: 112,
|
|
||||||
},
|
|
||||||
contentHeight: {
|
|
||||||
type: Number,
|
|
||||||
default: 40,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
//验证码
|
|
||||||
const emit = defineEmits(['update:code'])
|
|
||||||
const verifyCode = computed({
|
|
||||||
get: () => {
|
|
||||||
return props.code
|
|
||||||
},
|
|
||||||
set: (data) => {
|
|
||||||
emit('update:code', data)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// 生成校验码
|
|
||||||
const makeCode = (len = 4) => {
|
|
||||||
let code = ''
|
|
||||||
const codeLength = len
|
|
||||||
const identifyCodes = '123456789abcdefjhijkinpqrsduvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
|
|
||||||
for (let i = 0; i < codeLength; i++) {
|
|
||||||
code += identifyCodes[randomNum(0, identifyCodes.length)]
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成一个随机数
|
|
||||||
const randomNum = (min = 0, max: number) => Math.floor(Math.random() * (max - min)) + min
|
|
||||||
|
|
||||||
// 生成一个随机的颜色
|
|
||||||
function randomColor(min: number, max: number) {
|
|
||||||
let r = randomNum(min, max)
|
|
||||||
let g = randomNum(min, max)
|
|
||||||
let b = randomNum(min, max)
|
|
||||||
return 'rgb(' + r + ',' + g + ',' + b + ')'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 绘制干扰线
|
|
||||||
const drawLine = (ctx: CanvasRenderingContext2D) => {
|
|
||||||
for (let i = 0; i < 5; i++) {
|
|
||||||
ctx.strokeStyle = randomColor(props.lineColorMin, props.lineColorMax)
|
|
||||||
ctx.beginPath()
|
|
||||||
ctx.moveTo(randomNum(0, props.contentWidth), randomNum(0, props.contentHeight))
|
|
||||||
ctx.lineTo(randomNum(0, props.contentWidth), randomNum(0, props.contentHeight))
|
|
||||||
ctx.stroke()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//在画布上显示数据
|
|
||||||
const drawText = (ctx: CanvasRenderingContext2D, txt: string, i: number) => {
|
|
||||||
ctx.fillStyle = randomColor(props.colorMin, props.colorMax)
|
|
||||||
ctx.font = randomNum(props.fontSizeMin, props.fontSizeMax) + 'px SimHei'
|
|
||||||
let x = (i + 1) * (props.contentWidth / (txt.length + 1))
|
|
||||||
let y = randomNum(props.fontSizeMax, props.contentHeight - 5)
|
|
||||||
var deg = randomNum(-45, 45)
|
|
||||||
// 修改坐标原点和旋转角度
|
|
||||||
ctx.translate(x, y)
|
|
||||||
ctx.rotate((deg * Math.PI) / 180)
|
|
||||||
ctx.fillText(txt[i], 0, 0)
|
|
||||||
// 恢复坐标原点和旋转角度
|
|
||||||
ctx.rotate((-deg * Math.PI) / 180)
|
|
||||||
ctx.translate(-x, -y)
|
|
||||||
}
|
|
||||||
// 绘制干扰点
|
|
||||||
const drawDot = (ctx: CanvasRenderingContext2D) => {
|
|
||||||
for (let i = 0; i < 80; i++) {
|
|
||||||
ctx.fillStyle = randomColor(0, 255)
|
|
||||||
ctx.beginPath()
|
|
||||||
ctx.arc(randomNum(0, props.contentWidth), randomNum(0, props.contentHeight), 1, 0, 2 * Math.PI)
|
|
||||||
ctx.fill()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//画图
|
|
||||||
const drawPic = () => {
|
|
||||||
let canvas = document.getElementById('VerifyCode-canvas') as HTMLCanvasElement
|
|
||||||
if (!canvas) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
|
||||||
ctx.textBaseline = 'bottom'
|
|
||||||
// 绘制背景
|
|
||||||
ctx.fillStyle = randomColor(props.backgroundColorMin, props.backgroundColorMax)
|
|
||||||
ctx.fillRect(0, 0, props.contentWidth, props.contentHeight)
|
|
||||||
// 绘制文字
|
|
||||||
for (let i = 0; i < verifyCode.value.length; i++) {
|
|
||||||
drawText(ctx, verifyCode.value, i)
|
|
||||||
}
|
|
||||||
drawLine(ctx)
|
|
||||||
drawDot(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置验证码
|
|
||||||
const refreshCode = () => {
|
|
||||||
emit('update:code', makeCode())
|
|
||||||
drawPic()
|
|
||||||
}
|
|
||||||
|
|
||||||
// defineExpose({ refreshCode });
|
|
||||||
|
|
||||||
//组件挂载
|
|
||||||
onMounted(() => {
|
|
||||||
drawPic()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.VerifyCode {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<login-layout v-if="!loading" v-loading="loading">
|
<login-layout v-if="!loading" v-loading="loading">
|
||||||
<LoginContainer :subTitle="user.themeInfo?.slogan || $t('views.system.theme.defaultSlogan')">
|
<LoginContainer :subTitle="user.themeInfo?.slogan || $t('theme.defaultSlogan')">
|
||||||
<h2 class="mb-24">{{ $t('views.login.title') }}</h2>
|
<h2 class="mb-24">{{ $t('views.login.title') }}</h2>
|
||||||
<div>
|
<div>
|
||||||
<el-form
|
<el-form
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
size="large"
|
size="large"
|
||||||
class="input-item"
|
class="input-item"
|
||||||
v-model="loginForm.username"
|
v-model="loginForm.username"
|
||||||
:placeholder="$t('views.user.userForm.form.username.placeholder')"
|
:placeholder="$t('views.login.loginForm.username.placeholder')"
|
||||||
>
|
>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -28,36 +28,41 @@
|
||||||
size="large"
|
size="large"
|
||||||
class="input-item"
|
class="input-item"
|
||||||
v-model="loginForm.password"
|
v-model="loginForm.password"
|
||||||
:placeholder="$t('views.user.userForm.form.password.placeholder')"
|
:placeholder="$t('views.login.loginForm.password.placeholder')"
|
||||||
show-password
|
show-password
|
||||||
>
|
>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-24">
|
<div class="mb-24">
|
||||||
<el-form-item prop="code">
|
<el-form-item prop="captcha">
|
||||||
<div class="flex-between w-full">
|
<div class="flex-between w-full">
|
||||||
<el-input
|
<el-input
|
||||||
size="large"
|
size="large"
|
||||||
class="input-item"
|
class="input-item"
|
||||||
v-model="loginForm.code"
|
v-model="loginForm.captcha"
|
||||||
placeholder="请输入验证码"
|
:placeholder="$t('views.login.loginForm.captcha.placeholder')"
|
||||||
>
|
>
|
||||||
</el-input>
|
</el-input>
|
||||||
<VerifyCode v-model:code="identifyCode" />
|
|
||||||
|
<img :src="identifyCode" alt="" height="40" class="ml-8 cursor" @click="makeCode" />
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<el-button size="large" type="primary" class="w-full" @click="login"
|
<el-button
|
||||||
|
size="large"
|
||||||
|
type="primary"
|
||||||
|
class="w-full"
|
||||||
|
@click="loginHandle"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
>{{ $t('views.login.buttons.login') }}
|
>{{ $t('views.login.buttons.login') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<div class="operate-container flex-between mt-12">
|
<div class="operate-container flex-between mt-12">
|
||||||
<!-- <el-button class="register" @click="router.push('/register')" link type="primary">
|
|
||||||
注册
|
|
||||||
</el-button> -->
|
|
||||||
<el-button
|
<el-button
|
||||||
|
:loading="loading"
|
||||||
class="forgot-password"
|
class="forgot-password"
|
||||||
@click="router.push('/forgot_password')"
|
@click="router.push('/forgot_password')"
|
||||||
link
|
link
|
||||||
|
|
@ -77,67 +82,64 @@ import type { FormInstance, FormRules } from 'element-plus'
|
||||||
import type { LoginRequest } from '@/api/type/login'
|
import type { LoginRequest } from '@/api/type/login'
|
||||||
import LoginContainer from '@/views/login/components/LoginContainer.vue'
|
import LoginContainer from '@/views/login/components/LoginContainer.vue'
|
||||||
import LoginLayout from '@/views/login/components/LoginLayout.vue'
|
import LoginLayout from '@/views/login/components/LoginLayout.vue'
|
||||||
import VerifyCode from './components/VerifyCode.vue'
|
import loginApi from '@/api/user/login'
|
||||||
import { t, getBrowserLang } from '@/locales'
|
import { t, getBrowserLang } from '@/locales'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { user } = useStore()
|
const { login, user } = useStore()
|
||||||
// const { locale } = useI18n({ useScope: 'global' })
|
const { locale } = useI18n({ useScope: 'global' })
|
||||||
const loading = ref<boolean>(false)
|
const loading = ref<boolean>(false)
|
||||||
const identifyCode = ref<string>('1234')
|
|
||||||
|
const identifyCode = ref<string>('')
|
||||||
|
|
||||||
const loginFormRef = ref<FormInstance>()
|
const loginFormRef = ref<FormInstance>()
|
||||||
const loginForm = ref<LoginRequest>({
|
const loginForm = ref<LoginRequest>({
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
code: '',
|
captcha: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
const rules = ref<FormRules<LoginRequest>>({
|
const rules = ref<FormRules<LoginRequest>>({
|
||||||
username: [
|
username: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t('views.user.userForm.form.username.requiredMessage'),
|
message: t('views.login.loginForm.username.requiredMessage'),
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
password: [
|
password: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t('views.user.userForm.form.password.requiredMessage'),
|
message: t('views.login.loginForm.password.requiredMessage'),
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
captcha: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t('views.login.loginForm.captcha.requiredMessage'),
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
// const modeList = ref<string[]>([''])
|
const loginHandle = () => {
|
||||||
// const QrList = ref<any[]>([''])
|
loginFormRef.value?.validate().then(() => {
|
||||||
// const loginMode = ref('')
|
login.asyncLogin(loginForm.value, loading).then(() => {
|
||||||
// const showQrCodeTab = ref(false)
|
locale.value = localStorage.getItem('MaxKB-locale') || getBrowserLang() || 'en-US'
|
||||||
|
router.push({ name: 'home' })
|
||||||
// interface qrOption {
|
})
|
||||||
// key: string
|
})
|
||||||
// value: string
|
}
|
||||||
// }
|
function makeCode() {
|
||||||
|
loginApi.getCaptcha().then((res: any) => {
|
||||||
// const orgOptions = ref<qrOption[]>([])
|
identifyCode.value = res.data.captcha
|
||||||
|
})
|
||||||
const login = () => {
|
|
||||||
// loginFormRef.value?.validate().then(() => {
|
|
||||||
// loading.value = true
|
|
||||||
// user
|
|
||||||
// .login(loginMode.value, loginForm.value.username, loginForm.value.password)
|
|
||||||
// .then(() => {
|
|
||||||
// locale.value = localStorage.getItem('MaxKB-locale') || getBrowserLang() || 'en-US'
|
|
||||||
// router.push({ name: 'home' })
|
|
||||||
// })
|
|
||||||
// .finally(() => (loading.value = false))
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
// loading.value = true
|
makeCode()
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {})
|
onMounted(() => {})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue