Browse Source

支持文档分享权限控制

han_v2
han2015 6 months ago
parent
commit
540b20fa48
  1. 18
      src/api/doc/index.ts
  2. 2
      src/api/doc/type.ts
  3. 87
      src/api/hr/people/share_ctrol.ts
  4. 60
      src/views/doc/manage.vue
  5. 35
      src/views/doc/share.vue
  6. 146
      src/views/doc/sharePermission.vue

18
src/api/doc/index.ts

@ -17,7 +17,7 @@ export function getShareList( uid:string,data?: matterPage): AxiosPromise<matter
url: '/hxpan/api/share/page',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
@ -32,7 +32,7 @@ export function getShareBrowse( uid:string,data?: matterPage): AxiosPromise<resp
url: '/hxpan/api/share/browse',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
@ -47,7 +47,7 @@ export function postShareDelete( uid:string,data?: matterPage): AxiosPromise<res
url: '/hxpan/api/share/delete',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
@ -63,7 +63,7 @@ export function getMatterList( uid:string,data?: matterPage): AxiosPromise<matte
url: '/hxpan/api/matter/page',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
@ -77,7 +77,7 @@ export function postCreateDir(uid:string,data?: createDir){
url: '/hxpan/api/matter/create/directory',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
@ -92,7 +92,7 @@ export function postDelMatter(uid:string,data?: any){
url: '/hxpan/api/matter/delete',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
@ -106,7 +106,7 @@ export function postDelMatBatch(uid:string,data?: any){
url: '/hxpan/api/matter/delete/batch',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
@ -121,7 +121,7 @@ export function postCreateShare(uid:string,data?: createShare): AxiosPromise<res
url: '/hxpan/api/share/create',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
@ -136,7 +136,7 @@ export function postMatterRename(uid:string,data?: {uuid:string;name:string}){
url: '/hxpan/api/matter/rename',
method: 'post',
headers: {
'User-Id':uid,
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data

2
src/api/doc/type.ts

@ -49,6 +49,8 @@ export interface createShare{
matterUuids:string;
expireInfinity:boolean;
expireTime:string;
permitList:string
len:number
}
export interface respCreateShare{

87
src/api/hr/people/share_ctrol.ts

@ -0,0 +1,87 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
export interface shareOrgInfo{
id:number
name:string
superior:number
level:number
status:boolean
child :shareOrgInfo[]
}
/**
*
*/
export interface parsArchList extends PageQuery{
page:number,
pagesize:number
adminorg?:number; //行政组织
}
export interface memberInfo{
id:number,
name:string,
icon:string,
company:number,
maindeparment:number,
sunmaindeparment:number,
adminorg:number,
state:number,
keystr:string,
positionname :string,
}
export type shareArchivesList = PageResult<memberInfo[]>
/**
*
*/
export function getOrgTreeList(data: {orgid?:number}): AxiosPromise<shareOrgInfo[]>{
return request({
url: '/hrapi/org/govnewthreeing',
method: 'post',
data: data
});
}
/**
*
*/
export function getArchivesListPage(data?: parsArchList): AxiosPromise<shareArchivesList> {
return request({
url: '/hrapi/staff/archiveslistcont',
method: 'post',
data: data
});
}
/**
*
*/
export function getPermitedList(uid:string,data:{uuid:string}): AxiosPromise<string[]> {
return request({
url: '/hxpan/api/share/permits',
method: 'post',
headers: {
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
});
}
/**
*
*/
export function postPermitedList(uid:string,data?:{permitList:string, update:string,uid:string,uuid:string,len:number}){
return request({
url: '/hxpan/api/share/permits',
method: 'post',
headers: {
'Identifier':uid,
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
});
}

60
src/views/doc/manage.vue

@ -5,6 +5,7 @@
-->
<script lang="ts" setup>
import { getExpirTime, getFileIcon, readableSize} from "./tools"
import sharePermission from './sharePermission.vue';
import { useUserStore } from "@/store/modules/user";
import { getMatterList,postCreateDir,postDelMatter,postCreateShare,postMatterRename,postDelMatBatch} from "@/api/doc/index"
import { matterPage,matterInfo,respCreateShare,matterTree } from "@/api/doc/type"
@ -17,10 +18,10 @@ import {
Edit,
Promotion,
Folder,
Avatar
} from '@element-plus/icons-vue'
import {ElSelect,ElOption, ElText,ElInput,TableInstance,ElMessage,UploadFile,UploadFiles,ElPagination,ElTree,TreeInstance} from "element-plus";
import type { TreeNode } from 'element-plus/es/components/tree/src/tree.type'
import { number } from "echarts";
//TODO: add file icons done!
//TODO: click on table-item 1preview on file .....................
@ -36,7 +37,7 @@ import { number } from "echarts";
//TODO: test on Pagination done!
const userStore = useUserStore();
const uid="p0"+userStore.userInfoCont.userId;
const uid=btoa("p0"+userStore.userInfoCont.userId);
const siteHost=document.location.origin;
const apiURL=import.meta.env.VITE_APP_BASE_API+"/hxpan/api"
@ -66,17 +67,22 @@ const fileList=ref([])//upload files
//---------------------------
function onShareMatter(row?:matterInfo){
const showSharePermission=ref(false)
let permited =""
let _len=0
ElMessageBox({
title: row?.name+' 请选择分享有效时间',
message: () => h(ElSelect, {
defaultFirstOption:true,
modelValue: selectedValue.value,
'onUpdate:modelValue': (value) => {
selectedValue.value = value
},
valueKey: "value",
fallbackPlacements:['bottom-start'],
style: { width:'360px' }
message: () => h('div',{style:{ width:'660px'}},[
h(ElSelect,
{
defaultFirstOption:true,
modelValue: selectedValue.value,
'onUpdate:modelValue': (value) => {
selectedValue.value = value
},
valueKey: "value",
fallbackPlacements:['bottom-start'],
style: { width:'360px' }
},() => [
h(ElOption, { label: '六小时',key: 'sixhour', value: 'sixhour' }),
h(ElOption, { label: '一 天', key: 'oneday', value: 'oneday' }),
@ -86,13 +92,39 @@ function onShareMatter(row?:matterInfo){
h(ElOption, { label: '三 月', key: 'threemonth', value: 'threemonth' }),
h(ElOption, { label: '永 久', key: 'permanent', value: 'permanent' }),
]),
h(ElButton, {
style: "width:30px;margin:0 10px;",
icon: Avatar,
onClick: () => {
showSharePermission.value = true
}
}),
h(sharePermission, {
uid: uid,
uuid: row?.uuid ?? "",
modelValue: showSharePermission.value,
// "onUpdate:modelValue": (val: boolean) => {
// showSharePermission.value = val
// },
confirmFunc: (_list: string[]) => {
//
_len=_list.length
permited = btoa(_list.join("|"))
showSharePermission.value = false
},
closeFunc: () => {
showSharePermission.value = false
}
})
]
),
showCancelButton: true
}).then(() => {
let param;
if (row){
param={matterUuids:row.uuid,expireInfinity:false,expireTime:""}
param={matterUuids:row.uuid,expireInfinity:false,expireTime:"",permitList:permited,len:_len}
}else if (tabSelected.value.length>1){
param={matterUuids:tabSelected.value.map((item:matterInfo)=>item.uuid).join(","),expireInfinity:false,expireTime:""}
param={matterUuids:tabSelected.value.map((item:matterInfo)=>item.uuid).join(","),expireInfinity:false,expireTime:"",permitList:permited,len:_len}
}
if(param){
@ -101,7 +133,7 @@ function onShareMatter(row?:matterInfo){
}else{
param.expireTime=getExpirTime(selectedValue.value)
}
postCreateShare(uid,param).then((resp)=>{
showShareMessage(resp.data)
})

35
src/views/doc/share.vue

@ -15,13 +15,15 @@ import {
Delete,
Folder,
Share,
Avatar,
} from '@element-plus/icons-vue'
import {ElText } from "element-plus";
import {ElDialog, ElText } from "element-plus";
import { getExpirTime, getFileIcon,checkExpirTime } from "./tools"
import sharePermission from './sharePermission.vue';
const route = useRoute()
const userStore = useUserStore();
const uid="p0"+userStore.userInfoCont.userId;
const uid=btoa("p0"+userStore.userInfoCont.userId);
const siteHost=document.location.origin;
const apiURL=import.meta.env.VITE_APP_BASE_API+"/hxpan/api"
const matterList = ref<matterInfo[]>()
@ -29,6 +31,11 @@ const browerMode=ref(false) //share模式 1)self-list(default) 2)brower
const currentHoverRow=ref("")
import type { VNode } from 'vue'
const dynamicVNode = ref<VNode | null>(null)
function showShareMessage(row:{uuid:string,code:string,name:string,expireTime:string}){
let _shareURL=`${siteHost}/#/doc/share?uuid=${row.uuid}&code=${row.code}`
ElMessageBox({
@ -74,6 +81,17 @@ function onShareDelete(row:matterInfo){
}
}
//
function onShareMember(row:matterInfo){
dynamicVNode.value=h(sharePermission,{
uid:uid,
uuid:row.uuid,
closeFunc:()=>{
dynamicVNode.value=null
}
})
}
//
function onLoadShareList(){
let _page: matterPage = {
@ -89,7 +107,7 @@ function onLoadShareList(){
}
function handleMouseEnter(row:any){
currentHoverRow.value=row.name
currentHoverRow.value=row.uuid
}
onMounted(() => {
@ -99,8 +117,8 @@ onMounted(() => {
browerMode.value=true
getShareBrowse("",{shareUuid:query.uuid,code:query.code,puuid:'root',rootUuid:'root'}).then((resp)=>{
showShareMessage(resp.data)
return
})
return
}
browerMode.value=false
onLoadShareList()
@ -115,7 +133,7 @@ onMounted(() => {
:data="matterList"
:header-cell-style="{ background: '#f5f8fd' }"
style="width: 100%"
row-key="value"
row-key="uuid"
:row-style ="() => ({ height: '55px' })"
@cell-mouse-enter="handleMouseEnter">
<el-table-column style="width: 70%;" property="name" label="文件名">
@ -131,7 +149,8 @@ onMounted(() => {
</el-table-column>
<el-table-column width="250" align="center">
<template #default="scope">
<div v-show="currentHoverRow === scope.row.name">
<div v-show="currentHoverRow === scope.row.uuid">
<el-button size="small" :icon="Avatar" circle @click="onShareMember(scope.row)"></el-button>
<el-button size="small" :icon="Share" circle @click="showShareMessage(scope.row)"></el-button>
<el-button size="small" :icon="Delete" circle @click="onShareDelete(scope.row)"></el-button>
</div>
@ -146,7 +165,9 @@ onMounted(() => {
</el-table>
</el-row>
</div>
<div v-if="dynamicVNode">
<component :is="dynamicVNode" />
</div>
</template>
<style lang="scss" scoped>

146
src/views/doc/sharePermission.vue

@ -0,0 +1,146 @@
<script lang="ts" setup>
import {
getOrgTreeList,
getArchivesListPage,
shareOrgInfo,
memberInfo,
getPermitedList,
postPermitedList} from '@/api/hr/people/share_ctrol'
import { MessageBox } from '@element-plus/icons-vue/dist/types';
import { ElDialog, ElMessageBox,TableInstance } from 'element-plus';
const props = withDefaults(defineProps<{
uid:string, //uuid
uuid:string, //uuid
confirmFunc?:(data:string[])=>void, //
closeFunc:Function, //
}>(),{})
const treeData =ref<shareOrgInfo[]>([])
const members=ref<memberInfo[]>([])
const permited=new Set()
const tableMembersRef=ref<TableInstance>()
function onNodeClick(data:shareOrgInfo){
getArchivesListPage({adminorg:data.id, page:1,pagesize:13}).then(resp=>{
if(resp.data.count >200){
ElMessageBox.alert("人数超过200,请按部门分配权限")
return
}
members.value=resp.data.list
//
members.value.forEach(row => {
if (permited.has('p0'+row.keystr)) {
// row-key , :reserve-selection="true"
tableMembersRef.value!.toggleRowSelection(row)
}
})
})
}
function onSavePermChange(){
let _list = permited.keys().toArray().filter(val=>val!=='')
//
if(props.confirmFunc&&_list){
props.confirmFunc(_list)
props.closeFunc() //
return
}
//btoa base64
postPermitedList(props.uid,{
permitList: btoa(_list.join("|")),
update: "true",
uid: props.uid,
uuid: props.uuid,
len: _list.length
}).then(resp=>{
props.closeFunc()
}).catch(()=>{
ElMessageBox.alert("处理失败")
return
})
}
function onManualSelect(select:[],row:memberInfo){
if(permited.has('p0'+row.keystr)){ //
permited.delete('p0'+row.keystr)
}else{
permited.add('p0'+row.keystr) //
}
}
function onSelectionAll(news:memberInfo[]){
if(news.length>0){
news.forEach((item)=>{
permited.add('p0'+item.keystr)
})
}else{
news.forEach((item)=>{
permited.delete('p0'+item.keystr)
})
}
}
onMounted(()=>{
//uuiduuid should not null
if(props.uuid!==""){
getPermitedList(props.uid,{uuid:props.uuid}).then(resp=>{
resp.data?.forEach(item=>{
permited.add(item) //userUuids constitue the permited list
})
})
}
getOrgTreeList({}).then(resp=>{
treeData.value=resp.data
})
})
</script>
<template>
<el-dialog :model-value="true" :style="{'max-height': '650px'}" v-on:close="closeFunc()">
<template #header>
<span>权限管理</span>
</template>
<div style="display: grid;grid-template-columns:1fr 1fr;">
<div class="menus_tree">
<el-tree
ref="treeRef"
key="id"
:data="treeData"
node-key="uuid"
:style="{maxHeight:'500px','overflow-y': 'auto'}"
:props="{label: 'name',children:'child',isLeaf:'dir'}"
:default-expanded-keys="['root']"
@node-click="onNodeClick"
/>
</div>
<div class="tablelist">
<el-table ref="tableMembersRef"
:data="members"
row-key="keystr"
style="overflow-y: auto;height: 500px;"
@select="onManualSelect"
@select-all="onSelectionAll"
>
<el-table-column type="selection" :reserve-selection="true" width="30" />
<el-table-column property="name" label="成员"></el-table-column>
<el-table-column property="positionname" label="职位"></el-table-column>
</el-table>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeFunc()">取消</el-button>
<el-button type="primary" @click="onSavePermChange">保存</el-button>
</div>
</template>
</el-dialog>
</template>
Loading…
Cancel
Save