fix: user language

This commit is contained in:
wangdan-fit2cloud 2025-07-10 17:09:19 +08:00
parent 12feaac958
commit f926de4f91
27 changed files with 178 additions and 204 deletions

View File

@ -301,7 +301,7 @@ const getMcpTools: (
*
* @param file:file
*/
const uploadFile: (
const postUploadFile: (
file: any,
sourceId: string,
resourceType:
@ -313,12 +313,13 @@ const uploadFile: (
| 'TEMPORARY_30_MINUTE'
| 'TEMPORARY_120_MINUTE'
| 'TEMPORARY_1_DAY',
) => Promise<Result<any>> = (file, sourceId, resourceType) => {
loading?: Ref<boolean>,
) => Promise<Result<any>> = (file, sourceId, resourceType, loading) => {
const fd = new FormData()
fd.append('file', file)
fd.append('source_id', sourceId)
fd.append('source_type', resourceType)
return post(`/oss/file`, fd)
return post(`/oss/file`, fd, undefined, loading)
}
export default {
@ -346,5 +347,5 @@ export default {
postTextToSpeech,
speechToText,
getMcpTools,
uploadFile,
postUploadFile,
}

View File

@ -297,7 +297,7 @@ const modifyChat: (chat_id: string, data: any, loading?: Ref<boolean>) => Promis
* @param resourceType
* @returns
*/
const uploadFile: (
const postUploadFile: (
file: any,
sourceId: string,
resourceType:
@ -309,12 +309,13 @@ const uploadFile: (
| 'TEMPORARY_30_MINUTE'
| 'TEMPORARY_120_MINUTE'
| 'TEMPORARY_1_DAY',
) => Promise<Result<any>> = (file, sourceId, sourceType) => {
loading?: Ref<boolean>,
) => Promise<Result<any>> = (file, sourceId, sourceType, loading) => {
const fd = new FormData()
fd.append('file', file)
fd.append('source_id', sourceId)
fd.append('source_type', sourceType)
return post(`/oss/file`, fd)
return post(`/oss/file`, fd, undefined, loading)
}
export default {
open,
@ -344,5 +345,5 @@ export default {
speechToText,
deleteChat,
modifyChat,
uploadFile,
postUploadFile,
}

View File

@ -73,11 +73,11 @@
</div>
</template>
<script setup lang="ts">
import { computed, onMounted } from 'vue'
import KnowledgeSourceComponent from '@/components/ai-chat/component/knowledge-source-component/index.vue'
import MdRenderer from '@/components/markdown/MdRenderer.vue'
import OperationButton from '@/components/ai-chat/component/operation-button/index.vue'
import { type chatType } from '@/api/type/application'
import { computed } from 'vue'
import bus from '@/bus'
import useStore from '@/stores'
const props = defineProps<{
@ -100,7 +100,7 @@ const emit = defineEmits([
])
const showAvatar = computed(() => {
return (user.isEE() || user.isPE())? props.application.show_avatar : true
return user.isEE() || user.isPE() ? props.application.show_avatar : true
})
const showUserAvatar = computed(() => {
return user.isEE() || user.isPE() ? props.application.show_user_avatar : true
@ -165,5 +165,11 @@ const stopChat = (chat: chatType) => {
const startChat = (chat: chatType) => {
props.chatManagement.write(chat.id)
}
onMounted(() => {
bus.on('chat:stop', () => {
stopChat(props.chatRecord)
})
})
</script>
<style lang="scss" scoped></style>

View File

@ -14,7 +14,11 @@
</el-button>
<!-- 使用 custom-class 自定义样式 -->
<transition name="el-fade-in-linear">
<el-card class="custom-speech-card" :class="isTouching ? '' : 'active'" v-if="dialogVisible">
<el-card
class="custom-speech-card white-bg"
:class="isTouching ? '' : 'active'"
v-if="dialogVisible"
>
<p>
<el-text type="info" v-if="isTouching"
>00:{{ props.time < 10 ? `0${props.time}` : props.time }}</el-text
@ -43,16 +47,16 @@ import { ref, watch } from 'vue'
const props = defineProps({
time: {
type: Number,
default: 0
default: 0,
},
start: {
type: Boolean,
default: false
default: false,
},
disabled: {
type: Boolean,
default: false
}
default: false,
},
})
const emit = defineEmits(['TouchStart', 'TouchEnd'])
//
@ -77,7 +81,7 @@ watch(
dialogVisible.value = false
isTouching.value = false
}
}
},
)
watch(
() => props.start,
@ -90,7 +94,7 @@ watch(
dialogVisible.value = false
isTouching.value = false
}
}
},
)
function onTouchStart(event: any) {
@ -127,7 +131,6 @@ function onTouchEnd() {
left: 50%; /* 水平居中 */
transform: translateX(-50%);
width: 92%;
background: #ffffff;
border: 1px solid #ffffff;
box-shadow: 0px 6px 24px 0px rgba(31, 35, 41, 0.08);
z-index: 999;

View File

@ -1,10 +1,16 @@
<template>
<div class="ai-chat__operate p-16">
<div class="text-center mb-8" v-if="loading">
<el-button class="border-primary video-stop-button" @click="stopChat">
<app-icon iconName="app-video-stop" class="mr-8"></app-icon>
{{ $t('chat.operation.stopChat') }}</el-button
>
</div>
<div class="operate-textarea">
<el-scrollbar max-height="136">
<div
class="p-8-12"
v-loading="localLoading"
v-loading="uploadLoading"
v-if="
uploadDocumentList.length ||
uploadImageList.length ||
@ -143,6 +149,7 @@
</el-icon>
</div>
<el-image
v-if="item.url"
:src="item.url"
alt=""
fit="cover"
@ -299,7 +306,6 @@ import bus from '@/bus'
import 'recorder-core/src/engine/mp3'
import 'recorder-core/src/engine/mp3-engine'
import { MsgWarning } from '@/utils/message'
import { debounce } from 'lodash'
import chatAPI from '@/api/chat/chat'
const router = useRouter()
const route = useRoute()
@ -347,6 +353,8 @@ const localLoading = computed({
},
})
const uploadLoading = ref(false)
const inputPlaceholder = computed(() => {
return recorderStatus.value === 'START'
? `${t('chat.inputPlaceholder.speaking')}...`
@ -430,8 +438,13 @@ const uploadFile = async (file: any, fileList: any) => {
}
const api =
props.type === 'debug-ai-chat'
? applicationApi.uploadFile(file.raw, 'TEMPORARY_120_MINUTE', 'TEMPORARY_120_MINUTE')
: chatAPI.uploadFile(file.raw, chatId_context.value, 'CHAT')
? applicationApi.postUploadFile(
file.raw,
'TEMPORARY_120_MINUTE',
'TEMPORARY_120_MINUTE',
uploadLoading,
)
: chatAPI.postUploadFile(file.raw, chatId_context.value, 'CHAT', uploadLoading)
api.then((ok) => {
file.url = ok.data
const split_path = ok.data.split('/')
@ -639,7 +652,7 @@ class RecorderManage {
}
const getSpeechToTextAPI = () => {
if (props.type === 'ai-chat') {
return (application_id?: string, data?: any, loading?: Ref<boolean>) => {
return (data?: any, loading?: Ref<boolean>) => {
return chatAPI.speechToText(data, loading)
}
} else {
@ -802,6 +815,10 @@ function mouseenter(row: any) {
function mouseleave() {
showDelete.value = ''
}
function stopChat() {
bus.emit('chat:stop')
}
onMounted(() => {
bus.on('chat-input', (message: string) => {
inputValue.value = message

View File

@ -20,9 +20,9 @@
link
>{{ $t('chat.operation.continue') }}
</el-button>
<el-button type="primary" v-else-if="!chatRecord.write_ed" @click="stopChat(chatRecord)" link
<!-- <el-button type="primary" v-else-if="!chatRecord.write_ed" @click="stopChat(chatRecord)" link
>{{ $t('chat.operation.stopChat') }}
</el-button>
</el-button> -->
</div>
<ChatOperationButton

View File

@ -51,7 +51,9 @@
:executionIsRightPanel="props.executionIsRightPanel"
@open-execution-detail="emit('openExecutionDetail', chatList[index])"
@openParagraph="emit('openParagraph', chatList[index])"
@openParagraphDocument="(val: any)=>emit('openParagraphDocument', chatList[index], val)"
@openParagraphDocument="
(val: any) => emit('openParagraphDocument', chatList[index], val)
"
></AnswerContent>
</template>
<TransitionContent
@ -77,9 +79,6 @@
v-model:show-user-input="showUserInput"
v-if="type !== 'log'"
>
<template #operateBefore>
<slot name="operateBefore"> </slot>
</template>
<template #userInput>
<el-button
v-if="isUserInput || isAPIInput"
@ -105,7 +104,6 @@ import chatLogApi from '@/api/application/chat-log'
import { ChatManagement, type chatType } from '@/api/type/application'
import { randomId } from '@/utils/common'
import useStore from '@/stores'
import { isWorkFlow } from '@/utils/application'
import { debounce } from 'lodash'
import AnswerContent from '@/components/ai-chat/component/answer-content/index.vue'
import QuestionContent from '@/components/ai-chat/component/question-content/index.vue'
@ -139,7 +137,13 @@ const props = withDefaults(
type: 'ai-chat',
},
)
const emit = defineEmits(['refresh', 'scroll', 'openExecutionDetail', 'openParagraph','openParagraphDocument'])
const emit = defineEmits([
'refresh',
'scroll',
'openExecutionDetail',
'openParagraph',
'openParagraphDocument',
])
const { application, common } = useStore()
const isMobile = computed(() => {
return common.isMobile() || mode === 'embed' || mode === 'mobile'
@ -246,14 +250,18 @@ function sendMessage(val: string, other_params_data?: any, chat?: chatType): Pro
return userFormRef.value
?.validate()
.then((ok) => {
let userFormData = JSON.parse(localStorage.getItem(`${accessToken}userForm`) || '{}')
let userFormData = accessToken
? JSON.parse(localStorage.getItem(`${accessToken}userForm`) || '{}')
: {}
const newData = Object.keys(form_data.value).reduce((result: any, key: string) => {
result[key] = Object.prototype.hasOwnProperty.call(userFormData, key)
? userFormData[key]
: form_data.value[key]
return result
}, {})
localStorage.setItem(`${accessToken}userForm`, JSON.stringify(newData))
if (accessToken) {
localStorage.setItem(`${accessToken}userForm`, JSON.stringify(newData))
}
showUserInput.value = false
@ -300,11 +308,11 @@ const openChatId: () => Promise<string> = () => {
return res.data
})
.catch((res) => {
if (res.response.status === 403) {
return application.asyncAppAuthentication(accessToken).then(() => {
return openChatId()
})
}
// if (res.response.status === 403) {
// return application.asyncAppAuthentication(accessToken).then(() => {
// return openChatId()
// })
// }
return Promise.reject(res)
})
}
@ -512,16 +520,7 @@ function chatMessage(chat?: any, problem?: string, re_chat?: boolean, other_para
//
getChatMessageAPI()(chartOpenId.value, obj)
.then((response) => {
if (response.status === 401) {
application
.asyncAppAuthentication(accessToken)
.then(() => {
chatMessage(chat, problem)
})
.catch(() => {
errorWrite(chat)
})
} else if (response.status === 460) {
if (response.status === 460) {
return Promise.reject(t('chat.tip.errorIdentifyMessage'))
} else if (response.status === 461) {
return Promise.reject(t('chat.tip.errorLimitMessage'))
@ -661,6 +660,13 @@ defineExpose({
width: calc(100% - 50px);
max-width: 400px;
}
.video-stop-button {
box-shadow: 0px 6px 24px 0px rgba(31, 35, 41, 0.08);
&:hover {
background: #ffffff;
}
}
@media only screen and (max-width: 768px) {
.firstUserInput {
.user-form-container {

View File

@ -4,7 +4,7 @@
:is="
Object.keys(iconMap).includes(iconName)
? iconMap[iconName].iconReader()
: iconMap['404'].iconReader()
: iconMap['app-404'].iconReader()
"
class="el-icon app-icon"
>
@ -22,7 +22,7 @@ const props = withDefaults(
iconName?: string
}>(),
{
iconName: '404',
iconName: 'app-404',
},
)

View File

@ -292,7 +292,7 @@ export default {
])
},
},
'app-play-outlined': {
'app-debug-outlined': {
iconReader: () => {
return h('i', [
h(

View File

@ -230,6 +230,39 @@ export const iconMap: any = {
])
},
},
'app-404': {
iconReader: () => {
return h('i', [
h(
'svg',
{
viewBox: '0 0 1024 1024',
version: '1.1',
style: 'height:14px;width:14px',
xmlns: 'http://www.w3.org/2000/svg',
},
[
h('path', {
d: 'M260.266667 789.333333c-21.333333 0-38.4-17.066667-38.4-38.4v-59.733333H38.4c-12.8 0-29.866667-8.533333-34.133333-21.333333-4.266667-17.066667-4.266667-29.866667 4.266666-42.666667l221.866667-294.4c8.533333-12.8 25.6-17.066667 42.666667-12.8 17.066667 4.266667 25.6 21.333333 25.6 38.4v256h34.133333c21.333333 0 38.4 17.066667 38.4 38.4s-17.066667 38.4-38.4 38.4H298.666667v59.733333c0 21.333333-17.066667 38.4-38.4 38.4z m-145.066667-179.2h106.666667V469.333333l-106.666667 140.8zM913.066667 742.4c-21.333333 0-38.4-17.066667-38.4-38.4v-59.733333h-183.466667c-12.8 0-29.866667-8.533333-34.133333-21.333334-8.533333-12.8-4.266667-29.866667 4.266666-38.4l221.866667-294.4c8.533333-12.8 25.6-17.066667 42.666667-12.8 17.066667 4.266667 25.6 21.333333 25.6 38.4v256h34.133333c21.333333 0 38.4 17.066667 38.4 38.4s-17.066667 38.4-38.4 38.4h-34.133333v59.733334c0 17.066667-17.066667 34.133333-38.4 34.133333zM768 567.466667h106.666667V426.666667L768 567.466667zM533.333333 597.333333c-46.933333 0-85.333333-25.6-119.466666-68.266666-29.866667-38.4-42.666667-93.866667-42.666667-145.066667 0-55.466667 17.066667-106.666667 42.666667-145.066667 29.866667-42.666667 72.533333-68.266667 119.466666-68.266666 46.933333 0 85.333333 25.6 119.466667 68.266666 29.866667 38.4 42.666667 93.866667 42.666667 145.066667 0 55.466667-17.066667 106.666667-42.666667 145.066667-34.133333 46.933333-76.8 68.266667-119.466667 68.266666z m0-362.666666c-55.466667 0-98.133333 68.266667-98.133333 149.333333s46.933333 149.333333 98.133333 149.333333c55.466667 0 98.133333-68.266667 98.133334-149.333333s-46.933333-149.333333-98.133334-149.333333z',
fill: '#978CFF',
}),
h('path', {
d: 'M354.133333 691.2a162.133333 21.333333 0 1 0 324.266667 0 162.133333 21.333333 0 1 0-324.266667 0Z',
fill: '#E3E5FC',
}),
h('path', {
d: 'M8.533333 832a162.133333 21.333333 0 1 0 324.266667 0 162.133333 21.333333 0 1 0-324.266667 0Z',
fill: '#E3E5FC',
}),
h('path', {
d: 'M661.333333 797.866667a162.133333 21.333333 0 1 0 324.266667 0 162.133333 21.333333 0 1 0-324.266667 0Z',
fill: '#E3E5FC',
}),
],
),
])
},
},
// 动态加载的图标
...dynamicIcons,
}

View File

@ -2,7 +2,7 @@
<el-dropdown placement="bottom-start" class="workspace-dropdown" popper-class="workspace-dropdown-popper">
<el-button text style="font-size: 14px" class="workspace-dropdown__button">
<AppIcon iconName="app-workspace" style="font-size: 18px"></AppIcon>
<span class="ellipsis" style="max-width: 155px">
<span class="ellipsis" style="max-width: 155px" :title="currentWorkspace?.name">
{{ currentWorkspace?.name }}
</span>
<el-icon class="el-icon--right">
@ -19,7 +19,7 @@
:class="`${item.id === currentWorkspace?.id ? 'active' : ''} flex-between`" @click="changeWorkspace(item)">
<div class="flex align-center">
<AppIcon class="mr-8" iconName="app-workspace" style="font-size: 16px"></AppIcon>
<span class="ellipsis">
<span class="ellipsis" :title="item.name">
{{ item.name }}
</span>
</div>

View File

@ -271,7 +271,7 @@ export default {
label: '文本转语音',
text: '将文本通过语音合成模型转换为音频',
tts_model: {
label: '语音识别模型',
label: '语音合成模型',
},
content: {
label: '选择文本内容',

View File

@ -1,28 +1,28 @@
import { useLocalStorage } from '@vueuse/core';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { i18n, langCode, localeConfigKey } from '@/locales/index';
import { useLocalStorage } from '@vueuse/core'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { i18n, langCode, localeConfigKey } from '@/locales/index'
export function useLocale() {
const { locale } = useI18n({ useScope: 'global' });
function changeLocale(lang: string) {
// 如果切换的语言不在对应语言文件里则默认为简体中文
if (!langCode.includes(lang)) {
lang = 'en-US';
}
locale.value = lang;
useLocalStorage(localeConfigKey, 'en-US').value = lang;
const { locale } = useI18n({ useScope: 'global' })
function changeLocale(lang: string) {
// 如果切换的语言不在对应语言文件里则默认为简体中文
if (!langCode.includes(lang)) {
lang = 'en-US'
}
const getComponentsLocale = computed(() => {
const localeMessage = i18n.global.getLocaleMessage(locale.value) as Record<string, any>;
return localeMessage.componentsLocale;
});
locale.value = lang
useLocalStorage(localeConfigKey, 'en-US').value = lang
}
return {
changeLocale,
getComponentsLocale,
locale,
};
const getComponentsLocale = computed(() => {
const localeMessage = i18n.global.getLocaleMessage(locale.value) as Record<string, any>
return localeMessage.componentsLocale
})
return {
changeLocale,
getComponentsLocale,
locale,
}
}

View File

@ -24,8 +24,8 @@ instance.interceptors.request.use(
}
const { chatUser } = useStore()
const token = chatUser.getToken()
// const language = chatUser.getLanguage()
// config.headers['Accept-Language'] = `${language}`
const language = chatUser.getLanguage()
config.headers['Accept-Language'] = `${language}`
if (token) {
config.headers['AUTHORIZATION'] = `Bearer ${token}`
}
@ -177,12 +177,12 @@ export const postStream: (url: string, data?: unknown) => Promise<Result<any> |
) => {
const { chatUser } = useStore()
const token = chatUser.getToken()
// const language = user.getLanguage()
const language = chatUser.getLanguage()
const headers: HeadersInit = { 'Content-Type': 'application/json' }
if (token) {
headers['AUTHORIZATION'] = `Bearer ${token}`
}
// headers['Accept-Language'] = `${language}`
headers['Accept-Language'] = `${language}`
return fetch(url, {
method: 'POST',
body: data ? JSON.stringify(data) : undefined,

View File

@ -47,27 +47,6 @@ const useApplicationStore = defineStore('application', {
})
},
async asyncAppAuthentication(
token: string,
loading?: Ref<boolean>,
authentication_value?: any,
) {
return new Promise((resolve, reject) => {
applicationApi
.postAppAuthentication(token, loading, authentication_value)
.then((res: any) => {
localStorage.setItem(`${token}-accessToken`, res.data)
sessionStorage.setItem(`${token}-accessToken`, res.data)
resolve(res)
})
.catch((error: any) => {
reject(error)
})
})
},
async refreshAccessToken(token: string) {
this.asyncAppAuthentication(token)
},
// 修改应用
async asyncPutApplication(id: string, data: any, loading?: Ref<boolean>) {
return new Promise((resolve, reject) => {

View File

@ -3,9 +3,8 @@ import ChatAPI from '@/api/chat/chat'
import type { ChatProfile, ChatUserProfile } from '@/api/type/chat'
import type { LoginRequest } from '@/api/type/user'
import type { Ref } from 'vue'
import { useLocalStorage } from '@vueuse/core'
import { localeConfigKey } from '@/locales/index'
import useUserStore from './user'
import { getBrowserLang } from '@/locales/index'
interface ChatUser {
// 用户id
id: string
@ -24,6 +23,9 @@ const useChatUserStore = defineStore('chat-user', {
accessToken: undefined,
}),
actions: {
getLanguage() {
return localStorage.getItem(`${this.accessToken}-locale`) || getBrowserLang()
},
setAccessToken(accessToken: string) {
this.accessToken = accessToken
},
@ -41,9 +43,8 @@ const useChatUserStore = defineStore('chat-user', {
applicationProfile() {
return ChatAPI.applicationProfile().then((ok) => {
this.application = ok.data
const user = useUserStore()
useLocalStorage<string>(localeConfigKey, 'en-US').value =
ok?.data?.language || user.getLanguage()
localStorage.setItem(`${this.accessToken}-locale`, ok.data?.language || this.getLanguage())
if (this.application.custom_theme) {
this.application['custom_theme']['theme_color'] =
ok.data?.custom_theme?.theme_color || '#3370FF'

View File

@ -1,32 +1,19 @@
import {defineStore} from 'pinia'
import {type Ref} from 'vue'
import { defineStore } from 'pinia'
import { type Ref } from 'vue'
import LoginApi from '@/api/user/login'
import type {LoginRequest} from '@/api/type/login'
import type { LoginRequest } from '@/api/type/login'
import useUserStore from './user'
const useLoginStore = defineStore('login', {
state: () => ({
token: '',
userAccessToken: '',
}),
actions: {
getToken(): string | null {
if (this.token) {
return this.token
}
const user = useUserStore()
return user.userType === 1 ? localStorage.getItem('token') : this.getAccessToken()
},
getAccessToken() {
const token = sessionStorage.getItem(`${this.userAccessToken}-accessToken`)
if (token) {
return token
}
const local_token = localStorage.getItem(`${token}-accessToken`)
if (local_token) {
return local_token
}
return localStorage.getItem(`accessToken`)
return localStorage.getItem('token')
},
async asyncLogin(data: LoginRequest, loading?: Ref<boolean>) {
@ -99,7 +86,6 @@ const useLoginStore = defineStore('login', {
return ok.data
})
},
},
})

View File

@ -11,7 +11,6 @@ import { defaultPlatformSetting } from '@/utils/theme'
import useLoginStore from './login'
export interface userStateTypes {
userType: number // 1 系统操作者 2 对话用户
userInfo: User | null
version?: string
license_is_valid: boolean
@ -22,7 +21,6 @@ export interface userStateTypes {
const useUserStore = defineStore('user', {
state: (): userStateTypes => ({
userType: 1, // 1 系统操作者 2 对话用户
userInfo: null,
version: '',
license_is_valid: false,
@ -32,11 +30,8 @@ const useUserStore = defineStore('user', {
}),
actions: {
getLanguage() {
return this.userType === 1
? localStorage.getItem('MaxKB-locale') || getBrowserLang()
: sessionStorage.getItem('language') || getBrowserLang()
return localStorage.getItem('MaxKB-locale') || getBrowserLang()
},
setWorkspaceId(workspace_id: string) {
this.workspace_id = workspace_id
localStorage.setItem('workspace_id', workspace_id)

View File

@ -433,7 +433,6 @@ h5 {
.layout-bg {
background: var(--app-layout-bg-color);
}
.white-bg {
background: #ffffff;
}

View File

@ -1,5 +1,5 @@
<template>
<div v-show="show" class="workflow-dropdown-menu border border-r-6">
<div v-show="show" class="workflow-dropdown-menu border border-r-6 white-bg">
<el-tabs v-model="activeName" class="workflow-dropdown-tabs">
<div style="display: flex; width: 100%; justify-content: center" class="mb-12">
<el-input
@ -321,7 +321,6 @@ onMounted(() => {
z-index: 99;
width: 400px;
box-shadow: 0px 4px 8px 0px var(--app-text-color-light-1);
background: #ffffff;
padding-bottom: 8px;
.title {

View File

@ -1,5 +1,5 @@
<template>
<div class="workflow-publish-history border-l">
<div class="workflow-publish-history border-l white-bg">
<h4 class="border-b p-16-24">{{ $t('views.applicationWorkflow.setting.releaseHistory') }}</h4>
<div class="list-height pt-0">
<el-scrollbar>
@ -137,7 +137,6 @@ onMounted(() => {
position: absolute;
right: 0;
top: 57px;
background: #ffffff;
height: calc(100vh - 57px);
z-index: 9;
.list-height {

View File

@ -1,6 +1,6 @@
<template>
<div class="application-workflow" v-loading="loading">
<div class="header border-b flex-between p-12-24">
<div class="header border-b flex-between p-12-24 white-bg">
<div class="flex align-center">
<back-button @click="back"></back-button>
<h4>{{ detail?.name }}</h4>
@ -29,7 +29,7 @@
{{ $t('views.applicationWorkflow.setting.addComponent') }}
</el-button>
<el-button @click="clickShowDebug" :disabled="showDebug">
<AppIcon iconName="app-play-outlined" class="mr-4"></AppIcon>
<AppIcon iconName="app-debug-outlined" class="mr-4"></AppIcon>
{{ $t('views.applicationWorkflow.setting.debug') }}</el-button
>
<el-button @click="saveApplication(true)">
@ -142,7 +142,7 @@ import Workflow from '@/workflow/index.vue'
import DropdownMenu from '@/views/application-workflow/component/DropdownMenu.vue'
import PublishHistory from '@/views/application-workflow/component/PublishHistory.vue'
import ApplicationAPI from '@/api/application/application'
import { isAppIcon,resetUrl } from '@/utils/common'
import { isAppIcon, resetUrl } from '@/utils/common'
import { MsgSuccess, MsgError, MsgConfirm } from '@/utils/message'
import { datetimeFormat } from '@/utils/time'
import { mapToUrlParams } from '@/utils/application'
@ -575,9 +575,6 @@ onBeforeUnmount(() => {
.application-workflow {
background: var(--app-layout-bg-color);
height: 100%;
.header {
background: #ffffff;
}
.workflow-main {
height: calc(100vh - 62px);
box-sizing: border-box;

View File

@ -7,10 +7,11 @@
/>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { ref, computed, onBeforeMount } from 'vue'
import { useRoute } from 'vue-router'
import useStore from '@/stores'
import { useI18n } from 'vue-i18n'
const { locale } = useI18n({ useScope: 'global' })
const route = useRoute()
const { chatUser, common } = useStore()
@ -23,7 +24,6 @@ const {
} = route as any
const currentTemplate = computed(() => {
console.log(common.isMobile())
let modeName = ''
if (!mode || mode === 'pc') {
modeName = common.isMobile() ? 'mobile' : 'pc'
@ -34,6 +34,8 @@ const currentTemplate = computed(() => {
return components[name].default
})
const applicationAvailable = ref<boolean>(true)
onBeforeMount(() => {
locale.value = chatUser.getLanguage()
})
</script>

View File

@ -1,50 +0,0 @@
<template>
<div>
<el-form ref="FormRef" :model="form" @submit.prevent="validator">
<el-form-item prop="value" :rules="rules">
<el-input show-password v-model="form.value" />
</el-form-item>
<el-button class="w-full mt-8" type="primary" @click="validator" :loading="loading">
{{ $t('common.confirm') }}</el-button
>
</el-form>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useRoute } from 'vue-router'
import useStore from '@/stores'
import { t } from '@/locales'
const route = useRoute()
const FormRef = ref()
const {
params: { accessToken },
} = route as any
const { application } = useStore()
const loading = ref<boolean>(false)
const auth = () => {
return application.asyncAppAuthentication(accessToken, loading, form.value).then(() => {})
}
const validator_auth = (rule: any, value: string, callback: any) => {
if (value === '') {
callback(new Error(t('chat.passwordValidator.errorMessage1')))
} else {
auth().catch(() => {
callback(new Error(t('chat.passwordValidator.errorMessage2')))
})
}
}
const validator = () => {
FormRef.value.validate()
}
const rules = reactive({
value: [{ required: true, validator: validator_auth, trigger: 'manual' }],
})
const form = ref({
type: 'password',
value: '',
})
</script>
<style lang="scss" scoped></style>

View File

@ -16,13 +16,13 @@
@click="changeLang(lang.value)"
class="flex-between"
>
<span :class="lang.value === user.getLanguage() ? 'primary' : ''">{{
<span :class="lang.value === chatUser.getLanguage() ? 'primary' : ''">{{
lang.label
}}</span>
<el-icon
:class="lang.value === user.getLanguage() ? 'primary' : ''"
v-if="lang.value === user.getLanguage()"
:class="lang.value === chatUser.getLanguage() ? 'primary' : ''"
v-if="lang.value === chatUser.getLanguage()"
>
<Check />
</el-icon>
@ -51,7 +51,7 @@ defineProps({
default: true,
},
})
const { user, theme } = useStore()
const { chatUser, theme } = useStore()
const changeLang = (lang: string) => {
useLocalStorage(localeConfigKey, getBrowserLang()).value = lang
@ -59,7 +59,7 @@ const changeLang = (lang: string) => {
}
const currentLanguage = computed(() => {
return langList.value?.filter((v: any) => v.value === user.getLanguage())?.[0]?.label
return langList.value?.filter((v: any) => v.value === chatUser.getLanguage())?.[0]?.label
})
const fileURL = computed(() => {

View File

@ -166,7 +166,7 @@ import PasswordAuth from '@/views/chat/auth/component/password.vue'
import { isAppIcon } from '@/utils/common'
const router = useRouter()
const { login, user, theme, chatUser } = useStore()
const { theme, chatUser } = useStore()
const { locale } = useI18n({ useScope: 'global' })
const loading = ref<boolean>(false)
const route = useRoute()
@ -226,6 +226,7 @@ function makeCode() {
}
onBeforeMount(() => {
locale.value = chatUser.getLanguage()
makeCode()
})

View File

@ -1,5 +1,5 @@
<template>
<div class="login-preview mr-16">
<div class="login-preview mr-16 white-bg">
<div class="header">
<div class="tag flex-between">
<div class="flex align-center">
@ -78,7 +78,6 @@ const fileURL = computed(() => {
<style lang="scss" scoped>
.login-preview {
background: #ffffff;
border-radius: 4px;
transform-origin: center;
.login-container {