-
-
-`
- }
-
- function getHighestZIndexValue() {
- try {
- let maxZIndex = -Infinity
- let foundAny = false
-
- const allElements = document.all || document.querySelectorAll('*')
-
- for (let i = 0; i < allElements.length; i++) {
- const element = allElements[i]
-
- if (!element || element.nodeType !== 1) continue
-
- const styles = window.getComputedStyle(element)
-
- const position = styles.position
- if (position === 'static') continue
-
- const zIndex = styles.zIndex
- let zIndexValue
-
- if (zIndex === 'auto') {
- zIndexValue = 0
- } else {
- zIndexValue = parseInt(zIndex, 10)
- if (isNaN(zIndexValue)) continue
- }
-
- foundAny = true
-
- // 快速返回:如果找到很大的z-index,很可能就是最大值
- /* if (zIndexValue > 10000) {
- return zIndexValue;
- } */
-
- if (zIndexValue > maxZIndex) {
- maxZIndex = zIndexValue
- }
- }
- return foundAny ? maxZIndex : 0
- } catch (error) {
- console.warn('获取最高z-index时出错,返回默认值0:', error)
- return 0
- }
- }
-
- /**
- * 初始化引导
- * @param {*} root
- */
- const initGuide = (root) => {
- root.insertAdjacentHTML('beforeend', guideHtml)
- const button = root.querySelector('.sqlbot-assistant-button')
- const close_icon = root.querySelector('.sqlbot-assistant-close')
- const close_func = () => {
- root.removeChild(root.querySelector('.sqlbot-assistant-tips'))
- root.removeChild(root.querySelector('.sqlbot-assistant-mask'))
- localStorage.setItem('sqlbot_assistant_mask_tip', true)
- }
- button.onclick = close_func
- close_icon.onclick = close_func
- }
- const initChat = (root, data) => {
- // 添加对话icon
- root.insertAdjacentHTML('beforeend', chatButtonHtml(data))
- // 添加对话框
- root.insertAdjacentHTML('beforeend', getChatContainerHtml(data))
- // 按钮元素
- const chat_button = root.querySelector('.sqlbot-assistant-chat-button')
- let chat_button_img = root.querySelector('.sqlbot-assistant-chat-button > svg')
- if (data.float_icon) {
- chat_button_img = root.querySelector('.sqlbot-assistant-chat-button > img')
- }
- chat_button_img.style.display = 'block'
- function resizeImg() {
- const rate = window.outerWidth / window.innerWidth;
- chat_button_img.style.width = `${30 * (1 / rate)}px`;
- chat_button_img.style.height = `${30 * (1 / rate)}px`;
- }
- resizeImg()
- window.addEventListener('resize', resizeImg);
- // 对话框元素
- const chat_container = root.querySelector('#sqlbot-assistant-chat-container')
- // 引导层
- const mask_content = root.querySelector('.sqlbot-assistant-mask > .sqlbot-assistant-content')
- const mask_tips = root.querySelector('.sqlbot-assistant-tips')
- chat_button_img.onload = (event) => {
- if (mask_content) {
- mask_content.style.width = chat_button_img.width + 'px'
- mask_content.style.height = chat_button_img.height + 'px'
- if (data.x_type == 'left') {
- mask_tips.style.marginLeft =
- (chat_button_img.naturalWidth > 500 ? 500 : chat_button_img.naturalWidth) - 64 + 'px'
- } else {
- mask_tips.style.marginRight =
- (chat_button_img.naturalWidth > 500 ? 500 : chat_button_img.naturalWidth) - 64 + 'px'
- }
- }
- }
-
- const viewport = root.querySelector('.sqlbot-assistant-openviewport')
- const closeviewport = root.querySelector('.sqlbot-assistant-closeviewport')
- const close_func = () => {
- chat_container.style['display'] =
- chat_container.style['display'] == 'block' ? 'none' : 'block'
- chat_button.style['display'] = chat_container.style['display'] == 'block' ? 'none' : 'block'
- }
- close_icon = chat_container.querySelector('.sqlbot-assistant-chat-close')
- chat_button.onclick = close_func
- close_icon.onclick = close_func
- const viewport_func = () => {
- if (chat_container.classList.contains('sqlbot-assistant-enlarge')) {
- chat_container.classList.remove('sqlbot-assistant-enlarge')
- viewport.classList.remove('sqlbot-assistant-viewportnone')
- closeviewport.classList.add('sqlbot-assistant-viewportnone')
- } else {
- chat_container.classList.add('sqlbot-assistant-enlarge')
- viewport.classList.add('sqlbot-assistant-viewportnone')
- closeviewport.classList.remove('sqlbot-assistant-viewportnone')
- }
- }
- if (data.float_icon_drag) {
- chat_button.setAttribute('draggable', 'true')
-
- let startX = 0
- let startY = 0
- const img = new Image()
- img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='
- chat_button.addEventListener('dragstart', (e) => {
- startX = e.clientX - chat_button.offsetLeft
- startY = e.clientY - chat_button.offsetTop
- e.dataTransfer.setDragImage(img, 0, 0)
- })
-
- chat_button.addEventListener('drag', (e) => {
- if (e.clientX && e.clientY) {
- const left = e.clientX - startX
- const top = e.clientY - startY
-
- const maxX = window.innerWidth - chat_button.offsetWidth
- const maxY = window.innerHeight - chat_button.offsetHeight
-
- chat_button.style.left = Math.min(Math.max(0, left), maxX) + 'px'
- chat_button.style.top = Math.min(Math.max(0, top), maxY) + 'px'
- }
- })
-
- let touchStartX = 0
- let touchStartY = 0
-
- chat_button.addEventListener('touchstart', (e) => {
- touchStartX = e.touches[0].clientX - chat_button.offsetLeft
- touchStartY = e.touches[0].clientY - chat_button.offsetTop
- e.preventDefault()
- })
-
- chat_button.addEventListener('touchmove', (e) => {
- const left = e.touches[0].clientX - touchStartX
- const top = e.touches[0].clientY - touchStartY
-
- const maxX = window.innerWidth - chat_button.offsetWidth
- const maxY = window.innerHeight - chat_button.offsetHeight
-
- chat_button.style.left = Math.min(Math.max(0, left), maxX) + 'px'
- chat_button.style.top = Math.min(Math.max(0, top), maxY) + 'px'
-
- e.preventDefault()
- })
- }
- /* const drag = (e) => {
- if (['touchmove', 'touchstart'].includes(e.type)) {
- chat_button.style.top = e.touches[0].clientY - chat_button_img.clientHeight / 2 + 'px'
- chat_button.style.left = e.touches[0].clientX - chat_button_img.clientHeight / 2 + 'px'
- } else {
- chat_button.style.top = e.y - chat_button_img.clientHeight / 2 + 'px'
- chat_button.style.left = e.x - chat_button_img.clientHeight / 2 + 'px'
- }
- chat_button.style.width = chat_button_img.clientHeight + 'px'
- chat_button.style.height = chat_button_img.clientHeight + 'px'
- }
- if (data.float_icon_drag) {
- chat_button.setAttribute('draggable', 'true')
- chat_button.addEventListener('drag', drag)
- chat_button.addEventListener('dragover', (e) => {
- e.preventDefault()
- })
- chat_button.addEventListener('dragend', drag)
- chat_button.addEventListener('touchstart', drag)
- chat_button.addEventListener('touchmove', drag)
- } */
- viewport.onclick = viewport_func
- closeviewport.onclick = viewport_func
- }
- /**
- * 第一次进来的引导提示
- */
- function initsqlbot_assistant(data) {
- const sqlbot_div = document.createElement('div')
- const root = document.createElement('div')
- const sqlbot_root_id = 'sqlbot-assistant-root-' + data.id
- root.id = sqlbot_root_id
- initsqlbot_assistantStyle(sqlbot_div, sqlbot_root_id, data)
- sqlbot_div.appendChild(root)
- document.body.appendChild(sqlbot_div)
- const sqlbot_assistant_mask_tip = localStorage.getItem('sqlbot_assistant_mask_tip')
- if (sqlbot_assistant_mask_tip == null && data.show_guide) {
- initGuide(root)
- }
- initChat(root, data)
- }
-
- // 初始化全局样式
- function initsqlbot_assistantStyle(root, sqlbot_assistantId, data) {
- const maxZIndex = getHighestZIndexValue()
- const zIndex = Math.max((maxZIndex || 0) + 1, 10000)
- const maskZIndex = zIndex + 1
- style = document.createElement('style')
- style.type = 'text/css'
- style.innerText = `
- /* 放大 */
- #sqlbot-assistant .sqlbot-assistant-enlarge {
- width: 50%!important;
- height: 100%!important;
- bottom: 0!important;
- right: 0 !important;
- }
- @media only screen and (max-width: 768px){
- #sqlbot-assistant .sqlbot-assistant-enlarge {
- width: 100%!important;
- height: 100%!important;
- right: 0 !important;
- bottom: 0!important;
- }
- }
-
- /* 引导 */
-
- #sqlbot-assistant .sqlbot-assistant-mask {
- position: fixed;
- z-index: ${maskZIndex};
- background-color: transparent;
- height: 100%;
- width: 100%;
- top: 0;
- left: 0;
- }
- #sqlbot-assistant .sqlbot-assistant-mask .sqlbot-assistant-content {
- width: 64px;
- height: 64px;
- box-shadow: 1px 1px 1px 9999px rgba(0,0,0,.6);
- position: absolute;
- ${data.x_type}: ${data.x_val}px;
- ${data.y_type}: ${data.y_val}px;
- z-index: ${maskZIndex};
- }
- #sqlbot-assistant .sqlbot-assistant-tips {
- position: fixed;
- ${data.x_type}:calc(${data.x_val}px + 75px);
- ${data.y_type}: calc(${data.y_val}px + 0px);
- padding: 22px 24px 24px;
- border-radius: 6px;
- color: #ffffff;
- font-size: 14px;
- background: #3370FF;
- z-index: ${maskZIndex};
- }
- #sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-arrow {
- position: absolute;
- background: #3370FF;
- width: 10px;
- height: 10px;
- pointer-events: none;
- transform: rotate(45deg);
- box-sizing: border-box;
- /* left */
- ${data.x_type}: -5px;
- ${data.y_type}: 33px;
- border-left-color: transparent;
- border-bottom-color: transparent
- }
- #sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-title {
- font-size: 20px;
- font-weight: 500;
- margin-bottom: 8px;
- }
- #sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-button {
- text-align: right;
- margin-top: 24px;
- }
- #sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-button button {
- border-radius: 4px;
- background: #FFF;
- padding: 3px 12px;
- color: #3370FF;
- cursor: pointer;
- outline: none;
- border: none;
- }
- #sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-button button::after{
- border: none;
- }
- #sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-close {
- position: absolute;
- right: 20px;
- top: 20px;
- cursor: pointer;
-
- }
- #sqlbot-assistant-chat-container {
- width: 460px;
- height: 640px;
- display:none;
- }
- @media only screen and (max-width: 768px) {
- #sqlbot-assistant-chat-container {
- width: 100%;
- height: 70%;
- right: 0 !important;
- }
- }
-
- #sqlbot-assistant .sqlbot-assistant-chat-button{
- position: fixed;
- ${data.x_type}: ${data.x_val}px;
- ${data.y_type}: ${data.y_val}px;
- cursor: pointer;
- z-index: ${zIndex};
- }
- #sqlbot-assistant #sqlbot-assistant-chat-container{
- z-index: ${zIndex};
- position: relative;
- border-radius: 8px;
- //border: 1px solid #ffffff;
- background: linear-gradient(188deg, rgba(235, 241, 255, 0.20) 39.6%, rgba(231, 249, 255, 0.20) 94.3%), #EFF0F1;
- box-shadow: 0px 4px 8px 0px rgba(31, 35, 41, 0.10);
- position: fixed;bottom: 16px;right: 16px;overflow: hidden;
- }
-
- .ed-overlay-dialog {
- margin-top: 50px;
- }
- .ed-drawer {
- margin-top: 50px;
- }
-
- #sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-operate{
- top: 18px;
- right: 15px;
- position: absolute;
- display: flex;
- align-items: center;
- line-height: 18px;
- }
- #sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-operate .sqlbot-assistant-chat-close{
- margin-left:15px;
- cursor: pointer;
- }
- #sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-operate .sqlbot-assistant-openviewport{
-
- cursor: pointer;
- }
- #sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-operate .sqlbot-assistant-closeviewport{
-
- cursor: pointer;
- }
- #sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-viewportnone{
- display:none;
- }
- #sqlbot-assistant #sqlbot-assistant-chat-container #sqlbot-assistant-chat-iframe-${data.id} {
- height:100%;
- width:100%;
- border: none;
- }
- #sqlbot-assistant #sqlbot-assistant-chat-container {
- animation: appear .4s ease-in-out;
- }
- @keyframes appear {
- from {
- height: 0;;
- }
-
- to {
- height: 600px;
- }
- }`.replaceAll('#sqlbot-assistant ', `#${sqlbot_assistantId} `)
- root.appendChild(style)
- }
- function getParam(src, key) {
- const url = new URL(src)
- return url.searchParams.get(key)
- }
- function parsrCertificate(config) {
- const certificateList = config.certificate
- if (!certificateList?.length) {
- return null
- }
- const list = certificateList.map((item) => formatCertificate(item)).filter((item) => !!item)
- return JSON.stringify(list)
- }
- function isEmpty(obj) {
- return obj == null || typeof obj == 'undefined'
- }
- function formatCertificate(item) {
- const { type, source, target, target_key, target_val } = item
- let source_val = null
- if (type.toLocaleLowerCase() == 'localstorage') {
- source_val = localStorage.getItem(source)
- }
- if (type.toLocaleLowerCase() == 'sessionstorage') {
- source_val = sessionStorage.getItem(source)
- }
- if (type.toLocaleLowerCase() == 'cookie') {
- source_val = getCookie(source)
- }
- if (type.toLocaleLowerCase() == 'custom') {
- source_val = source
- }
- if (isEmpty(source_val)) {
- return null
- }
- return {
- target,
- key: target_key || source,
- value: (target_val && eval(target_val)) || source_val,
- }
- }
- function getCookie(key) {
- if (!key || !document.cookie) {
- return null
- }
- const cookies = document.cookie.split(';')
- for (let i = 0; i < cookies.length; i++) {
- const cookie = cookies[i].trim()
-
- if (cookie.startsWith(key + '=')) {
- return decodeURIComponent(cookie.substring(key.length + 1))
- }
- }
- return null
- }
- function registerMessageEvent(id, data) {
- const iframe = document.getElementById(`sqlbot-assistant-chat-iframe-${id}`)
- const url = iframe.src
- const eventName = 'sqlbot_assistant_event'
- window.addEventListener('message', (event) => {
- if (event.data?.eventName === eventName) {
- if (event.data?.messageId !== id) {
- return
- }
- if (event.data?.busi == 'ready' && event.data?.ready) {
- params = {
- eventName,
- messageId: id,
- hostOrigin: window.location.origin,
- }
- if (data.type === 1) {
- const certificate = parsrCertificate(data)
- params['busi'] = 'certificate'
- params['certificate'] = certificate
- }
- const contentWindow = iframe.contentWindow
- contentWindow.postMessage(params, url)
- }
- }
- })
- }
- function loadScript(src, id) {
- const domain_url = getDomain(src)
- const online = getParam(src, 'online')
- const userFlag = getParam(src, 'userFlag')
- const history = getParam(src, 'history')
- let url = `${domain_url}/api/v1/system/assistant/info/${id}`
- if (domain_url.includes('5173')) {
- url = url.replace('5173', '8000')
- }
- fetch(url)
- .then((response) => response.json())
- .then((res) => {
- if (!res.data) {
- throw new Error(res)
- }
- const data = res.data
- const config_json = data.configuration
- let tempData = Object.assign(defaultData, data)
- if (tempData.configuration) {
- delete tempData.configuration
- }
- if (config_json) {
- const config = JSON.parse(config_json)
- if (config) {
- delete config.id
- tempData = Object.assign(tempData, config)
- }
- }
- tempData['id'] = id
- tempData['domain_url'] = domain_url
-
- if (tempData['float_icon'] && !tempData['float_icon'].startsWith('http://')) {
- tempData['float_icon'] =
- `${domain_url}/api/v1/system/assistant/picture/${tempData['float_icon']}`
-
- if (domain_url.includes('5173')) {
- tempData['float_icon'] = tempData['float_icon'].replace('5173', '8000')
- }
- }
-
- tempData['online'] = online && online.toString().toLowerCase() == 'true'
- tempData['userFlag'] = userFlag
- tempData['history'] = history
- initsqlbot_assistant(tempData)
- registerMessageEvent(id, tempData)
- })
- .catch((e) => {
- showMsg('嵌入失败', e.message)
- })
- }
- function getDomain(src) {
- return src.substring(0, src.indexOf('/assistant.js'))
- }
- function init() {
- const sqlbotScripts = document.querySelectorAll(`script[id^="${script_id_prefix}"]`)
- const scriptsArray = Array.from(sqlbotScripts)
- const src_list = scriptsArray.map((script) => script.src)
- src_list.forEach((src) => {
- const id = getParam(src, 'id')
- window.sqlbot_assistant_handler[id] = window.sqlbot_assistant_handler[id] || {}
- window.sqlbot_assistant_handler[id]['id'] = id
- const propName = script_id_prefix + id + '-state'
- if (window[propName]) {
- return true
- }
- window[propName] = true
- loadScript(src, id)
- expposeGlobalMethods(id)
- })
- }
-
- function showMsg(title, content) {
- // 检查并创建容器(如果不存在)
- let container = document.getElementById('messageContainer')
- if (!container) {
- container = document.createElement('div')
- container.id = 'messageContainer'
- container.style.position = 'fixed'
- container.style.bottom = '20px'
- container.style.right = '20px'
- container.style.zIndex = '1000'
- document.body.appendChild(container)
- } else {
- // 如果容器已存在,先移除旧弹窗
- const oldMessage = container.querySelector('div')
- if (oldMessage) {
- oldMessage.style.transform = 'translateX(120%)'
- oldMessage.style.opacity = '0'
- setTimeout(() => {
- container.removeChild(oldMessage)
- }, 300)
- }
- }
-
- // 创建弹窗元素
- const messageBox = document.createElement('div')
- messageBox.style.width = '240px'
- messageBox.style.minHeight = '100px'
- messageBox.style.background = 'linear-gradient(135deg, #ff6b6b, #ff8e8e)'
- messageBox.style.borderRadius = '8px'
- messageBox.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)'
- messageBox.style.padding = '15px'
- messageBox.style.color = 'white'
- messageBox.style.fontFamily = 'Arial, sans-serif'
- messageBox.style.display = 'flex'
- messageBox.style.flexDirection = 'column'
- messageBox.style.transform = 'translateX(120%)'
- messageBox.style.transition = 'transform 0.3s ease-out'
- messageBox.style.opacity = '0'
- messageBox.style.transition = 'opacity 0.3s ease, transform 0.3s ease'
- messageBox.style.overflow = 'hidden'
-
- // 创建标题元素
- const titleElement = document.createElement('div')
- titleElement.style.fontSize = '18px'
- titleElement.style.fontWeight = 'bold'
- titleElement.style.marginBottom = '10px'
- titleElement.style.borderBottom = '1px solid rgba(255, 255, 255, 0.3)'
- titleElement.style.paddingBottom = '8px'
- titleElement.textContent = title
-
- // 创建内容元素
- const contentElement = document.createElement('div')
- contentElement.style.fontSize = '14px'
- contentElement.style.flexGrow = '1'
- contentElement.style.overflow = 'auto'
- contentElement.textContent = content
-
- // 组装元素
- messageBox.appendChild(titleElement)
- messageBox.appendChild(contentElement)
-
- // 添加到容器
- container.appendChild(messageBox)
-
- // 触发显示动画
- setTimeout(() => {
- messageBox.style.transform = 'translateX(0)'
- messageBox.style.opacity = '1'
- }, 10)
-
- // 3秒后自动隐藏
- setTimeout(() => {
- messageBox.style.transform = 'translateX(120%)'
- messageBox.style.opacity = '0'
- setTimeout(() => {
- container.removeChild(messageBox)
- // 如果容器是空的,也移除容器
- if (container.children.length === 0) {
- document.body.removeChild(container)
- }
- }, 300)
- }, 5000)
- }
-
- /* function hideMsg() {
- const container = document.getElementById('messageContainer');
- if (container) {
- const messageBox = container.querySelector('div');
- if (messageBox) {
- messageBox.style.transform = 'translateX(120%)';
- messageBox.style.opacity = '0';
- setTimeout(() => {
- container.removeChild(messageBox);
- // 如果容器是空的,也移除容器
- if (container.children.length === 0) {
- document.body.removeChild(container);
- }
- }, 300);
- }
- }
- } */
-
- function updateParam(target_url, key, newValue) {
- try {
- const url = new URL(target_url)
- const [hashPath, hashQuery] = url.hash.split('?')
- let searchParams
- if (hashQuery) {
- searchParams = new URLSearchParams(hashQuery)
- } else {
- searchParams = url.searchParams
- }
- searchParams.set(key, newValue)
- if (hashQuery) {
- url.hash = `${hashPath}?${searchParams.toString()}`
- } else {
- url.search = searchParams.toString()
- }
- return url.toString()
- } catch (e) {
- console.error('Invalid URL:', target_url)
- return target_url
- }
- }
- function expposeGlobalMethods(id) {
- window.sqlbot_assistant_handler[id]['setOnline'] = (online) => {
- if (online != null && typeof online != 'boolean') {
- throw new Error('The parameter can only be of type boolean')
- }
- const iframe = document.getElementById(`sqlbot-assistant-chat-iframe-${id}`)
- if (iframe) {
- const url = iframe.src
- const eventName = 'sqlbot_assistant_event'
- const params = {
- busi: 'setOnline',
- online,
- eventName,
- messageId: id,
- }
- const contentWindow = iframe.contentWindow
- contentWindow.postMessage(params, url)
- }
- }
- window.sqlbot_assistant_handler[id]['refresh'] = (online, userFlag) => {
- if (online != null && typeof online != 'boolean') {
- throw new Error('The parameter can only be of type boolean')
- }
- const iframe = document.getElementById(`sqlbot-assistant-chat-iframe-${id}`)
- if (iframe) {
- const url = iframe.src
- let new_url = updateParam(url, 't', Date.now())
- if (online != null) {
- new_url = updateParam(new_url, 'online', online)
- }
- if (userFlag != null) {
- new_url = updateParam(new_url, 'userFlag', userFlag)
- }
- iframe.src = 'about:blank'
- setTimeout(() => {
- iframe.src = new_url
- }, 500)
- }
- }
- window.sqlbot_assistant_handler[id]['destroy'] = () => {
- const sqlbot_root_id = 'sqlbot-assistant-root-' + id
- const container_div = document.getElementById(sqlbot_root_id)
- if (container_div) {
- const root_div = container_div.parentNode
- if (root_div?.parentNode) {
- root_div.parentNode.removeChild(root_div)
- }
- }
-
- const scriptDom = document.getElementById(`sqlbot-assistant-float-script-${id}`)
- if (scriptDom) {
- scriptDom.parentNode.removeChild(scriptDom)
- }
- const propName = script_id_prefix + id + '-state'
- if (window[propName]) {
- delete window[propName]
- }
- delete window.sqlbot_assistant_handler[id]
- }
- window.sqlbot_assistant_handler[id]['setHistory'] = (show) => {
- if (show != null && typeof show != 'boolean') {
- throw new Error('The parameter can only be of type boolean')
- }
- const iframe = document.getElementById(`sqlbot-assistant-chat-iframe-${id}`)
- if (iframe) {
- const url = iframe.src
- const eventName = 'sqlbot_assistant_event'
- const params = {
- busi: 'setHistory',
- show,
- eventName,
- messageId: id,
- }
- const contentWindow = iframe.contentWindow
- contentWindow.postMessage(params, url)
- }
- }
- window.sqlbot_assistant_handler[id]['createConversation'] = (param) => {
- const iframe = document.getElementById(`sqlbot-assistant-chat-iframe-${id}`)
- if (iframe) {
- const url = iframe.src
- const eventName = 'sqlbot_assistant_event'
- const params = {
- busi: 'createConversation',
- param,
- eventName,
- messageId: id,
- }
- const contentWindow = iframe.contentWindow
- contentWindow.postMessage(params, url)
- }
- }
- }
- // window.addEventListener('load', init)
- const executeWhenReady = (fn) => {
- if (
- document.readyState === 'complete' ||
- (document.readyState !== 'loading' && !document.documentElement.doScroll)
- ) {
- setTimeout(fn, 0)
- } else {
- const onReady = () => {
- document.removeEventListener('DOMContentLoaded', onReady)
- window.removeEventListener('load', onReady)
- fn()
- }
- document.addEventListener('DOMContentLoaded', onReady)
- window.addEventListener('load', onReady)
- }
- }
-
- executeWhenReady(init)
-})()
diff --git a/frontend/src/api/assistant.ts b/frontend/src/api/assistant.ts
index bb955e09f..b883976f0 100644
--- a/frontend/src/api/assistant.ts
+++ b/frontend/src/api/assistant.ts
@@ -6,6 +6,6 @@ export const assistantApi = {
add: (data: any) => request.post('/system/assistant', data),
edit: (data: any) => request.put('/system/assistant', data),
delete: (id: number) => request.delete(`/system/assistant/${id}`),
- query: (id: number) => request.get(`/system/assistant/${id}`),
+ // query: (id: number) => request.get(`/system/assistant/${id}`),
validate: (data: any) => request.get('/system/assistant/validator', { params: data }),
}
diff --git a/frontend/src/api/chat.ts b/frontend/src/api/chat.ts
index 2a5870632..4a52187ee 100644
--- a/frontend/src/api/chat.ts
+++ b/frontend/src/api/chat.ts
@@ -474,7 +474,7 @@ export const chatApi = {
return request.post('/chat/rename', { id: chat_id, brief: brief })
},
deleteChat: (id: number | undefined, brief: any): Promise
=> {
- return request.delete(`/chat/${id}/${brief}`)
+ return request.delete(`/chat/${id}`, { data: { id: id, brief: brief } })
},
analysis: (record_id: number | undefined, controller?: AbortController) => {
return request.fetchStream(`/chat/record/${record_id}/analysis`, {}, controller)
diff --git a/frontend/src/api/embedded.ts b/frontend/src/api/embedded.ts
index 0733088ae..2e51008ae 100644
--- a/frontend/src/api/embedded.ts
+++ b/frontend/src/api/embedded.ts
@@ -5,7 +5,7 @@ export const getAdvancedApplicationList = () =>
request.get('/system/assistant/advanced_application')
export const updateAssistant = (data: any) => request.put('/system/assistant', data)
export const saveAssistant = (data: any) => request.post('/system/assistant', data)
-export const getOne = (id: any) => request.get(`/system/assistant/${id}`)
+// export const getOne = (id: any) => request.get(`/system/assistant/${id}`)
export const delOne = (id: any) => request.delete(`/system/assistant/${id}`)
export const dsApi = (id: any) => request.get(`/datasource/ws/${id}`)
diff --git a/frontend/src/api/system.ts b/frontend/src/api/system.ts
index f9ed3ec10..4d56fecb1 100644
--- a/frontend/src/api/system.ts
+++ b/frontend/src/api/system.ts
@@ -27,6 +27,8 @@ export const modelApi = {
query: (id: number) => request.get(`/system/aimodel/${id}`),
setDefault: (id: number) => request.put(`/system/aimodel/default/${id}`),
check: (data: any) => request.fetchStream('/system/aimodel/status', data),
- platform: (id: number) => request.get(`/system/platform/org/${id}`),
+ platform: (id: number, lazy?: number, pid?: string) =>
+ request.post(`/system/platform/org/${id}`, { lazy, pid }),
userSync: (data: any) => request.post(`/system/platform/user/sync`, data),
+ list_by_ws: () => request.get(`/system/aimodel/list/by_ws`),
}
diff --git a/frontend/src/api/workspace.ts b/frontend/src/api/workspace.ts
index 5298045b5..46637678c 100644
--- a/frontend/src/api/workspace.ts
+++ b/frontend/src/api/workspace.ts
@@ -15,3 +15,12 @@ export const workspaceDelete = (id: any) => request.delete(`/system/workspace/${
export const workspaceList = () => request.get('/system/workspace')
export const workspaceDetail = (id: any) => request.get(`/system/workspace/${id}`)
export const uwsOption = (params: any) => request.get('system/workspace/uws/option', { params })
+
+export const workspaceModelMapping = (aiModelId: any) =>
+ request.get(`/system/aimodel/${aiModelId}/ws_mapping`)
+export const workspaceModelMappingUpdate = (aiModelId: any, data: any) =>
+ request.put(`/system/aimodel/${aiModelId}/ws_mapping`, data)
+export const workspaceModelMappingAdd = (aiModelId: any, data: any) =>
+ request.post(`/system/aimodel/${aiModelId}/ws_mapping`, data)
+export const workspaceModelMappingDelete = (aiModelId: any, data: any) =>
+ request.delete(`/system/aimodel/${aiModelId}/ws_mapping`, { data })
diff --git a/frontend/src/assets/svg/chart/icon-thousand-separator.svg b/frontend/src/assets/svg/chart/icon-thousand-separator.svg
new file mode 100644
index 000000000..670e86901
--- /dev/null
+++ b/frontend/src/assets/svg/chart/icon-thousand-separator.svg
@@ -0,0 +1,6 @@
+
diff --git a/frontend/src/assets/svg/icon_block_outlined.svg b/frontend/src/assets/svg/icon_block_outlined.svg
new file mode 100644
index 000000000..ffefda2c0
--- /dev/null
+++ b/frontend/src/assets/svg/icon_block_outlined.svg
@@ -0,0 +1,11 @@
+
diff --git a/frontend/src/assets/svg/icon_describe_outlined.svg b/frontend/src/assets/svg/icon_describe_outlined.svg
new file mode 100644
index 000000000..7dc0951b4
--- /dev/null
+++ b/frontend/src/assets/svg/icon_describe_outlined.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/src/assets/svg/workspace-white.svg b/frontend/src/assets/svg/workspace-white.svg
new file mode 100644
index 000000000..7e9cac0a5
--- /dev/null
+++ b/frontend/src/assets/svg/workspace-white.svg
@@ -0,0 +1,5 @@
+
diff --git a/frontend/src/components/drawer-filter/src/DrawerEnumFilter.vue b/frontend/src/components/drawer-filter/src/DrawerEnumFilter.vue
index a7cae5c5d..262b5c710 100644
--- a/frontend/src/components/drawer-filter/src/DrawerEnumFilter.vue
+++ b/frontend/src/components/drawer-filter/src/DrawerEnumFilter.vue
@@ -84,7 +84,7 @@ useEmitt({
padding: 1px 6px;
background: var(--deTextPrimary5, #f5f6f7);
color: var(--deTextPrimary, #1f2329);
- border-radius: 4px;
+ border-radius: 6px;
cursor: pointer;
display: inline-block;
margin-bottom: 12px;
diff --git a/frontend/src/components/filter-text/src/FilterText.vue b/frontend/src/components/filter-text/src/FilterText.vue
index 4eedaa269..d423543d4 100644
--- a/frontend/src/components/filter-text/src/FilterText.vue
+++ b/frontend/src/components/filter-text/src/FilterText.vue
@@ -181,7 +181,7 @@ watch(
.arrow-filter:hover {
background: rgba(31, 35, 41, 0.1);
- border-radius: 4px;
+ border-radius: 6px;
}
.ed-icon-arrow-right.arrow-filter {
diff --git a/frontend/src/components/layout/Person.vue b/frontend/src/components/layout/Person.vue
index ae0448e26..a58a02afb 100644
--- a/frontend/src/components/layout/Person.vue
+++ b/frontend/src/components/layout/Person.vue
@@ -345,7 +345,7 @@ const logout = async () => {
position: relative;
cursor: pointer;
margin: 0 4px;
- border-radius: 4px;
+ border-radius: 6px;
&:hover {
background-color: #1f23291a;
}
@@ -382,7 +382,7 @@ const logout = async () => {
padding-right: 8px;
margin-bottom: 2px;
position: relative;
- border-radius: 4px;
+ border-radius: 6px;
cursor: pointer;
&:not(.empty):hover {
background: #1f23291a;
diff --git a/frontend/src/components/layout/Workspace.vue b/frontend/src/components/layout/Workspace.vue
index 1f76e92ad..456c083cd 100644
--- a/frontend/src/components/layout/Workspace.vue
+++ b/frontend/src/components/layout/Workspace.vue
@@ -198,7 +198,7 @@ onMounted(async () => {
padding-right: 8px;
margin-bottom: 2px;
position: relative;
- border-radius: 4px;
+ border-radius: 6px;
cursor: pointer;
&:not(.empty):hover {
background: #1f23291a;
diff --git a/frontend/src/components/layout/index.vue b/frontend/src/components/layout/index.vue
index f83ef983a..4a0097e41 100644
--- a/frontend/src/components/layout/index.vue
+++ b/frontend/src/components/layout/index.vue
@@ -362,7 +362,7 @@ onMounted(() => {
column-gap: 12px;
align-items: center;
padding: 8px 16px;
- border-radius: 4px;
+ border-radius: 6px;
cursor: pointer;
border: none;
font-weight: 500;
@@ -493,7 +493,7 @@ onMounted(() => {
column-gap: 12px;
align-items: center;
padding: 8px 16px;
- border-radius: 4px;
+ border-radius: 6px;
cursor: pointer;
border: none;
font-weight: 500;
diff --git a/frontend/src/entity/supplier.ts b/frontend/src/entity/supplier.ts
index cd672f9d8..bd4ddc971 100644
--- a/frontend/src/entity/supplier.ts
+++ b/frontend/src/entity/supplier.ts
@@ -276,7 +276,7 @@ export const supplierList: Array<{
{ name: 'doubao-1-5-pro-32k-character-250715' },
{ name: 'kimi-k2-250711' },
{ name: 'deepseek-v3-250324' },
- { name: 'deepseek-r1' },
+ { name: 'deepseek-v4-pro-260425' },
],
},
},
@@ -290,11 +290,7 @@ export const supplierList: Array<{
0: {
api_domain: 'https://api.minimax.io/v1',
common_args: [{ key: 'temperature', val: 0.7, type: 'number', range: '[0, 1]' }],
- model_options: [
- { name: 'MiniMax-M2.7' },
- { name: 'MiniMax-M2.5' },
- { name: 'MiniMax-M2.5-highspeed' },
- ],
+ model_options: [{ name: 'MiniMax-M3' }, { name: 'MiniMax-M2.7' }],
},
},
},
diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json
index f8a420250..4cdef7da8 100644
--- a/frontend/src/i18n/en.json
+++ b/frontend/src/i18n/en.json
@@ -32,12 +32,24 @@
"enter_variable_name": "Please Enter Variable Name",
"enter_variable_value": "Please Enter Variable Value"
},
+ "authorized_space": {
+ "authorized_space": "Authorized Space",
+ "authorized_space_list": "Authorized Space List",
+ "select_space": "Select Space",
+ "modify_authorized_space": "Modify Authorized Space",
+ "workspaces_authorized": "Authorized {num} Workspaces",
+ "number_of_members": "Number of Members",
+ "delete_selected_workspaces": "Are you sure you want to delete the selected {msg} workspaces?",
+ "delete_workspace": "Are you sure you want to delete the workspace: {msg}?",
+ "no_workspace": "No Workspaces"
+ },
"sync": {
"records": "Displaying {num} records out of {total}",
"confirm_upload": "Confirm Upload",
"field_details": "Field Details",
"integration": "Platform integration needs to be enabled.",
"the_existing_user": "If the user already exists, overwrite the existing user.",
+ "lazy_load": "Lazy Load",
"sync_users": "Sync Users",
"sync_wechat_users": "Sync WeChat Users",
"sync_dingtalk_users": "Sync DingTalk Users",
@@ -64,6 +76,7 @@
"context_record_count": "Context Record Count",
"context_record_count_hint": "Number of user question rounds",
"model_thinking_process": "Expand Model Thinking Process",
+ "hide_model_thinking_process": "Hide Model Thinking Process",
"rows_of_data": "Limit 1000 Rows of Data",
"third_party_platform_settings": "Authentication Settings",
"by_third_party_platform": "Automatic User Creation",
@@ -71,8 +84,8 @@
"platform_user_roles": "Third-Party Platform User Roles",
"excessive_data_volume": "Disabling the 1000-row data limit may cause system lag due to excessive data volume.",
"sqlbot_name": "Data Query Assistant Name",
- "hide_sql": "Hide Show SQL Button",
- "hide_log": "Hide Execution Log",
+ "show_sql": "Allow Viewing SQL Statements",
+ "show_log": "Show Execution Log",
"prompt": "Prompt",
"disabling_successfully": "Disabling Successfully",
"closed_by_default": "In the Question Count window, control whether the model thinking process is expanded or closed by default.",
@@ -178,6 +191,7 @@
"system_manage": "System Management",
"update_success": "Update",
"save_success": "Save Successful",
+ "operation_success": "Operation successful",
"next": "Next",
"save": "Save",
"logout": "Logout",
@@ -399,7 +413,8 @@
"address": "Address",
"low_version": "Compatible with lower versions",
"ssl": "Enable SSL",
- "file_path": "File Path"
+ "file_path": "File Path",
+ "pool_size": "Connection Pool Size"
},
"sync_fields": "Sync Fields",
"sync_fields_success": "Sync fields successfully",
@@ -571,6 +586,7 @@
"member_feng_yibudao": "Do you want to remove the member: {msg}?",
"select_member": "Select member",
"selected_2_people": "Selected: {msg} people",
+ "selected_number": "Selected: {msg} items",
"clear": "Clear",
"historical_dialogue": "No historical dialogue",
"rename_a_workspace": "Rename a workspace",
@@ -672,6 +688,9 @@
"application_description": "Application description",
"cross_domain_settings": "Cross-domain settings",
"enableCustomModel": "Use specified model",
+ "useModel": "Use model",
+ "defaultModel": "Default model",
+ "customModel": "Specified model",
"third_party_address": "Please enter the embedded third party address,multiple items separated by semicolons",
"set_to_private": "Set as private",
"set_to_public": "Set as public",
@@ -722,7 +741,7 @@
"display_settings": "Display Settings",
"header_text_color": "Header Text Color",
"app_logo": "App Logo",
- "maximum_size_10mb": "Recommended size: 32 x 32, supports JPG, PNG, and SVG, maximum size: 10MB",
+ "maximum_size_10mb": "Recommended size: 32 x 32, supports JPG, PNG, maximum size: 10MB",
"replace": "Replace",
"default_icon_position": "Default Icon Position",
"draggable_position": "Draggable Position",
@@ -771,6 +790,8 @@
"no_data": "No Data",
"loading_data": "Loading ...",
"show_error_detail": "Show error info",
+ "thousands_separator_setting": "Thousands Separator Setting",
+ "thousands_separator_display": "Apply Thousands Separator Display",
"log": {
"GENERATE_SQL": "Generate SQL",
"GENERATE_CHART": "Generate Chart Structure",
@@ -835,11 +856,11 @@
"website_logo": "Website Logo",
"tab": "Tab",
"replace_image": "Replace Image",
- "larger_than_200kb": "Logo displayed at the top of the website: Recommended size: 48 x 48 pixels, supports JPG, PNG, and SVG, and no larger than 200KB",
+ "larger_than_200kb": "Logo displayed at the top of the website: Recommended size: 48 x 48 pixels, supports JPG, PNG, and no larger than 200KB",
"login_logo": "System Logo",
- "larger_than_200kb_de": "Logo on the right side of the login page: Recommended size: 204 x 52 pixels, supports JPG, PNG, and SVG, and no larger than 200KB",
+ "larger_than_200kb_de": "Logo on the right side of the login page: Recommended size: 204 x 52 pixels, supports JPG, PNG, and no larger than 200KB",
"login_background_image": "Login Background Image",
- "larger_than_5mb": "Background image on the left: Recommended size: 576 x 900 for vector images, 1152 x 1800 for bitmap images, supports JPG, PNG, and SVG, and no larger than 5MB",
+ "larger_than_5mb": "Background image on the left: Recommended size: 576 x 900 for vector images, 1152 x 1800 for bitmap images, supports JPG, PNG, and no larger than 5MB",
"website_name": "Website Name",
"on_webpage_tabs": "Platform name displayed on webpage tabs",
"welcome_message": "Display a welcome message",
diff --git a/frontend/src/i18n/index.ts b/frontend/src/i18n/index.ts
index 3b8078316..c06dfcd98 100644
--- a/frontend/src/i18n/index.ts
+++ b/frontend/src/i18n/index.ts
@@ -12,7 +12,31 @@ import { getBrowserLocale } from '@/utils/utils'
const elementKoLocale = elementEnLocale
const { wsCache } = useCache()
+const isEmbeddedRoute = () => {
+ const hash = window.location.hash
+ if (!hash) return false
+ const hashPath = hash.substring(1).split('?')[0]
+ return ['/assistant', '/embeddedPage', '/embeddedCommon'].includes(hashPath)
+}
+
+const getUrlLang = () => {
+ try {
+ const hash = window.location.hash
+ if (!hash) return null
+ const hashQuery = hash.substring(1).split('?')[1]
+ if (!hashQuery) return null
+ return new URLSearchParams(hashQuery).get('lang')
+ } catch {
+ return null
+ }
+}
+
const getDefaultLocale = () => {
+ // 嵌入式页面的 URL lang 参数(第三种国际化渠道),优先级最高
+ const urlLang = getUrlLang()
+ if (urlLang && isEmbeddedRoute()) {
+ return urlLang
+ }
return wsCache.get('user.language') || getBrowserLocale() || 'zh-CN'
}
diff --git a/frontend/src/i18n/ko-KR.json b/frontend/src/i18n/ko-KR.json
index 8c988192e..100efe262 100644
--- a/frontend/src/i18n/ko-KR.json
+++ b/frontend/src/i18n/ko-KR.json
@@ -32,12 +32,24 @@
"enter_variable_name": "변수 이름을 입력하세요",
"enter_variable_value": "변수 값을 입력하세요"
},
+ "authorized_space": {
+ "authorized_space": "권한 있는 공간",
+ "authorized_space_list": "권한 있는 공간 목록",
+ "select_space": "공간 선택",
+ "modify_authorized_space": "권한 있는 공간 수정",
+ "workspaces_authorized": "{num}개의 권한 있는 작업 공간",
+ "number_of_members": "회원 수",
+ "delete_selected_workspaces": "선택한 {msg}개의 작업 공간을 삭제하시겠습니까?",
+ "delete_workspace": "작업 공간을 삭제하시겠습니까: {msg}?",
+ "no_workspace": "작업 공간 없음"
+ },
"sync": {
"records": "{total}개 중 {num}개의 레코드 표시",
"confirm_upload": "업로드 확인",
"field_details": "필드 세부 정보",
"integration": "플랫폼 통합을 활성화해야 합니다.",
"the_existing_user": "해당 사용자가 이미 존재하는 경우 기존 사용자를 덮어씁니다.",
+ "lazy_load": "지연 로딩",
"sync_users": "사용자 동기화",
"sync_wechat_users": "위챗 사용자 동기화",
"sync_dingtalk_users": "딩톡 사용자 동기화",
@@ -64,6 +76,7 @@
"context_record_count": "컨텍스트 기록 수",
"context_record_count_hint": "사용자 질문 라운드 수",
"model_thinking_process": "모델 사고 프로세스 확장",
+ "hide_model_thinking_process": "모델 사고 과정 숨기기",
"rows_of_data": "데이터 1,000행 제한",
"third_party_platform_settings": "로그인 인증 설정",
"by_third_party_platform": "자동 사용자 생성",
@@ -71,8 +84,8 @@
"platform_user_roles": "타사 플랫폼 사용자 역할",
"excessive_data_volume": "1,000행 데이터 제한을 비활성화하면 과도한 데이터 양으로 인해 시스템 지연이 발생할 수 있습니다.",
"sqlbot_name": "데이터 질의 도우미 이름",
- "hide_sql": "SQL 표시 버튼 숨기기",
- "hide_log": "실행 로그 숨기기",
+ "show_sql": "SQL 문 보기 허용",
+ "show_log": "실행 로그 표시",
"prompt": "프롬프트",
"disabling_successfully": "비활성화 완료",
"closed_by_default": "질문 수 창에서 모델 사고 프로세스를 기본적으로 확장할지 또는 닫을지 여부를 제어합니다.",
@@ -178,6 +191,7 @@
"system_manage": "시스템 관리",
"update_success": "업데이트 성공",
"save_success": "저장 성공",
+ "operation_success": "작업 성공",
"next": "다음 단계",
"save": "저장",
"logout": "로그아웃",
@@ -399,7 +413,8 @@
"address": "주소",
"low_version": "낮은 버전 호환",
"ssl": "SSL 활성화",
- "file_path": "파일 경로"
+ "file_path": "파일 경로",
+ "pool_size": "연결 풀 크기"
},
"sync_fields": "동기화된 테이블 구조",
"sync_fields_success": "테이블 구조 동기화 성공",
@@ -571,6 +586,7 @@
"member_feng_yibudao": "멤버를 제거하시겠습니까: {msg}?",
"select_member": "멤버 선택",
"selected_2_people": "선택됨: {msg}명",
+ "selected_number": "선택됨: {msg}개",
"clear": "지우기",
"historical_dialogue": "과거 대화가 없습니다",
"rename_a_workspace": "작업 공간 이름 바꾸기",
@@ -672,6 +688,9 @@
"application_description": "애플리케이션 설명",
"cross_domain_settings": "교차 도메인 설정",
"enableCustomModel": "지정된 모델 사용",
+ "useModel": "사용 모델",
+ "defaultModel": "기본 모델",
+ "customModel": "지정 모델",
"third_party_address": "임베디드할 제3자 주소를 입력하십시오, 여러 항목을 세미콜론으로 구분",
"set_to_private": "비공개로 설정",
"set_to_public": "공개로 설정",
@@ -722,7 +741,7 @@
"display_settings": "표시 설정",
"header_text_color": "헤더 텍스트 색상",
"app_logo": "애플리케이션 로고",
- "maximum_size_10mb": "권장 크기 32 x 32, JPG, PNG, SVG 지원, 크기 10MB 이하",
+ "maximum_size_10mb": "권장 크기 32 x 32, JPG, PNG 지원, 크기 10MB 이하",
"replace": "교체",
"default_icon_position": "아이콘 기본 위치",
"draggable_position": "드래그 가능한 위치",
@@ -771,6 +790,8 @@
"no_data": "데이터가 없습니다",
"loading_data": "로딩 중 ...",
"show_error_detail": "구체적인 정보 보기",
+ "thousands_separator_setting": "천 단위 구분 기호 설정",
+ "thousands_separator_display": "천 단위 구분 기호 표시 적용",
"log": {
"GENERATE_SQL": "SQL 생성",
"GENERATE_CHART": "차트 구조 생성",
@@ -835,11 +856,11 @@
"website_logo": "웹사이트 로고",
"tab": "페이지 탭",
"replace_image": "이미지 교체",
- "larger_than_200kb": "상단 웹사이트에 표시되는 로고, 권장 크기 48 x 48, JPG, PNG, SVG 지원, 크기 200KB 이하",
+ "larger_than_200kb": "상단 웹사이트에 표시되는 로고, 권장 크기 48 x 48, JPG, PNG 지원, 크기 200KB 이하",
"login_logo": "시스템 로고",
- "larger_than_200kb_de": "로그인 페이지 오른쪽 로고, 권장 크기 204*52, JPG, PNG, SVG 지원, 크기 200KB 이하",
+ "larger_than_200kb_de": "로그인 페이지 오른쪽 로고, 권장 크기 204*52, JPG, PNG 지원, 크기 200KB 이하",
"login_background_image": "로그인 배경 이미지",
- "larger_than_5mb": "왼쪽 배경 이미지, 벡터 이미지 권장 크기 576*900, 비트맵 권장 크기 1152*1800; JPG, PNG, SVG 지원, 크기 5MB 이하",
+ "larger_than_5mb": "왼쪽 배경 이미지, 벡터 이미지 권장 크기 576*900, 비트맵 권장 크기 1152*1800; JPG, PNG 지원, 크기 5MB 이하",
"website_name": "웹사이트 이름",
"on_webpage_tabs": "웹페이지 탭에 표시되는 플랫폼 이름",
"welcome_message": "환영 메시지 표시",
diff --git a/frontend/src/i18n/zh-CN.json b/frontend/src/i18n/zh-CN.json
index abbdd63c0..9f5cc9b24 100644
--- a/frontend/src/i18n/zh-CN.json
+++ b/frontend/src/i18n/zh-CN.json
@@ -32,12 +32,24 @@
"enter_variable_name": "请输入变量名称",
"enter_variable_value": "请输入变量值"
},
+ "authorized_space": {
+ "authorized_space": "授权空间",
+ "authorized_space_list": "授权空间列表",
+ "select_space": "选择空间",
+ "modify_authorized_space": "修改授权空间",
+ "workspaces_authorized": "已授权 {num} 个工作空间",
+ "number_of_members": "成员数量",
+ "delete_selected_workspaces": "是否移除选中的 {msg} 个工作空间?",
+ "delete_workspace": "是否移除工作空间:{msg}?",
+ "no_workspace": "暂无工作空间"
+ },
"sync": {
"records": "显示 {num} 条数据,共 {total} 条",
"confirm_upload": "确定上传",
"field_details": "字段详情",
"integration": "需开启平台对接",
"the_existing_user": "若用户已存在,覆盖旧用户",
+ "lazy_load": "懒加载",
"sync_users": "同步用户",
"sync_wechat_users": "同步企业微信用户",
"sync_dingtalk_users": "同步钉钉用户",
@@ -64,6 +76,7 @@
"context_record_count": "上下文记录数",
"context_record_count_hint": "用户提问轮数",
"model_thinking_process": "展开模型思考过程",
+ "hide_model_thinking_process": "隐藏模型思考过程",
"rows_of_data": "限制 1000 行数据",
"third_party_platform_settings": "登录认证设置",
"by_third_party_platform": "自动创建用户",
@@ -71,8 +84,8 @@
"platform_user_roles": "第三方平台用户角色",
"excessive_data_volume": "关闭1000行的数据限制后,数据量过大,可能会造成系统卡顿",
"sqlbot_name": "问数小助手名称",
- "hide_sql": "隐藏展示SQL按钮",
- "hide_log": "隐藏执行日志",
+ "show_sql": "允许查看SQL语句",
+ "show_log": "显示执行日志",
"prompt": "提示",
"disabling_successfully": "关闭成功",
"closed_by_default": "在问数窗口中,控制模型思考过程默认展开或者关闭",
@@ -178,6 +191,7 @@
"system_manage": "系统管理",
"update_success": "更新成功",
"save_success": "保存成功",
+ "operation_success": "操作成功",
"next": "下一步",
"save": "保存",
"logout": "退出登录",
@@ -399,7 +413,8 @@
"address": "地址",
"low_version": "兼容低版本",
"ssl": "启用 SSL",
- "file_path": "文件路径"
+ "file_path": "文件路径",
+ "pool_size": "连接池大小"
},
"sync_fields": "同步表结构",
"sync_fields_success": "同步表结构成功",
@@ -571,6 +586,7 @@
"member_feng_yibudao": "是否移除成员:{msg}?",
"select_member": "选择成员",
"selected_2_people": "已选:{msg} 人",
+ "selected_number": "已选:{msg} 个",
"clear": "清空",
"historical_dialogue": "暂无历史对话",
"rename_a_workspace": "重命名工作空间",
@@ -672,6 +688,9 @@
"application_description": "应用描述",
"cross_domain_settings": "跨域设置",
"enableCustomModel": "使用指定大模型",
+ "useModel": "使用模型",
+ "defaultModel": "默认模型",
+ "customModel": "指定模型",
"third_party_address": "请输入嵌入的第三方地址,多个以分号分割",
"set_to_private": "设为私有",
"set_to_public": "设为公共",
@@ -722,7 +741,7 @@
"display_settings": "显示设置",
"header_text_color": "头部文本颜色",
"app_logo": "应用 Logo",
- "maximum_size_10mb": "建议尺寸 32 x 32,支持 JPG、PNG、SVG,大小不超过 10MB",
+ "maximum_size_10mb": "建议尺寸 32 x 32,支持 JPG、PNG,大小不超过 10MB",
"replace": "替换",
"default_icon_position": "图标默认位置",
"draggable_position": "可拖拽位置",
@@ -771,6 +790,8 @@
"no_data": "暂无数据",
"loading_data": "加载中...",
"show_error_detail": "查看具体信息",
+ "thousands_separator_setting": "千分位符设置",
+ "thousands_separator_display": "应用千分位符展示",
"log": {
"GENERATE_SQL": "生成 SQL",
"GENERATE_CHART": "生成图表结构",
@@ -835,11 +856,11 @@
"website_logo": "网站 Logo",
"tab": "页签",
"replace_image": "替换图片",
- "larger_than_200kb": "顶部网站显示的 Logo,建议尺寸 48 x 48,支持 JPG、PNG、SVG,大小不超过 200KB",
+ "larger_than_200kb": "顶部网站显示的 Logo,建议尺寸 48 x 48,支持 JPG、PNG,大小不超过 200KB",
"login_logo": "系统 Logo",
- "larger_than_200kb_de": "登录页面右侧 Logo,建议尺寸 204*52,支持 JPG、PNG、SVG,大小不超过 200KB",
+ "larger_than_200kb_de": "登录页面右侧 Logo,建议尺寸 204*52,支持 JPG、PNG,大小不超过 200KB",
"login_background_image": "登录背景图",
- "larger_than_5mb": "左侧背景图,矢量图建议尺寸 576*900,位图建议尺寸 1152*1800;支持 JPG、PNG、SVG,大小不超过 5M",
+ "larger_than_5mb": "左侧背景图,矢量图建议尺寸 576*900,位图建议尺寸 1152*1800;支持 JPG、PNG,大小不超过 5M",
"website_name": "网站名称",
"on_webpage_tabs": "显示在网页 Tab 的平台名称",
"welcome_message": "显示欢迎语",
diff --git a/frontend/src/i18n/zh-TW.json b/frontend/src/i18n/zh-TW.json
index 94668749f..b64649f9a 100644
--- a/frontend/src/i18n/zh-TW.json
+++ b/frontend/src/i18n/zh-TW.json
@@ -32,12 +32,24 @@
"enter_variable_name": "請輸入變數名稱",
"enter_variable_value": "請輸入變數值"
},
+ "authorized_space": {
+ "authorized_space": "授權空間",
+ "authorized_space_list": "授權空間列表",
+ "select_space": "選擇空間",
+ "modify_authorized_space": "修改授權空間",
+ "workspaces_authorized": "已授權 {num} 個工作空間",
+ "number_of_members": "成員數量",
+ "delete_selected_workspaces": "是否移除選中的 {msg} 個工作空間?",
+ "delete_workspace": "是否移除工作空間:{msg}?",
+ "no_workspace": "暫無工作空間"
+ },
"sync": {
"records": "顯示 {num} 筆資料,共 {total} 筆",
"confirm_upload": "確定上傳",
"field_details": "欄位詳情",
"integration": "需開啟平台對接",
"the_existing_user": "若使用者已存在,覆蓋舊使用者",
+ "lazy_load": "懶加載",
"sync_users": "同步使用者",
"sync_wechat_users": "同步企業微信使用者",
"sync_dingtalk_users": "同步釘釘使用者",
@@ -64,6 +76,7 @@
"context_record_count": "上下文記錄數",
"context_record_count_hint": "使用者提問輪數",
"model_thinking_process": "展開模型思考過程",
+ "hide_model_thinking_process": "隱藏模型思考過程",
"rows_of_data": "限制 1000 列資料",
"third_party_platform_settings": "登入認證設定",
"by_third_party_platform": "自動建立使用者",
@@ -71,8 +84,8 @@
"platform_user_roles": "第三方平台使用者角色",
"excessive_data_volume": "關閉1000列的資料限制後,資料量過大,可能會造成系統卡頓",
"sqlbot_name": "問數小助手名稱",
- "hide_sql": "隱藏展示SQL按鈕",
- "hide_log": "隱藏執行日誌",
+ "show_sql": "允許查看SQL語句",
+ "show_log": "顯示執行日誌",
"prompt": "提示",
"disabling_successfully": "關閉成功",
"closed_by_default": "在問數視窗中,控制模型思考過程預設展開或者關閉",
@@ -178,6 +191,7 @@
"system_manage": "系統管理",
"update_success": "更新成功",
"save_success": "儲存成功",
+ "operation_success": "操作成功",
"next": "下一步",
"save": "儲存",
"logout": "登出",
@@ -399,7 +413,8 @@
"address": "位址",
"low_version": "相容低版本",
"ssl": "啟用 SSL",
- "file_path": "文件路徑"
+ "file_path": "文件路徑",
+ "pool_size": "連線池大小"
},
"sync_fields": "同步表結構",
"sync_fields_success": "同步表結構成功",
@@ -571,6 +586,7 @@
"member_feng_yibudao": "是否移除成員:{msg}?",
"select_member": "選擇成員",
"selected_2_people": "已選:{msg} 人",
+ "selected_number": "已選:{msg} 個",
"clear": "清空",
"historical_dialogue": "暫無歷史對話",
"rename_a_workspace": "重新命名工作區",
@@ -672,6 +688,9 @@
"application_description": "應用描述",
"cross_domain_settings": "跨網域設定",
"enableCustomModel": "使用指定模型",
+ "useModel": "使用模型",
+ "defaultModel": "預設模型",
+ "customModel": "指定模型",
"third_party_address": "請輸入嵌入的第三方位址,多個以分號分割",
"set_to_private": "設為私有",
"set_to_public": "設為公共",
@@ -722,7 +741,7 @@
"display_settings": "顯示設定",
"header_text_color": "頭部文字顏色",
"app_logo": "應用 Logo",
- "maximum_size_10mb": "建議尺寸 32 x 32,支援 JPG、PNG、SVG,大小不超過 10MB",
+ "maximum_size_10mb": "建議尺寸 32 x 32,支援 JPG、PNG,大小不超過 10MB",
"replace": "取代",
"default_icon_position": "圖示預設位置",
"draggable_position": "可拖曳位置",
@@ -771,6 +790,8 @@
"no_data": "暫無資料",
"loading_data": "載入中...",
"show_error_detail": "檢視具體資訊",
+ "thousands_separator_setting": "千分位符設定",
+ "thousands_separator_display": "套用千分位符顯示",
"log": {
"GENERATE_SQL": "產生 SQL",
"GENERATE_CHART": "產生圖表結構",
@@ -835,11 +856,11 @@
"website_logo": "網站 Logo",
"tab": "頁籤",
"replace_image": "取代圖片",
- "larger_than_200kb": "頂部網站顯示的 Logo,建議尺寸 48 x 48,支援 JPG、PNG、SVG,大小不超過 200KB",
+ "larger_than_200kb": "頂部網站顯示的 Logo,建議尺寸 48 x 48,支援 JPG、PNG,大小不超過 200KB",
"login_logo": "系統 Logo",
- "larger_than_200kb_de": "登入頁面右側 Logo,建議尺寸 204*52,支援 JPG、PNG、SVG,大小不超過 200KB",
+ "larger_than_200kb_de": "登入頁面右側 Logo,建議尺寸 204*52,支援 JPG、PNG,大小不超過 200KB",
"login_background_image": "登入背景圖",
- "larger_than_5mb": "左側背景圖,向量圖建議尺寸 576*900,點陣圖建議尺寸 1152*1800;支援 JPG、PNG、SVG,大小不超過 5M",
+ "larger_than_5mb": "左側背景圖,向量圖建議尺寸 576*900,點陣圖建議尺寸 1152*1800;支援 JPG、PNG,大小不超過 5M",
"website_name": "網站名稱",
"on_webpage_tabs": "顯示在網頁 Tab 的平台名稱",
"welcome_message": "顯示歡迎語",
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
index f81e9fcbe..08c414c1a 100644
--- a/frontend/src/main.ts
+++ b/frontend/src/main.ts
@@ -1,3 +1,7 @@
+import 'core-js/features/object/has-own'
+// @ts-ignore: css-has-pseudo/browser lacks official type definitions
+import cssHasPseudo from 'css-has-pseudo/browser'
+
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import './style.less'
@@ -7,6 +11,26 @@ import { i18n } from './i18n'
import VueDOMPurifyHTML from 'vue-dompurify-html'
// import 'element-plus/dist/index.css'
+cssHasPseudo(document)
+
+function supportsFlexGap() {
+ const flex = document.createElement('div')
+ flex.style.display = 'flex'
+ flex.style.flexDirection = 'column'
+ flex.style.rowGap = '1px'
+
+ flex.appendChild(document.createElement('div'))
+ flex.appendChild(document.createElement('div'))
+
+ document.body.appendChild(flex)
+ const isSupported = flex.scrollHeight === 1
+ document.body.removeChild(flex)
+
+ return isSupported
+}
+
+document.documentElement.setAttribute('data-no-flex-gap', String(!supportsFlexGap()))
+
const app = createApp(App)
const pinia = createPinia()
diff --git a/frontend/src/stores/appearance.ts b/frontend/src/stores/appearance.ts
index 2093f300a..ed368a7dc 100644
--- a/frontend/src/stores/appearance.ts
+++ b/frontend/src/stores/appearance.ts
@@ -315,7 +315,7 @@ const setLinkIcon = (linkWeb?: string) => {
if (linkWeb) {
link['href'] = baseUrl + linkWeb
} else {
- link['href'] = '/LOGO-fold.svg'
+ link['href'] = `${location.pathname}LOGO-fold.svg`
}
}
}
diff --git a/frontend/src/stores/assistant.ts b/frontend/src/stores/assistant.ts
index 754d00a11..45474fcbd 100644
--- a/frontend/src/stores/assistant.ts
+++ b/frontend/src/stores/assistant.ts
@@ -1,10 +1,6 @@
import { defineStore } from 'pinia'
import { store } from './index'
import { chatApi, ChatInfo } from '@/api/chat'
-import { useCache } from '@/utils/useCache'
-
-const { wsCache } = useCache()
-const flagKey = 'sqlbit-assistant-flag'
type Resolver = (value: T | PromiseLike) => void
type Rejecter = (reason?: any) => void
interface PendingRequest {
@@ -16,7 +12,6 @@ interface AssistantState {
id: string
token: string
assistant: boolean
- flag: number
type: number
certificate: string
online: boolean
@@ -35,7 +30,6 @@ export const AssistantStore = defineStore('assistant', {
id: '',
token: '',
assistant: false,
- flag: 0,
type: 0,
certificate: '',
online: false,
@@ -61,9 +55,6 @@ export const AssistantStore = defineStore('assistant', {
getAssistant(): boolean {
return this.assistant
},
- getFlag(): number {
- return this.flag
- },
getType(): number {
return this.type
},
@@ -176,14 +167,6 @@ export const AssistantStore = defineStore('assistant', {
setAssistant(assistant: boolean) {
this.assistant = assistant
},
- setFlag(flag: number) {
- if (wsCache.get(flagKey)) {
- this.flag = wsCache.get(flagKey)
- } else {
- this.flag = flag
- wsCache.set(flagKey, flag)
- }
- },
setPageEmbedded(embedded?: boolean) {
this.pageEmbedded = !!embedded
},
@@ -208,7 +191,6 @@ export const AssistantStore = defineStore('assistant', {
return chat
},
clear() {
- wsCache.delete(flagKey)
this.$reset()
},
},
diff --git a/frontend/src/stores/chatConfig.ts b/frontend/src/stores/chatConfig.ts
index 95ea95388..478547826 100644
--- a/frontend/src/stores/chatConfig.ts
+++ b/frontend/src/stores/chatConfig.ts
@@ -6,9 +6,10 @@ import { formatArg } from '@/utils/utils.ts'
interface ChatConfig {
sqlbot_name: string
expand_thinking_block: boolean
+ hide_thinking_block: boolean
limit_rows: boolean
- hide_sql: boolean
- hide_log: boolean
+ show_sql: boolean
+ show_log: boolean
}
export const chatConfigStore = defineStore('chatConfigStore', {
@@ -16,9 +17,10 @@ export const chatConfigStore = defineStore('chatConfigStore', {
return {
sqlbot_name: 'SQLBot',
expand_thinking_block: false,
+ hide_thinking_block: false,
limit_rows: true,
- hide_sql: false,
- hide_log: false,
+ show_sql: true,
+ show_log: true,
}
},
getters: {
@@ -28,11 +30,14 @@ export const chatConfigStore = defineStore('chatConfigStore', {
getExpandThinkingBlock(): boolean {
return this.expand_thinking_block
},
- getHideSQL(): boolean {
- return this.hide_sql
+ getHideThinkingBlock(): boolean {
+ return this.hide_thinking_block
},
- getHideLog(): boolean {
- return this.hide_log
+ getShowSQL(): boolean {
+ return this.show_sql
+ },
+ getShowLog(): boolean {
+ return this.show_log
},
getLimitRows(): boolean {
return this.limit_rows
@@ -43,14 +48,17 @@ export const chatConfigStore = defineStore('chatConfigStore', {
request.get('/system/parameter/chat').then((res: any) => {
if (res) {
res.forEach((item: any) => {
+ if (item.pkey === 'chat.hide_thinking_block') {
+ this.hide_thinking_block = formatArg(item.pval)
+ }
if (item.pkey === 'chat.expand_thinking_block') {
this.expand_thinking_block = formatArg(item.pval)
}
- if (item.pkey === 'chat.hide_sql') {
- this.hide_sql = formatArg(item.pval)
+ if (item.pkey === 'chat.show_sql') {
+ this.show_sql = formatArg(item.pval)
}
- if (item.pkey === 'chat.hide_log') {
- this.hide_log = formatArg(item.pval)
+ if (item.pkey === 'chat.show_log') {
+ this.show_log = formatArg(item.pval)
}
if (item.pkey === 'chat.limit_rows') {
this.limit_rows = formatArg(item.pval)
diff --git a/frontend/src/style.less b/frontend/src/style.less
index fe7799bbb..0d1d9263b 100644
--- a/frontend/src/style.less
+++ b/frontend/src/style.less
@@ -1,3 +1,23 @@
+/* ==========================================
+ 老旧浏览器 Flex Gap 完美物理隔离补丁
+ ========================================== */
+
+/* 1. 当浏览器【不支持 flex gap】时,激活此特定命名空间 */
+:root[data-no-flex-gap='true'] .flex-gap-fallback {
+ display: flex;
+}
+
+/* 2. 仅对标记了该 class 的容器下的【相邻子元素】水平方向加间距 */
+:root[data-no-flex-gap='true'] .flex-gap-fallback > * + * {
+ margin-left: var(--gap-size, 16px); /* 默认 16px,可通过变量动态修改 */
+}
+
+/* 3. 如果需要处理垂直排列(flex-direction: column) */
+:root[data-no-flex-gap='true'] .flex-gap-fallback.flex-col > * + * {
+ margin-left: 0;
+ margin-top: var(--gap-size, 16px);
+}
+
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
@@ -25,11 +45,15 @@
--shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
--ed-border-radius-base: 6px !important;
--ed-border-color: #d9dcdf !important;
+}
+
+:root:root {
--ed-color-primary-light-7: #d2f1e9 !important;
--ed-border-color: #d9dcdf !important;
--ed-disabled-border-color: #d9dcdf !important;
--ed-border-color-light: #dee0e3 !important;
--ed-border-color-lighter: #dee0e3 !important;
+ --ed-border-radius-base: 6px !important;
}
a {
@@ -84,7 +108,7 @@ body {
.list-item_primary {
height: 40px;
- border-radius: 4px;
+ border-radius: 6px;
padding: 8px 12px;
cursor: pointer;
display: flex;
@@ -226,7 +250,7 @@ strong {
.ed-select__popper {
padding: 0 4px !important;
.ed-select-dropdown__item {
- border-radius: 4px;
+ border-radius: 6px;
}
.ed-select-dropdown__list {
@@ -427,10 +451,9 @@ strong {
}
.ed-tree-node__content {
- border-radius: 4px;
+ border-radius: 6px;
}
-
.login-content {
/* 针对 Webkit 浏览器的自动填充样式重置 */
input:-webkit-autofill,
@@ -438,7 +461,7 @@ strong {
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
/* 1. 使用足够大的内阴影来覆盖背景色,把 #ffffff 替换成你输入框原本的背景色 */
- -webkit-box-shadow: 0 0 0px 1000px #f5f7fa inset !important;
+ -webkit-box-shadow: 0 0 0px 1000px #ffffff inset !important;
/* 2. 由于常规的 color 属性也会失效,需要用这个属性修改文字颜色 */
-webkit-text-fill-color: #333333 !important;
@@ -446,4 +469,12 @@ strong {
/* 3. 保留光标的正常颜色 */
caret-color: #333333;
}
-}
\ No newline at end of file
+}
+
+.ed-popper.is-pure:has(.ed-select-dropdown) {
+ padding: 0 !important;
+
+ .ed-select-dropdown {
+ padding: 0 4px !important;
+ }
+}
diff --git a/frontend/src/views/chat/ChatList.vue b/frontend/src/views/chat/ChatList.vue
index c2a98aa3b..33799afc5 100644
--- a/frontend/src/views/chat/ChatList.vue
+++ b/frontend/src/views/chat/ChatList.vue
@@ -200,7 +200,7 @@ const handleConfirmPassword = () => {
-
+
{
display: flex;
flex-direction: column;
+ --gap-size: 16px;
gap: 16px;
.group {
@@ -399,7 +400,7 @@ const handleConfirmPassword = () => {
diff --git a/frontend/src/views/dashboard/canvas/CanvasCore.vue b/frontend/src/views/dashboard/canvas/CanvasCore.vue
index 7fe3a84a7..6a58d220f 100644
--- a/frontend/src/views/dashboard/canvas/CanvasCore.vue
+++ b/frontend/src/views/dashboard/canvas/CanvasCore.vue
@@ -727,7 +727,11 @@ function startResize(e: MouseEvent, point: string, item: CanvasItem, index: numb
infoBox.value.point = point
}
-function containerClick() {
+function containerClick(e?: MouseEvent) {
+ // Ignore clicks that originate inside a component so interacting with component
+ // content (e.g. selecting/copying cells in an S2 table) does not clear the
+ // current selection. Only blank-canvas clicks deselect.
+ if ((e?.target as HTMLElement)?.closest?.('.item')) return
// remove current component info
dashboardStore.setCurComponent(null)
}
diff --git a/frontend/src/views/dashboard/canvas/CanvasShape.vue b/frontend/src/views/dashboard/canvas/CanvasShape.vue
index f49de87fb..a498b3590 100644
--- a/frontend/src/views/dashboard/canvas/CanvasShape.vue
+++ b/frontend/src/views/dashboard/canvas/CanvasShape.vue
@@ -52,7 +52,11 @@ const props = defineProps({
const { draggable } = toRefs(props)
const shapeClick = (e: MouseEvent) => {
- e.stopPropagation()
+ // Do not stopPropagation here: the click must reach window so components that
+ // rely on a window-level click listener (e.g. the S2 table copy interaction,
+ // which only enables Cmd/Ctrl+C when the last click landed on its canvas) work
+ // inside the editor. Deselection is handled by containerClick ignoring clicks
+ // that originate inside a component.
e.preventDefault()
}
diff --git a/frontend/src/views/dashboard/canvas/ComponentBar.vue b/frontend/src/views/dashboard/canvas/ComponentBar.vue
index bd6ac78b2..b2480804c 100644
--- a/frontend/src/views/dashboard/canvas/ComponentBar.vue
+++ b/frontend/src/views/dashboard/canvas/ComponentBar.vue
@@ -115,7 +115,7 @@ const doDeleteComponent = (e: MouseEvent) => {
+
+
diff --git a/frontend/src/views/system/model/Model.vue b/frontend/src/views/system/model/Model.vue
index 76f514058..47da0cd49 100644
--- a/frontend/src/views/system/model/Model.vue
+++ b/frontend/src/views/system/model/Model.vue
@@ -16,8 +16,11 @@ import { getModelTypeName } from '@/entity/CommonEntity.ts'
import { useI18n } from 'vue-i18n'
import { get_supplier } from '@/entity/supplier'
import { highlightKeyword } from '@/utils/xss'
+import AuthorizedWorkspaceDialogForModel from '@/views/system/workspace/AuthorizedWorkspaceDialogForModel.vue'
+import AuthorizedWorkspaceDraw from '@/views/system/workspace/AuthorizedWorkspaceDraw.vue'
interface Model {
+ ws_mapping_count: number | undefined
name: string
model_type: string
base_model: string
@@ -249,6 +252,16 @@ const deleteHandler = (item: any) => {
})
}
+const AuthorizedWorkspaceDialogForModelRef = ref()
+const AuthorizedWorkspaceDrawRef = ref()
+
+const handleAuthorizedSpace = (item: any) => {
+ AuthorizedWorkspaceDialogForModelRef.value.open(item.id)
+}
+const handleEditWorkspaceList = (item: any) => {
+ AuthorizedWorkspaceDrawRef.value.open(item.id)
+}
+
const clickModel = (ele: any) => {
activeStep.value = 1
supplierChang(ele)
@@ -387,6 +400,7 @@ const submit = (item: any) => {
:ref="(el: any) => setCardRef(el, index)"
:key="ele.id"
:name="ele.name"
+ :num="ele.ws_mapping_count"
:supplier="ele.supplier"
:model-type="getModelTypeName(ele['model_type'])"
:base-model="ele['base_model']"
@@ -394,6 +408,8 @@ const submit = (item: any) => {
@edit="handleEditModel(ele)"
@del="deleteHandler"
@default="handleDefault(ele)"
+ @authorized-space="handleAuthorizedSpace(ele)"
+ @edit-workspace-list="handleEditWorkspaceList(ele)"
>
@@ -468,6 +484,8 @@ const submit = (item: any) => {
+
+
diff --git a/frontend/src/views/system/workspace/AuthorizedWorkspaceDialogForModelAdd.vue b/frontend/src/views/system/workspace/AuthorizedWorkspaceDialogForModelAdd.vue
new file mode 100644
index 000000000..4f1fc4ba6
--- /dev/null
+++ b/frontend/src/views/system/workspace/AuthorizedWorkspaceDialogForModelAdd.vue
@@ -0,0 +1,349 @@
+
+
+ {{ $t('authorized_space.select_space') }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('datasource.select_all') }}
+
+
+
+
+
+
+
+
+ {{ space.name }}
+
+
+
+
+
+
+
+
+ {{ $t('workspace.selected_number', { msg: checkTableList.length }) }}
+
+
+
+ {{ $t('workspace.clear') }}
+
+
+
+
+
+
+
+
{{
+ ele.name
+ }}
+
+
+
+
+
+
+
+
+
+
+ {{ $t('common.cancel') }}
+
+ {{ $t('common.confirm2') }}
+
+
+
+
+
+
+
diff --git a/frontend/src/views/system/workspace/AuthorizedWorkspaceDraw.vue b/frontend/src/views/system/workspace/AuthorizedWorkspaceDraw.vue
new file mode 100644
index 000000000..808eb16ac
--- /dev/null
+++ b/frontend/src/views/system/workspace/AuthorizedWorkspaceDraw.vue
@@ -0,0 +1,521 @@
+
+
+
+
+
+ {{ $t('authorized_space.workspaces_authorized', { num: filteredList.length }) }}
+
+
+
+
+
+
+ {{ $t('authorized_space.authorized_space') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('datasource.select_all') }}
+
+
+
+
+ {{
+ $t('user.selected_2_items', { msg: multipleSelectionAll.length })
+ }}
+
+ {{ $t('common.cancel') }}
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/system/workspace/index.vue b/frontend/src/views/system/workspace/index.vue
index da3519cd4..303c888e6 100644
--- a/frontend/src/views/system/workspace/index.vue
+++ b/frontend/src/views/system/workspace/index.vue
@@ -701,7 +701,7 @@ const handleCurrentChange = (val: number) => {
display: flex;
align-items: center;
padding-left: 8px;
- border-radius: 4px;
+ border-radius: 6px;
cursor: pointer;
padding-right: 8px;
margin-bottom: 2px;
@@ -876,7 +876,7 @@ const handleCurrentChange = (val: number) => {