feat:修复知识库问题
parent
c142297f41
commit
4c9ac22a7f
|
|
@ -40,6 +40,8 @@ def get_embedding_id(knowledge_id_list):
|
|||
_("The vector model of the associated knowledge base is inconsistent and the segmentation cannot be recalled."))
|
||||
if len(knowledge_list) == 0:
|
||||
raise Exception(_("The knowledge base setting is wrong, please reset the knowledge base"))
|
||||
if knowledge_list[0].embedding_model_id is None:
|
||||
raise Exception(_("The knowledge base setting is wrong, please reset the knowledge base"))
|
||||
return knowledge_list[0].embedding_model_id
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ def get_embedding_id(dataset_id_list):
|
|||
raise Exception("关联知识库的向量模型不一致,无法召回分段。")
|
||||
if len(dataset_list) == 0:
|
||||
raise Exception("知识库设置错误,请重新设置知识库")
|
||||
if dataset_list[0].embedding_model_id is None:
|
||||
raise Exception("Knowledge base setting error, please reset the knowledge base")
|
||||
return dataset_list[0].embedding_model_id
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ from django.db.models import QuerySet
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from application.models import ApplicationAccessToken, ChatUserType, Application, ApplicationVersion
|
||||
from application.models import ApplicationAccessToken, ChatUserType, Application, ApplicationVersion, \
|
||||
ApplicationKnowledgeMapping
|
||||
from application.models.application_api_key import ApplicationApiKey
|
||||
from application.serializers.application import ApplicationSerializerModel
|
||||
from common.auth.common import ChatUserToken, ChatAuthentication
|
||||
|
|
@ -23,6 +24,7 @@ from common.constants.cache_version import Cache_Version
|
|||
from common.database_model_manage.database_model_manage import DatabaseModelManage
|
||||
from common.exception.app_exception import NotFound404, AppUnauthorizedFailed
|
||||
from common.utils.rsa_util import get_key_pair_by_sql
|
||||
from knowledge.models import Knowledge, Problem
|
||||
|
||||
|
||||
class AnonymousAuthenticationSerializer(serializers.Serializer):
|
||||
|
|
@ -173,6 +175,61 @@ class ApplicationProfileSerializer(serializers.Serializer):
|
|||
_v = getattr(application_version, version_field)
|
||||
setattr(application, app_field, _v)
|
||||
|
||||
@staticmethod
|
||||
def get_work_flow_knowledge_id_list(work_flow):
|
||||
knowledge_id_list = []
|
||||
knowledge_keys = {
|
||||
'knowledge_id',
|
||||
'knowledge_id_list',
|
||||
'dataset_id',
|
||||
'dataset_id_list',
|
||||
'all_knowledge_id_list',
|
||||
}
|
||||
|
||||
def collect(data):
|
||||
if isinstance(data, dict):
|
||||
for key, value in data.items():
|
||||
if key in knowledge_keys:
|
||||
if isinstance(value, list):
|
||||
knowledge_id_list.extend([str(item) for item in value if item])
|
||||
elif value:
|
||||
knowledge_id_list.append(str(value))
|
||||
else:
|
||||
collect(value)
|
||||
elif isinstance(data, list):
|
||||
for item in data:
|
||||
collect(item)
|
||||
|
||||
collect(work_flow or {})
|
||||
return list(dict.fromkeys(knowledge_id_list))
|
||||
|
||||
@staticmethod
|
||||
def get_suggested_questions(application):
|
||||
knowledge_id_list = [str(knowledge_id) for knowledge_id in QuerySet(ApplicationKnowledgeMapping).filter(
|
||||
application_id=application.id
|
||||
).values_list('knowledge_id', flat=True)]
|
||||
knowledge_id_list.extend(ApplicationProfileSerializer.get_work_flow_knowledge_id_list(application.work_flow))
|
||||
knowledge_id_list = list(dict.fromkeys(knowledge_id_list))
|
||||
knowledge_id_list = [str(knowledge_id) for knowledge_id in QuerySet(Knowledge).filter(
|
||||
id__in=knowledge_id_list
|
||||
).values_list('id', flat=True)]
|
||||
problem_query_set = QuerySet(Problem)
|
||||
if len(knowledge_id_list) > 0:
|
||||
problem_query_set = problem_query_set.filter(knowledge_id__in=knowledge_id_list)
|
||||
else:
|
||||
problem_query_set = problem_query_set.filter(knowledge__workspace_id=application.workspace_id)
|
||||
problem_list = problem_query_set.exclude(content='').order_by(
|
||||
'-hit_num', '-create_time'
|
||||
).values_list('content', flat=True)
|
||||
result = []
|
||||
for content in problem_list:
|
||||
content = (content or '').strip()
|
||||
if content and content not in result:
|
||||
result.append(content)
|
||||
if len(result) >= 3:
|
||||
break
|
||||
return result
|
||||
|
||||
def profile(self, with_valid=True):
|
||||
if with_valid:
|
||||
self.is_valid()
|
||||
|
|
@ -219,6 +276,7 @@ class ApplicationProfileSerializer(serializers.Serializer):
|
|||
'show_user_avatar': application_setting.show_user_avatar,
|
||||
'float_location': application_setting.float_location,
|
||||
'chat_background': application_setting.chat_background}
|
||||
suggested_questions = self.get_suggested_questions(application)
|
||||
base_node = [node for node in ((application.work_flow or {}).get('nodes', []) or []) if
|
||||
node.get('id') == 'base-node']
|
||||
return {**ApplicationSerializerModel(application).data,
|
||||
|
|
@ -232,6 +290,7 @@ class ApplicationProfileSerializer(serializers.Serializer):
|
|||
'file_upload_enable': application.file_upload_enable,
|
||||
'file_upload_setting': application.file_upload_setting,
|
||||
'work_flow': {'nodes': base_node} if base_node else None,
|
||||
'suggested_questions': suggested_questions,
|
||||
'show_source': application_access_token.show_source,
|
||||
'show_exec': application_access_token.show_exec,
|
||||
'language': application_access_token.language,
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@ def get_embedding_model_by_knowledge_id_list(knowledge_id_list: List):
|
|||
raise Exception(_('The knowledge base is inconsistent with the vector model'))
|
||||
if len(knowledge_list) == 0:
|
||||
raise Exception(_('Knowledge base setting error, please reset the knowledge base'))
|
||||
if knowledge_list[0].embedding_model_id is None or knowledge_list[0].embedding_model is None:
|
||||
raise Exception(_('Knowledge base setting error, please reset the knowledge base'))
|
||||
|
||||
default_params = get_model_default_params(knowledge_list[0].embedding_model)
|
||||
|
||||
|
|
@ -130,6 +132,8 @@ def get_embedding_model_by_knowledge_id_list(knowledge_id_list: List):
|
|||
|
||||
def get_embedding_model_by_knowledge_id(knowledge_id: str):
|
||||
knowledge = QuerySet(Knowledge).select_related('embedding_model').filter(id=knowledge_id).first()
|
||||
if knowledge is None or knowledge.embedding_model_id is None or knowledge.embedding_model is None:
|
||||
raise Exception(_('Knowledge base setting error, please reset the knowledge base'))
|
||||
|
||||
default_params = get_model_default_params(knowledge.embedding_model)
|
||||
|
||||
|
|
@ -138,6 +142,8 @@ def get_embedding_model_by_knowledge_id(knowledge_id: str):
|
|||
|
||||
|
||||
def get_embedding_model_by_knowledge(knowledge):
|
||||
if knowledge is None or knowledge.embedding_model_id is None or knowledge.embedding_model is None:
|
||||
raise Exception(_('Knowledge base setting error, please reset the knowledge base'))
|
||||
default_params = get_model_default_params(knowledge.embedding_model)
|
||||
|
||||
return ModelManage.get_model(str(knowledge.embedding_model_id),
|
||||
|
|
@ -146,6 +152,8 @@ def get_embedding_model_by_knowledge(knowledge):
|
|||
|
||||
def get_embedding_model_id_by_knowledge_id(knowledge_id):
|
||||
knowledge = QuerySet(Knowledge).select_related('embedding_model').filter(id=knowledge_id).first()
|
||||
if knowledge is None or knowledge.embedding_model_id is None:
|
||||
raise Exception(_('Knowledge base setting error, please reset the knowledge base'))
|
||||
return str(knowledge.embedding_model_id)
|
||||
|
||||
|
||||
|
|
@ -155,6 +163,8 @@ def get_embedding_model_id_by_knowledge_id_list(knowledge_id_list: List):
|
|||
raise Exception(_('The knowledge base is inconsistent with the vector model'))
|
||||
if len(knowledge_list) == 0:
|
||||
raise Exception(_('Knowledge base setting error, please reset the knowledge base'))
|
||||
if knowledge_list[0].embedding_model_id is None:
|
||||
raise Exception(_('Knowledge base setting error, please reset the knowledge base'))
|
||||
return str(knowledge_list[0].embedding_model_id)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1702,9 +1702,11 @@ class DocumentSerializers(serializers.Serializer):
|
|||
source_file.save(file_content)
|
||||
|
||||
file.seek(0)
|
||||
parsed_documents = DocumentSerializers.Split(
|
||||
split_serializer = DocumentSerializers.Split(
|
||||
data={'workspace_id': self.data.get('workspace_id'), 'knowledge_id': self.data.get('knowledge_id')}
|
||||
).file_to_paragraph(file, None, None, 4096)
|
||||
)
|
||||
split_serializer.is_valid(instance={'file': [file]}, raise_exception=True)
|
||||
parsed_documents = split_serializer.file_to_paragraph(file, None, None, 4096)
|
||||
paragraphs = []
|
||||
for parsed_document in parsed_documents:
|
||||
paragraphs.extend(parsed_document.get('content', []))
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ def get_model(model, **kwargs):
|
|||
@param model: model 数据库Model实例对象
|
||||
@return: 模型实例
|
||||
"""
|
||||
if model is None:
|
||||
raise Exception(_("Model does not exist"))
|
||||
return get_model_(model.provider, model.model_type, model.model_name, model.credential, str(model.id), **kwargs)
|
||||
|
||||
|
||||
|
|
@ -105,6 +107,8 @@ def is_valid_credential(provider, model_type, model_name, model_credential: Dict
|
|||
|
||||
|
||||
def get_model_by_id(_id, workspace_id):
|
||||
if _id is None:
|
||||
raise Exception(_("Model does not exist"))
|
||||
model = QuerySet(Model).filter(id=_id).first()
|
||||
# 归还链接到连接池
|
||||
connection.close()
|
||||
|
|
@ -116,6 +120,9 @@ def get_model_by_id(_id, workspace_id):
|
|||
return model
|
||||
|
||||
def get_model_default_params(model):
|
||||
if model is None:
|
||||
raise Exception(_("Model does not exist"))
|
||||
|
||||
def convert_to_int(value):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -43,11 +43,48 @@ const showUserAvatar = computed(() => {
|
|||
return props.application.show_user_avatar == undefined ? true : props.application.show_user_avatar
|
||||
})
|
||||
|
||||
const applicationName = computed(() => {
|
||||
return props.application?.name || props.application?.application_name || 'XXX'
|
||||
})
|
||||
|
||||
const replaceApplicationName = (text: string) => {
|
||||
return (text || '').replaceAll('XXX', applicationName.value)
|
||||
}
|
||||
|
||||
const defaultQuestions = computed(() => {
|
||||
const source = replaceApplicationName(props.application?.prologue || '')
|
||||
const questionList = Array.from(source.matchAll(/-\s+(.+)/g))
|
||||
.map((match) => match[1]?.trim())
|
||||
.filter((item) => item)
|
||||
if (questionList.length) {
|
||||
return questionList.slice(0, 3)
|
||||
}
|
||||
return [
|
||||
`${applicationName.value}主要功能有什么?`,
|
||||
`${applicationName.value}如何收费?`,
|
||||
'需要转人工服务',
|
||||
]
|
||||
})
|
||||
|
||||
const suggestedQuestions = computed(() => {
|
||||
const questions = props.application?.suggested_questions
|
||||
return Array.isArray(questions)
|
||||
? questions.map((item) => `${item || ''}`.trim()).filter((item) => item).slice(0, 3)
|
||||
: []
|
||||
})
|
||||
|
||||
const toQuickQuestion = (match: string, offset: number, input: string) => {
|
||||
return `<quick_question>${match.replace('- ', '')}</quick_question>`
|
||||
}
|
||||
const prologue = computed(() => {
|
||||
const temp = props.available ? props.application?.prologue : t('chat.tip.prologueMessage')
|
||||
const temp = props.available
|
||||
? [
|
||||
`您好,我是${applicationName.value},您可以向我提出以下或其它问题。`,
|
||||
...(suggestedQuestions.value.length ? suggestedQuestions.value : defaultQuestions.value).map(
|
||||
(item) => `<quick_question>${item}</quick_question>`,
|
||||
),
|
||||
].join('\n')
|
||||
: t('chat.tip.prologueMessage')
|
||||
if (temp) {
|
||||
const tag_list = [
|
||||
/<html_rander>[\d\D]*?<\/html_rander>/g,
|
||||
|
|
|
|||
|
|
@ -5,15 +5,20 @@
|
|||
<template v-for="(item, index) in md_view_list" :key="index">
|
||||
<div
|
||||
v-if="item.type === 'question'"
|
||||
@click="
|
||||
sendMessage && type !== 'log' ? sendMessage(item.content, 'new') : (content: string) => {}
|
||||
"
|
||||
@click="sendQuestion(item.content)"
|
||||
class="problem-button mt-4 mb-4"
|
||||
:class="sendMessage && type !== 'log' ? 'cursor' : 'disabled'"
|
||||
>
|
||||
<el-space :size="8" alignment="flex-start">
|
||||
<AppIcon iconName="app-edit" class="color-primary" style="margin-top: 3px"></AppIcon>
|
||||
{{ item.content }}
|
||||
<AppIcon
|
||||
iconName="app-edit"
|
||||
class="color-primary quick-question-edit"
|
||||
style="margin-top: 3px"
|
||||
@click.stop="setInputQuestion(item.content)"
|
||||
></AppIcon>
|
||||
<span>
|
||||
{{ item.content }}
|
||||
</span>
|
||||
</el-space>
|
||||
</div>
|
||||
<HtmlRander v-else-if="item.type === 'html_rander'" :source="item.content"></HtmlRander>
|
||||
|
|
@ -49,6 +54,7 @@ import EchartsRander from './EchartsRander.vue'
|
|||
import FormRander from './FormRander.vue'
|
||||
import ReasoningRander from './ReasoningRander.vue'
|
||||
import { nanoid } from 'nanoid'
|
||||
import bus from '@/bus'
|
||||
config({
|
||||
markdownItConfig(md) {
|
||||
md.renderer.rules.image = (tokens, idx, options, env, self) => {
|
||||
|
|
@ -88,6 +94,16 @@ const props = withDefaults(
|
|||
},
|
||||
)
|
||||
const editorRef = ref()
|
||||
const sendQuestion = (question: string) => {
|
||||
if (props.sendMessage && props.type !== 'log') {
|
||||
props.sendMessage(question, 'new')
|
||||
}
|
||||
}
|
||||
const setInputQuestion = (question: string) => {
|
||||
if (props.type !== 'log') {
|
||||
bus.emit('chat-input', question)
|
||||
}
|
||||
}
|
||||
const md_view_list = computed(() => {
|
||||
const temp_source = props.source
|
||||
return split_form_rander(
|
||||
|
|
|
|||
|
|
@ -128,6 +128,24 @@
|
|||
@close="closeSingleSelectDialog"
|
||||
width="500px"
|
||||
>
|
||||
<div v-if="pendingPermissionChange" class="permission-confirm-info mb-16">
|
||||
<div>{{ resourceTypeLabel }}:{{ targetResourceName }}</div>
|
||||
<div>
|
||||
{{ $t('views.userManage.userForm.nick_name.label') }}:{{
|
||||
pendingPermissionChange.row?.nick_name || '-'
|
||||
}}
|
||||
</div>
|
||||
<div>
|
||||
{{ $t('views.login.loginForm.username.label') }}:{{
|
||||
pendingPermissionChange.row?.username || '-'
|
||||
}}
|
||||
</div>
|
||||
<div>
|
||||
{{ $t('views.model.modelForm.permissionType.label') }}:{{
|
||||
getPermissionLabel(pendingPermissionChange.val)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<el-radio-group v-if="isFolder" v-model="authAllChildren" class="radio-block">
|
||||
<el-radio :value="false">
|
||||
<p class="color-text-primary lighter">
|
||||
|
|
@ -326,6 +344,8 @@ watch(drawerVisible, (bool) => {
|
|||
searchType.value = 'nick_name'
|
||||
searchForm.value = { nick_name: '', username: '', permission: undefined }
|
||||
permissionData.value = []
|
||||
targetResource.value = null
|
||||
folderData.value = null
|
||||
paginationConfig.current_page = 1
|
||||
paginationConfig.total = 0
|
||||
multipleSelection.value = []
|
||||
|
|
@ -336,6 +356,7 @@ watch(drawerVisible, (bool) => {
|
|||
const loading = ref(false)
|
||||
const targetId = ref('')
|
||||
const folderData = ref<any>(null)
|
||||
const targetResource = ref<any>(null)
|
||||
const permissionData = ref<any[]>([])
|
||||
const searchType = ref('nick_name')
|
||||
const searchForm = ref<any>({
|
||||
|
|
@ -374,6 +395,32 @@ const singleSelectDialogVisible = ref(false)
|
|||
const pendingPermissionChange = ref<{ val: any; row: any } | null>(null)
|
||||
const radioPermission = ref('')
|
||||
const authAllChildren = ref(false)
|
||||
|
||||
const resourceTypeLabelMap: Record<string, string> = {
|
||||
APPLICATION: t('views.application.title'),
|
||||
KNOWLEDGE: t('views.knowledge.title'),
|
||||
TOOL: t('views.tool.title'),
|
||||
MODEL: t('views.model.title'),
|
||||
}
|
||||
|
||||
const resourceTypeLabel = computed(() => {
|
||||
return props.isFolder
|
||||
? '文件夹'
|
||||
: resourceTypeLabelMap[props.type] || t('views.system.resourceAuthorization.title')
|
||||
})
|
||||
|
||||
const targetResourceName = computed(() => {
|
||||
return targetResource.value?.name || folderData.value?.name || targetId.value || '-'
|
||||
})
|
||||
|
||||
const getPermissionLabel = (permission: string) => {
|
||||
return (
|
||||
getFolderPermissionOptions().find((item) => item.value === permission)?.label ||
|
||||
permission ||
|
||||
'-'
|
||||
)
|
||||
}
|
||||
|
||||
function openMulConfigureDialog() {
|
||||
if (multipleSelection.value.length === 0) {
|
||||
return
|
||||
|
|
@ -458,9 +505,10 @@ const getPermissionList = () => {
|
|||
})
|
||||
}
|
||||
|
||||
const open = (id: string, folder_data?: any) => {
|
||||
const open = (id: string, resource_data?: any) => {
|
||||
targetId.value = id
|
||||
folderData.value = folder_data
|
||||
folderData.value = props.isFolder ? resource_data : null
|
||||
targetResource.value = resource_data || null
|
||||
drawerVisible.value = true
|
||||
getPermissionList()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
<h1 class="header-title">AI-RAG</h1>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<router-link v-if="isSystemManagement" to="/application" class="back-link">
|
||||
<button v-if="isSystemManagement" class="back-link" type="button" @click="goBackWorkspace">
|
||||
<span class="back-icon">←</span>
|
||||
{{menuText.back}}
|
||||
</router-link>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -18,10 +18,11 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import ChinaMobileIcon from '@/components/china-mobile-icon/index.vue'
|
||||
const { locale } = useI18n({ useScope: 'global' })
|
||||
const SYSTEM_ENTRY_FROM_KEY = 'system_entry_from'
|
||||
const menuText = computed(() => {
|
||||
if (locale.value === 'en-US') {
|
||||
return {
|
||||
|
|
@ -40,11 +41,21 @@ const menuText = computed(() => {
|
|||
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const isSystemManagement = computed(() => {
|
||||
const path = route.path
|
||||
return path.startsWith('/system') || path.startsWith('/admin/system')
|
||||
return path.startsWith('/system') || path === '/operate' || path.startsWith('/admin/system')
|
||||
})
|
||||
|
||||
const isValidReturnPath = (path?: string | null) => {
|
||||
return Boolean(path && !path.startsWith('/system') && path !== '/operate')
|
||||
}
|
||||
|
||||
const goBackWorkspace = () => {
|
||||
const fromPath = sessionStorage.getItem(SYSTEM_ENTRY_FROM_KEY)
|
||||
router.push(isValidReturnPath(fromPath) ? fromPath! : '/knowledge')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
@ -91,9 +102,10 @@ const isSystemManagement = computed(() => {
|
|||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
text-decoration: none;
|
||||
color: #1890ff;
|
||||
border: 1px solid #1890ff;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,25 @@ import useStore from '@/stores'
|
|||
import { routes } from '@/router/routes'
|
||||
import { getFirstAvailableMenuPath, resolveMenuIdByPath } from '@/utils/menu-setting'
|
||||
NProgress.configure({ showSpinner: false, speed: 500, minimum: 0.3 })
|
||||
const SYSTEM_ENTRY_FROM_KEY = 'system_entry_from'
|
||||
|
||||
const isSystemRoutePath = (path: string) => {
|
||||
return path.startsWith('/system') || path === '/operate'
|
||||
}
|
||||
|
||||
const shouldRecordSystemEntryFrom = (
|
||||
to: RouteLocationNormalized,
|
||||
from: RouteLocationNormalized,
|
||||
) => {
|
||||
return (
|
||||
isSystemRoutePath(to.path) &&
|
||||
!isSystemRoutePath(from.path) &&
|
||||
from.name &&
|
||||
from.path !== '/' &&
|
||||
from.path !== '/login'
|
||||
)
|
||||
}
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(window.MaxKB?.prefix ? window.MaxKB?.prefix : import.meta.env.BASE_URL),
|
||||
routes: routes,
|
||||
|
|
@ -22,6 +41,9 @@ const router = createRouter({
|
|||
router.beforeEach(
|
||||
async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
|
||||
NProgress.start()
|
||||
if (shouldRecordSystemEntryFrom(to, from)) {
|
||||
sessionStorage.setItem(SYSTEM_ENTRY_FROM_KEY, from.fullPath)
|
||||
}
|
||||
if (to.name === '404') {
|
||||
next()
|
||||
return
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ const CopyApplicationDialogRef = ref()
|
|||
|
||||
const ResourceAuthorizationDrawerRef = ref()
|
||||
function openAuthorization(item: any) {
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id)
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id, item)
|
||||
}
|
||||
|
||||
const MoveToDialogRef = ref()
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ const paginationConfig = reactive({
|
|||
|
||||
const ResourceAuthorizationDrawerRef = ref()
|
||||
function openAuthorization(item: any) {
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id)
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id, item)
|
||||
}
|
||||
|
||||
const MoveToDialogRef = ref()
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ const MoreFilledPermission = (id: any) => {
|
|||
|
||||
const ResourceAuthorizationDrawerRef = ref()
|
||||
function openAuthorization(item: any) {
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id)
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id, item)
|
||||
}
|
||||
|
||||
const downModel = ref<Model>()
|
||||
|
|
|
|||
|
|
@ -354,7 +354,7 @@ const MoreFilledPermission = () => {
|
|||
const ResourceAuthorizationDrawerRef = ref()
|
||||
|
||||
function openAuthorization(item: any) {
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id)
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id, item)
|
||||
}
|
||||
|
||||
const apiInputParams = ref([])
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ const paginationConfig = reactive({
|
|||
|
||||
const ResourceAuthorizationDrawerRef = ref()
|
||||
function openAuthorization(item: any) {
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id)
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id, item)
|
||||
}
|
||||
|
||||
const exportKnowledge = (item: any) => {
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ const MoreFilledPermission = () => {
|
|||
|
||||
const ResourceAuthorizationDrawerRef = ref()
|
||||
function openAuthorization(item: any) {
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id)
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id, item)
|
||||
}
|
||||
|
||||
const deleteModel = (row: any) => {
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ const MoreFilledPermission = (row: any) => {
|
|||
|
||||
const ResourceAuthorizationDrawerRef = ref()
|
||||
function openAuthorization(item: any) {
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id)
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id, item)
|
||||
}
|
||||
|
||||
function exportTool(row: any) {
|
||||
|
|
|
|||
|
|
@ -150,12 +150,15 @@ import { ComplexPermission } from '@/utils/permission/type'
|
|||
import { getPermissionOptions } from '@/views/system/resource-authorization/constant'
|
||||
import useStore from '@/stores'
|
||||
import { TreeToFlatten } from '@/utils/array'
|
||||
import { MsgConfirm } from '@/utils/message'
|
||||
|
||||
const { model, user } = useStore()
|
||||
const route = useRoute()
|
||||
const props = defineProps<{
|
||||
data: any[]
|
||||
type: string
|
||||
resourceLabel?: string
|
||||
currentMember?: any
|
||||
getData?: () => void
|
||||
}>()
|
||||
const emit = defineEmits(['submitPermissions'])
|
||||
|
|
@ -170,6 +173,7 @@ watch(
|
|||
defaultExpandKeys.value = props.data?.length > 0 ? [props.data[0]?.id] : []
|
||||
isComputedFirst.value = false
|
||||
}
|
||||
refreshPermissionSnapshot(newData || [])
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
|
@ -329,6 +333,41 @@ const filteredData = computed(() => {
|
|||
|
||||
const multipleSelection = ref<any[]>([])
|
||||
const selectObj: any = {}
|
||||
const permissionSnapshot = ref<Record<string, string>>({})
|
||||
|
||||
const refreshPermissionSnapshot = (data: any[]) => {
|
||||
const snapshot: Record<string, string> = {}
|
||||
TreeToFlatten(data || []).forEach((item: any) => {
|
||||
snapshot[item.id] = item.permission
|
||||
})
|
||||
permissionSnapshot.value = snapshot
|
||||
}
|
||||
|
||||
const escapeHtml = (value: any) => {
|
||||
return String(value ?? '-')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
}
|
||||
|
||||
const getPermissionLabel = (value: string, row: any) => {
|
||||
return getRowPermissionOptions(row).find((item) => item.value === value)?.label || value
|
||||
}
|
||||
|
||||
const getConfirmDescription = (value: string, row: any) => {
|
||||
const resourceLabel = props.resourceLabel || '资源'
|
||||
const memberName = props.currentMember?.nick_name || props.currentMember?.username || '-'
|
||||
return `
|
||||
<div style="line-height: 1.8;">
|
||||
<div>${escapeHtml(resourceLabel)}:${escapeHtml(row?.name)}</div>
|
||||
<div>姓名:${escapeHtml(memberName)}</div>
|
||||
<div>操作权限:${escapeHtml(getPermissionLabel(value, row))}</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
const selectAll = (selection: any[]) => {
|
||||
multipleSelection.value = selection
|
||||
}
|
||||
|
|
@ -384,7 +423,17 @@ function closeDialog() {
|
|||
multipleTableRef.value?.clearSelection()
|
||||
}
|
||||
|
||||
function submitPermissions(value: string, row: any) {
|
||||
async function submitPermissions(value: string, row: any) {
|
||||
const previousPermission = permissionSnapshot.value[row.id] || 'NOT_AUTH'
|
||||
try {
|
||||
await MsgConfirm('确认修改资源权限', getConfirmDescription(value, row), {
|
||||
dangerouslyUseHTMLString: true,
|
||||
type: 'warning',
|
||||
})
|
||||
} catch {
|
||||
row.permission = previousPermission
|
||||
return
|
||||
}
|
||||
const obj = [
|
||||
{
|
||||
target_id: row.id,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@
|
|||
<PermissionTable
|
||||
:data="treeData"
|
||||
:type="activeData.type"
|
||||
:resource-label="activeData.label"
|
||||
:current-member="currentMember"
|
||||
ref="PermissionTableRef"
|
||||
:getData="getPermissionList"
|
||||
@submitPermissions="submitPermissions"
|
||||
|
|
@ -213,6 +215,10 @@ const treeData = computed(() => {
|
|||
return toTree(permissionData.value, 'folder_id')
|
||||
})
|
||||
|
||||
const currentMember = computed(() => {
|
||||
return memberList.value.find((item: any) => item.id === currentUser.value)
|
||||
})
|
||||
|
||||
function clickMemberHandle(item: any) {
|
||||
currentUser.value = item.id
|
||||
currentType.value = item.type
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ const MoreFieldPermission = (id: any) => {
|
|||
|
||||
const ResourceAuthorizationDrawerRef = ref()
|
||||
function openAuthorization(item: any) {
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id)
|
||||
ResourceAuthorizationDrawerRef.value.open(item.id, item)
|
||||
}
|
||||
|
||||
const InitParamDrawerRef = ref()
|
||||
|
|
|
|||
Loading…
Reference in New Issue