Browse Source

Merge branch 'space2'

qin_26
han2015 2 months ago
parent
commit
284168f5b0
  1. 16
      src/api/doc/space.ts
  2. 20
      src/store/modules/orgMember.ts
  3. 118
      src/views/doc/agent.vue
  4. 48
      src/views/doc/manage.vue
  5. 4
      src/views/doc/onlyoffice.vue
  6. 4
      src/views/doc/recentVisited.vue
  7. 111
      src/views/doc/space.vue
  8. 95
      src/views/doc/spacePermission.vue

16
src/api/doc/space.ts

@ -74,6 +74,22 @@ export function doDelSpace(uid:string,data?: any){
});
}
/**
*
*/
export function spaceMatterRename(uid:string,data?: any){
return request({
url: '/hxpan/api/space/rename',
method: 'post',
headers: {
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
});
}
/**
*
*/

20
src/store/modules/orgMember.ts

@ -1,33 +1,35 @@
import { defineStore } from 'pinia'
import { ref} from 'vue';
import request from "@/utils/request";
import { id } from 'element-plus/es/locale';
export const useOrgMemberStore = defineStore('orgMember', () => {
interface OrgMemberItem {
id: string;
label: string;
children?:OrgMemberItem[];
name: string;
child?:OrgMemberItem[];
}
const listMap = ref<Record<string, string>>({})
const dataTree = ref<OrgMemberItem>({ id: '', label: '', children: [] })
const dataTree = ref<OrgMemberItem>({ id: '', name: '', child: [] })
async function init() {
await request({
url: "/javasys/lowCode/transfer/getOrgAndManTree",
url: "/systemapi/app/get_org_everyone_people",//"172.20.2.87:39168",
method: "post",
data:{id:"313",all: 1}
}).then((response) => {
// assuming response.data is an array of OrgMemberItem
dataTree.value=response.data
handleChildren(response.data.children)
dataTree.value={id:"313",name:"集团公司",child:response.data}
handleChildren(response.data)
});
}
function handleChildren(childs:any[]){
childs.forEach(item => {
listMap.value[item.id] = item.label;
if(item.children){
handleChildren(item.children)
listMap.value[item.id] = item.name;
if(item.child){
handleChildren(item.child)
}
});
}

118
src/views/doc/agent.vue

@ -26,7 +26,7 @@ const inputState=ref(true)
const conversations=ref<chatRecord[]>([])
const centHoverItem=ref("")
const interact_msg=ref<{ask:boolean,think:string,content:string}[]>([])
const interact_msg=ref<{ask:boolean,think:string,content:string,docinfo?:any[]}[]>([])
const props = withDefaults(defineProps<{
userid:string,
closefunc:()=>void,
@ -75,7 +75,7 @@ async function onSendTextToAI(){
}else{
interact_msg.value.push({ask:true,think:"", content:myquestion.value})
}
let docinfo:any=[]
controller.value = new AbortController();
try{
const res= await doAiChat(`${baseURL}/aibot/agents/${props.agent.uuid}/chat`,{
@ -98,7 +98,6 @@ async function onSendTextToAI(){
let chunk = ''; //
while (true) {
const {done, value} = await reader.read()
if (done) break;
//
chunk += decoder.decode(value, {stream: true});
@ -112,9 +111,13 @@ async function onSendTextToAI(){
if(json.event==="message"){
conversation.value=json.conversation_id
respMsg.value+=json.answer
}else if(json.event==="message_end"){
docinfo=json.metadata.retriever_resources
}
}
}
if (done) break;//
}
}catch (e: any) {
if (e.name === 'AbortError') {
@ -126,14 +129,13 @@ async function onSendTextToAI(){
const arr=respMsg.value.split("</think>")
if(arr.length===1){
interact_msg.value.push({ask:false,think:"",content:arr[0]})
interact_msg.value.push({ask:false,think:"",content:arr[0],docinfo:docinfo})
}else{
//
interact_msg.value.push({ask:false,think:arr[0],content:arr[1]})
interact_msg.value.push({ask:false,think:arr[0],content:arr[1],docinfo:docinfo})
}
respMsg.value=""
setAiChat({
"userid":atob(props.userid),
"uuid":conversation.value,
@ -180,6 +182,16 @@ function handleMouseLeave(){
}
function newContext(){
const c =conversations.value.find(c=>c.uuid==conversation.value)
if(!c){
conversations.value.push({
"agentuuid":props.agent.uuid,
"uuid":conversation.value,
"brief":interact_msg.value[0].content,
"messages":interact_msg.value
})
}
inputState.value=true
interact_msg.value=[]
conversation.value=""
@ -192,6 +204,13 @@ function resetContext(){
props.closefunc()
}
//ai
function formatRefContent(content:string){
let result=content.replaceAll(/"/g,'')
result=result.replaceAll(/Unnamed: /g,' ')
return result
}
//
onMounted(() => {
loadKnownLibList()
@ -212,7 +231,8 @@ onMounted(() => {
<li class="action_menu" @click="newContext">
新建会话
</li>
<li class="list_item" v-for="item in conversations" @mouseover="handleMouseEnter(item)" @mouseleave="handleMouseLeave()" @click="showChat(item.uuid)">{{ item.brief }}
<li class="list_item" v-for="item in conversations" @mouseover="handleMouseEnter(item)" @mouseleave="handleMouseLeave()" @click="showChat(item.uuid)">
<span>{{ item.brief }}</span>
<el-button v-show="centHoverItem == item.uuid" icon="Delete" size="small" circle @click="(e)=>{e.stopPropagation();onDelChat(item.uuid)}"></el-button>
</li>
</ul>
@ -224,6 +244,15 @@ onMounted(() => {
<div v-else class="t_resp">
<el-text style="white-space: pre-line" v-html="msg.think"></el-text>
<VueMarkdown :markdown="msg.content" :rehype-plugins="[rehypeRaw]" :remark-plugins="[remarkGfm]" ></VueMarkdown>
<div v-if="msg.docinfo?.length>0" class="doc_ref">
引用<hr>
<el-tooltip v-for="doc in msg.docinfo" placement="top" effect="dark">
<template #content>
<div v-html="formatRefContent(doc.content)" />
</template>
<span>{{doc.document_name}}</span>
</el-tooltip>
</div>
</div>
</template>
@ -306,14 +335,38 @@ onMounted(() => {
background-color: #dddddd;
padding: 10px 8px;
margin: 3px 14px 3px 0;
border-radius: 8px;
span{
width: 90%;
overflow: hidden;
text-overflow: ellipsis;
border-radius: 8px;
text-wrap-mode: nowrap;
}
button{
margin-left: auto;
}
}
.doc_ref{
margin: 16px;
display: flex;
flex-wrap: wrap;
hr{
width: 90%;
margin: inherit;
border: none;
border-top: .5px solid rgb(26 25 25 / 23%);
}
span{
width: 300px;
overflow: hidden;
text-overflow: ellipsis;
text-wrap-mode: nowrap;
margin: 2px 10px;
padding: 0 10px;
background-color: #d7d5d5;
border-radius: 6px;
}
}
</style>
<style>
@ -322,4 +375,53 @@ onMounted(() => {
margin-bottom: 8px;
display: block;
}
.t_resp{
h2,h3,h4,h5{
margin: 12px 0;
}
p{
margin-left: 16px;
}
p+ul{
margin-left: 56px;
}
li p{
margin-left: 0;
}
ol{
margin-left: 14px;
ul{
margin-left: 30px;
li{
list-style: disc;
}
}
}
ol>li{
list-style-type: decimal;
}
ul{
margin-left: 30px;
list-style: disc;
ul{
margin-left: 30px;
}
}
table{
border: 0px solid;
border-spacing: 1px;
border-collapse: collapse;
th{
background-color: #e5e5e5;
border: 1px solid;
min-width: 180px;
}
td{
border: 1px solid;
min-width: 180px;
}
}
}
</style>

48
src/views/doc/manage.vue

@ -22,7 +22,7 @@ import preview from './preview.vue';
import space from './space.vue';
import spacePermission from './spacePermission.vue';
import SvgIcon from "@/components/SvgIcon/index.vue";
import {doDelSpace} from "@/api/doc/space"
import {doDelSpace,doAccessManage} from "@/api/doc/space"
import Space from "./space.vue";
//TODO: add file icons done!
@ -254,10 +254,12 @@ function onMatterRename(row:matterInfo){
},
}),
}).then(() => {
if(newname.value&&newname.value!=""){
postMatterRename(uid,{
uuid:row.uuid,
name:newname.value,
}).then(()=>onLoadMatterList())
}
})
}
@ -658,6 +660,31 @@ function flushSpaceTree(uuid:string,data:matterTree[]){
spaceTreeRef.value.updateKeyChildren(uuid,data)
}
//
function onAccessManage(){
dynamicVNode.value = h(sharePermission, {
uid: uid,
uuid: "",
spaceid:SpaceID.value.uuid, //
confirmFunc: (_list: string[],_infos:string[]) => {
//
//_len=_list.length
let permited = btoa(_list.join("|"))
doAccessManage(uid,{
"space":SpaceID.value.uuid,
"roles":permited,
"owner":SpaceID.value.userUuid,
"len":_list.length
}).then(()=>{
})
},
closeFunc: () => {
dynamicVNode.value=null
}
})
}
//
function onDeleteSpace(row:matterInfo){
ElMessageBox.confirm(`确认删除空间 ( ${row.name}) ? 空间内所有文件将不可恢复!取消则放弃删除操作。`, "警告", {
@ -763,6 +790,7 @@ const handleSelectionChange = (val:matterInfo[]) => {
<el-button size="small" :icon="Setting" circle ></el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="(e)=>{ e.stopPropagation(); onAccessManage(data)}">空间成员管理</el-dropdown-item>
<el-dropdown-item @click="(e)=>{ e.stopPropagation(); onDelSpaceMatter(data)}">删除</el-dropdown-item>
<el-dropdown-item @click="(e)=>{ e.stopPropagation(); onSpacePManage(data)}">权限管理</el-dropdown-item>
</el-dropdown-menu>
@ -815,7 +843,7 @@ const handleSelectionChange = (val:matterInfo[]) => {
</el-button-group>
</el-row>
<el-row :gutter="24" style="overflow-y: auto;">
<el-row :gutter="24" style="overflow-y: auto; height: 90%;">
<el-table v-if="modListOrGrild"
stripe
:data="matterList"
@ -839,7 +867,7 @@ const handleSelectionChange = (val:matterInfo[]) => {
</div>
</template>
</el-table-column>
<el-table-column width="250" align="center">
<el-table-column width="360" align="center">
<template #default="scope">
<div v-show="currentHoverRow === scope.row.name">
<!-- <el-button size="small" :icon="Promotion" circle ></el-button> -->
@ -848,6 +876,7 @@ const handleSelectionChange = (val:matterInfo[]) => {
<el-button size="small" :icon="Download" circle @click="onDownload(scope.row)"></el-button>
<el-button size="small" :icon="Edit" circle @click="onlyOfficeEdit(scope.row)"></el-button>
<el-button size="small" :icon="Delete" circle @click="onDelMatter(scope.row)"></el-button>
<el-button size="small" circle @click="onMatterRename(scope.row)"></el-button>
</div>
</template>
</el-table-column>
@ -876,10 +905,11 @@ const handleSelectionChange = (val:matterInfo[]) => {
</div>
<ul v-if="row.name!=''" class="grid-menus" v-show="currentHoverRow === row.name" @mouseleave="currentHoverRow=''">
<li v-if="getFileIcon(row.name)!='img'" @click="onPrivateView(row)">预览</li>
<li size="small" :icon="Share" @click="onShareMatter(row)">分享</li>
<li size="small" :icon="Download" @click="onDownload(row)">下载</li>
<li size="small" :icon="Edit" @click="onlyOfficeEdit(row)">编辑</li>
<li size="small" :icon="Delete" @click="onDelMatter(row)">删除</li>
<li @click="onShareMatter(row)">分享</li>
<li @click="onDownload(row)">下载</li>
<li @click="onlyOfficeEdit(row)">编辑</li>
<li @click="onDelMatter(row)">删除</li>
<li @click="onMatterRename(row)">重命名</li>
</ul>
</div>
</div>
@ -976,12 +1006,13 @@ const handleSelectionChange = (val:matterInfo[]) => {
.table-grid{
display: flex;
flex-wrap: wrap; /* 关键属性,允许子元素自动换行 */
align-content: flex-start;
.grid-item{
position: relative;
width: 134px;
height: 145px;
margin: 5px;
.grid-box{
height: 150px;
display: flex;
flex-direction: column;
overflow: hidden;
@ -997,6 +1028,7 @@ const handleSelectionChange = (val:matterInfo[]) => {
line-height: 27px;
text-align: center;
color: #878989;
z-index: 90;
box-shadow:0px 0px 12px rgba(0,0,0,0.12);
li{
cursor: pointer;

4
src/views/doc/onlyoffice.vue

@ -53,8 +53,8 @@ onMounted(()=>{
const _url=decodeURIComponent(window.atob(query.fileurl))
const name=query.name?.toString()??""
const dtype=query.dtype?.toString()??"word"
//
if (_info.includes(name)){
config.value.document.url=_url
config.value.document.title=name
const _key=_url.match(/(\w+-\w+-\w+)/)![0]
@ -68,7 +68,7 @@ onMounted(()=>{
if(_verify.endsWith("true") && _key.includes(_verify.replace("true",""))){
config.value.editorConfig.mode="edit"
}
}
}
})

4
src/views/doc/recentVisited.vue

@ -24,9 +24,9 @@ const props = withDefaults(defineProps<{
function onlyOfficeView(row:shareItem){
const _type=fileType(row.name!)
if(_type!==""){ //office file
const info =btoa(encodeURIComponent(`${row.userUuid}/root${row.matters[0].path}`))
const info =btoa(encodeURIComponent(`${row.name}`))
const _url=`${siteHost}${apiURL}/share/zip?shareUuid=${row.uuid}&code=${row.code}&uid=${props.uid}&dprt=${props.udprt}&puuid=root&rootUuid=root`
window.open(`/#/onlyoffice?name=${row.name}&dtype=${_type}&info=${info}&fileurl=`+encodeURIComponent(_url),"_blank")
window.open(`/#/onlyoffice?name=${row.name}&dtype=${_type}&info=${info}&fileurl=`+window.btoa(encodeURIComponent(_url)),"_blank")
}else{
//by kkFilePreview
let a = row.name ?? '';

111
src/views/doc/space.vue

@ -9,16 +9,16 @@ import sharePermission from './sharePermission.vue';
import spacePermission from './spacePermission.vue';
import { matterPage,matterInfo,matterTree,doFileUpload,matterPermit} from "@/api/doc/type"
import { doAccessManage,getSpaceMatterList,doCreateSpaceDir,doDelSpaceMatter,
doAiTraining ,doCreateAiagent} from "@/api/doc/space"
doAiTraining ,doCreateAiagent,spaceMatterRename} from "@/api/doc/space"
import { h } from 'vue'
import {
Delete,
View,
Download,
Plus,
Plus,Search,
Edit,
Setting,
Promotion,
Grid,List,
} from '@element-plus/icons-vue'
import {ElMessage,UploadFile,UploadFiles,ElPagination} from "element-plus";
import aiagent from './agent.vue';
@ -29,6 +29,7 @@ const orgMembers = useOrgMemberStore() //为了初始化
const defaultAiAgent=import.meta.env.VITE_DEFAULT_AI_AGENT
const matterList = ref<matterInfo[]>([])
const searchname=ref("") //
const newdirName=ref("") //
const currentHoverRow=ref("") //table
const breadcrumbList=ref<matterInfo[]>([{name:"根目录",uuid:"root", dir:true}]) //
@ -41,6 +42,7 @@ const dynamicVNode = ref<VNode | null>(null) //permission 组件的父组件
const paginInfo = ref({ page: 0, total: 0 })
const CutLevelPermit=ref(0)
const modListOrGrild=ref(true) //
enum PERMITS {
FORBID, //0
VIEW, //1
@ -88,8 +90,18 @@ const uploadFormData = computed(() => {
}
});
function updateListOrGrid(val:boolean){
modListOrGrild.value=val
if(val){
localStorage.setItem("listOrGrid","true")
}else{
localStorage.setItem("listOrGrid","false")
}
}
//--------------&-------------
function onAccessManage(){
//manage
dynamicVNode.value = h(sharePermission, {
uid: props.uid,
uuid: "",
@ -159,10 +171,9 @@ function onDownload(row:matterInfo){
})
}
//
function onLoadMatterList(){
let _page: matterPage = {
function onLoadMatterList(name?:string){
let _page: matterPage= {
page: paginInfo.value.page,
pageSize: 50,
orderCreateTime: "DESC",
@ -172,6 +183,18 @@ function onLoadMatterList(){
space:props.spaceid,
};
if(name){
_page={
pageSize: 50,
orderCreateTime: "DESC",
orderDir: "DESC",
deleted:false,
name:name,
space:props.spaceid,
}
}
getSpaceMatterList(props.uid,_page).then((resp)=>{
//page+1 index1apiindex0
paginInfo.value={total:resp.data.totalPages, page:resp.data.page}
@ -251,6 +274,31 @@ function onCreateDir(){
})
}
//
function onMatterRename(row:matterInfo){
const newname=ref(row.name)
ElMessageBox({
title:"请输入新的文件名",
confirmButtonText: "确定",
cancelButtonText: "取消",
message: () => h(ElInput, {
style: { width:'360px' },
modelValue: newname.value,
'onUpdate:modelValue': (val) => {
newname.value = val
},
}),
}).then(() => {
if(newname.value&&newname.value!=""){
spaceMatterRename(props.uid,{
space:props.spaceid,
uuid:row.uuid,
name:newname.value,
}).then(()=>onLoadMatterList())
}
})
}
//------------------------------------------
// @cell-dblclick="handleDoubleClick"
//
@ -445,7 +493,11 @@ function handleAiUpload(info:matterInfo){
//
if (info.path?.startsWith(currentAgent.value.path)){
doAiTraining(`/agents/${currentAgent.value.uuid}/updates`,{"matter":info.uuid}).then(resp=>{
console.log(resp)
ElMessage({
message: '已成功安排训练',
type: 'success',
plain: true,
})
})
}else{
alert("当前路径没有智能体")
@ -508,6 +560,13 @@ onMounted(() => {
//AI
currentAgent.value={name:"通用AI",model:false,uuid:defaultAiAgent,path:"root"}
let val =localStorage.getItem("listOrGrid")
if(val&&val=="false"){
modListOrGrild.value=false
}else{
modListOrGrild.value=true
}
if (props.ismanager) {
CutLevelPermit.value=PERMITS.MANAGER
}else{
@ -537,7 +596,6 @@ function isOwner(){
</script>
<template>
<div>
<el-row :gutter="24" style="margin: 12px 0px;">
<span class="el-breadcrumb" style="font-weight: bold; align-content: center;">[ {{ props.spacename }} ] : </span>
<el-breadcrumb separator="/" style="align-content: center;">
@ -547,6 +605,11 @@ function isOwner(){
</el-breadcrumb-item>
</el-breadcrumb>
<span v-if="currentNode.uuid!='root'" style="font-weight: bold;margin:0 5px;align-content:center;">/ {{ currentNode.name }}</span>
<el-col :span="6" class="search">
<el-input placeholder="搜索文件" v-model="searchname" @blur="searchname===''?onLoadMatterList():''"/>
<el-button :icon="Search" @click="onLoadMatterList(searchname)"></el-button>
</el-col>
</el-row>
<el-row :gutter="24">
@ -568,15 +631,18 @@ function isOwner(){
<el-button @click="createDir">新建目录</el-button>
</el-col>
<el-button style="margin-left: auto;" @click="()=>currentAgent.model=true">AI助手</el-button>
<el-button-group v-if="isOwner()" class="control" style="margin: 0 10px;">
<el-button :icon="Plus" @click="onAccessManage">成员</el-button>
<el-button :icon="Plus" @click="onAiAgent">创建智能体</el-button>
<!-- <el-button :icon="Delete" @click="onDeleteSpace">删除</el-button> -->
</el-button-group>
<el-button-group style="margin-right:20px;">
<el-button :icon="List" @click="updateListOrGrid(true)"></el-button>
<el-button :icon="Grid" @click="updateListOrGrid(false)"></el-button>
</el-button-group>
</el-row>
<el-row :gutter="24" style="height: 84%;overflow-y: auto;">
<el-table v-if="listOrGrid"
<el-row :gutter="24" style="overflow-y: auto;height: 90%;">
<el-table v-if="modListOrGrild"
stripe
:data="matterList"
:header-cell-style="{ background: '#f5f8fd' }"
@ -603,12 +669,15 @@ function isOwner(){
<div v-show="currentHoverRow === scope.row.name" style="display:inline; margin-left:15px">
<el-button v-if="getFileIcon(scope.row.name)!='img'" size="small" :icon="View" circle @click="onPrivateView(scope.row)"></el-button>
<el-button v-if="scope.row.permitVal>=PERMITS.DOWNLOAD" size="small" :icon="Download" circle @click="onDownload(scope.row)"></el-button>
<el-button v-if="scope.row.permitVal>=PERMITS.EDIT" size="small" :icon="Edit" circle @click="onlyOfficeEdit(scope.row)"></el-button>
<span v-if="scope.row.permitVal>=PERMITS.MANAGER" class="manager_span" >
<el-button v-if="!scope.row.dir" size="small" circle @click="handleAiUpload(scope.row)">AI</el-button>
<el-button size="small" :icon="Delete" circle @click="onDelMatter(scope.row)"></el-button>
<el-button size="small" :icon="Setting" circle @click="onSpacePManage(scope.row)"></el-button>
</span>
<span v-if="scope.row.permitVal>=PERMITS.EDIT" class="manager_span">
<el-button size="small" :icon="Edit" circle @click="onlyOfficeEdit(scope.row)"></el-button>
<el-button size="small" circle @click="onMatterRename(scope.row)"></el-button>
</span>
</div>
</template>
</el-table-column>
@ -640,7 +709,10 @@ function isOwner(){
<ul v-if="row.name!=''" class="grid-menus" v-show="currentHoverRow === row.name" @mouseleave="currentHoverRow=''">
<li v-if="getFileIcon(row.name)!='img'" @click="onPrivateView(row)">预览</li>
<li v-if="row.permitVal! >= PERMITS.DOWNLOAD" @click="onDownload(row)">下载</li>
<li v-if="row.permitVal! >= PERMITS.EDIT" @click="onlyOfficeEdit(row)">编辑</li>
<span v-if="row.permitVal! >= PERMITS.EDIT" >
<li @click="onlyOfficeEdit(row)">编辑</li>
<li @click="onMatterRename(row)">重命名</li>
</span>
<span v-if="row.permitVal! >= PERMITS.MANAGER" >
<li @click="onDelMatter(row)">删除</li>
<li @click="onSpacePManage(row)">权限</li>
@ -653,7 +725,6 @@ function isOwner(){
<el-row v-if="paginInfo.total>1" style="justify-content: center;">
<el-pagination size="small" background layout="prev, pager, next" :current-page="paginInfo.page+1" @current-change="(value:number)=>{paginInfo.page=value-1;onLoadMatterList();}" :page-count="paginInfo.total" class="mt-4"/>
</el-row>
</div>
<aiagent :agent="currentAgent" :userid="uid" :uuid="currentAgent" :closefunc="()=>{currentAgent.model=false}"></aiagent>
@ -671,16 +742,22 @@ function isOwner(){
align-self: flex-start;
}
}
.search{
margin-left: auto;
margin-right: 20px;
display:inherit;
}
.table-grid{
display: flex;
flex-wrap: wrap; /* 关键属性,允许子元素自动换行 */
align-content: flex-start;
.grid-item{
position: relative;
width: 134px;
height: 135px;
margin: 5px;
.grid-box{
height: 150px;
display: flex;
flex-direction: column;
overflow: hidden;
@ -696,7 +773,7 @@ function isOwner(){
line-height: 27px;
text-align: center;
color: #878989;
z-index: 999;
z-index: 90;
box-shadow:0px 0px 12px rgba(0,0,0,0.12);
li{
cursor: pointer;

95
src/views/doc/spacePermission.vue

@ -8,6 +8,7 @@ import {
import { ElDialog, ElMessageBox,ElStep,TreeInstance} from 'element-plus';
import { useOrgMemberStore } from "@/store/modules/orgMember";
import { dataTool } from 'echarts';
const props = withDefaults(defineProps<{
uid:string, //uuid
uuid:string, //uuid
@ -21,16 +22,17 @@ const spacePermit=ref<{id:number,data:string,matterUid:string}>({}) //权限
const treeRef=ref<TreeInstance>() //tree
const managerMode=ref(false)
const managers=ref<string[]>([])
const firstLevelKeys = ref<string[]>([]) //
let resultPermits: Record<string, number> = {};
interface Tree {
id: string
label:string
parentId?:string
name:string
superior?:string
indeterminate?:boolean,
radio?:number[];
children?: Tree[]
child?: Tree[]
ismanager?:boolean,
}
@ -48,7 +50,7 @@ async function onSavePermChange(){
managers.value.push("p0"+item.id)
}
if(item.children) collectManager(item)
if(item.child) collectManager(item)
})
await addSpaceManager(btoa(props.uid),{
@ -69,7 +71,7 @@ async function onSavePermChange(){
resultPermits[item.id]=item.radio[0]
}
if(item.children) collectNodePermits(item)
if(item.child) collectNodePermits(item)
})
spacePermit.value.data=JSON.stringify(resultPermits)
@ -85,18 +87,18 @@ async function onSavePermChange(){
}
function collectManager(node:Tree){
node.children?.forEach(ele => {
node.child?.forEach(ele => {
if(ele.ismanager){
managers.value.push("p0"+ele.id)
}
if(ele.children) collectManager(ele)
if(ele.child) collectManager(ele)
});
}
//
function collectNodePermits(node:Tree){
node.children?.forEach(ele => {
node.child?.forEach(ele => {
if(ele.radio&&ele.radio.length>0){
if(ele.indeterminate) {
ele.radio[0]+=10
@ -104,7 +106,7 @@ function collectNodePermits(node:Tree){
resultPermits[ele.id]=ele.radio[0]
}
if(ele.children){
if(ele.child){
collectNodePermits(ele)
}
});
@ -114,25 +116,25 @@ function collectNodePermits(node:Tree){
//
function onGroupValueChange(node:Tree, val:number[]){
if(node.indeterminate) node.indeterminate=false;
node.children?.forEach(ele => {
node.child?.forEach(ele => {
ele.radio=val
if(ele.children){
if(ele.child){
onGroupValueChange(ele,val)
}
});
if(node.parentId){
if(node.superior){
updateParentNode(node)
}
}
//
function updateParentNode(node:Tree){
if(node.parentId){
if(node.superior){
const pnode = treeRef.value?.getNode(node.parentId);
const pnode = treeRef.value?.getNode(node.superior);
if(pnode){
const tdata=pnode.data as Tree
if (tdata.children?.every(ele=>{
if (tdata.child?.every(ele=>{
if(ele.indeterminate) return !ele.indeterminate;//
if(ele.radio?.length==0) return ele.radio.length==tdata.radio?.length;
@ -165,10 +167,23 @@ function onShowManagers(){
const node = treeRef.value?.getNode(item.replace("p0",""));
if(node && node.data){
node.data.ismanager=true
setParentIndeterminate(node.data as Tree)
}
})
}
function setParentIndeterminate(node:Tree){
if(node.superior){
const pnode = treeRef.value?.getNode(node.superior);
if(pnode){
const tdata=pnode.data as Tree
tdata.indeterminate=true
setParentIndeterminate(tdata)
}
}
}
function refreshSpaceData(){
getSpaceMemberList(
btoa(props.uid),
@ -183,13 +198,17 @@ function refreshSpaceData(){
addNode(item,orgMembers.dataTree)
});
if(dataSource.value.length>0){//
firstLevelKeys.value.push(dataSource.value[0].id)
}
resp.data?.members?.forEach(item=>{
const mid=item.replace("p0","")
for(let data of dataSource.value){
if(checkNode(mid,data)) return;
}
dataSource.value.push({id:mid,label:orgMembers.listMap[mid],radio:[2]})
dataSource.value.push({id:mid,name:orgMembers.listMap[mid],radio:[]})
});
managers.value=resp.data?.managers.split("|")
@ -197,7 +216,6 @@ function refreshSpaceData(){
spacePermit.value.matterUid=resp.data?.permits.MatterUuid
spacePermit.value.data=resp.data.permits.data!="" ? resp.data.permits.data : "{}"
nextTick(() => {
const permitJson = JSON.parse(spacePermit.value.data) //object
Object.keys(permitJson).forEach(key=>{
@ -217,28 +235,28 @@ function refreshSpaceData(){
}
function addNode(key:string,node:Tree){
node.children?.forEach(ele => {
node.child?.forEach(ele => {
if(ele.id==key){
const eleClone=structuredClone(toRaw(ele)) //eleProxyclonetoRawobject
eleClone.radio=[2]
eleClone.parentId=ele.parentId
dataSource.value.push(eleClone) //{id:ele.id,label:ele.label,radio:2,stage:level,children:ele.children}
//eleClone.radio=[2]
eleClone.superior=ele.superior
dataSource.value.push(eleClone) //{id:ele.id,name:ele.name,radio:2,stage:level,children:ele.children}
return
}
if(ele.children){
if(ele.child){
addNode(key,ele)
}
});
}
function checkNode(key:string,node:Tree):boolean{
for (const child of node.children||[]) {
if(child.id==key){
for (const ch of node.child||[]) {
if(ch.id==key){
return true
}
if(child.children){
if(ch.child){
//returnreturnfortruereturn
if(checkNode(key,child)) return true;
if(checkNode(key,ch)) return true;
}
}
@ -266,11 +284,26 @@ onMounted(()=>{
<span>管理员</span>
</div>
<div v-else class="buttons">
<span>禁止</span>
<el-tooltip placement="top" effect="dark"
content="禁止访问">
<span>不可见</span>
</el-tooltip>
<el-tooltip placement="top" effect="dark"
content="仅可预览,不可下载">
<span>仅预览</span>
</el-tooltip>
<el-tooltip placement="top" effect="dark"
content="可下载可见文件,不可上传文件">
<span>可下载</span>
</el-tooltip>
<el-tooltip placement="top" effect="dark"
content="可上传和下载可见文件">
<span>上传下载</span>
</el-tooltip>
<el-tooltip placement="top" effect="dark"
content="可上传、下载、编辑文档">
<span>编辑</span>
</el-tooltip>
</div>
</div>
<div class="tablelist">
@ -278,15 +311,17 @@ onMounted(()=>{
ref="treeRef"
:data="dataSource"
node-key="id"
default-expand-all
accordion
:props="{label: 'name',children:'child'}"
:default-expanded-keys="firstLevelKeys"
:expand-on-click-node="false"
>
<template #default="{ node, data }">
<div class="tree-node">
<span>{{ node.label }}</span>
<span>{{ data.name }}</span>
<div v-if="managerMode" class="buttons">
<el-checkbox v-if="!data.children" v-model="data.ismanager" />
<el-checkbox v-model="data.ismanager" :indeterminate="data.indeterminate" />
</div>
<div v-else class="buttons">
<el-checkbox-group :min="0" :max="1" v-model="data.radio" @change="(val)=>onGroupValueChange(data,val)">

Loading…
Cancel
Save