Browse Source

Merge branch 'han_v0'

han_v2
herenshan112 6 months ago
parent
commit
9263c4155c
  1. 1
      .env.development
  2. 1
      .env.production
  3. 1
      .env.staging
  4. 18
      src/api/doc/index.ts
  5. 3
      src/api/doc/type.ts
  6. 88
      src/api/hr/people/share_ctrol.ts
  7. 69
      src/views/doc/manage.vue
  8. 35
      src/views/doc/preview.vue
  9. 115
      src/views/doc/share.vue
  10. 156
      src/views/doc/sharePermission.vue

1
.env.development

@ -9,3 +9,4 @@ VITE_APP_BASE_API = '/dev-api'
VITE_APP_BASE_URL = 'http://myvuetest.net'
VITE_APP_TOKEN_KEY = 'offlineAccessSystemAppToken'
VITE_APP_SJZT_URL = 'http://172.20.5.86/prod-api'
VITE_OFFICE_HOST="http://192.168.56.101:8012"

1
.env.production

@ -5,3 +5,4 @@ VITE_APP_PORT = 17777
VITE_APP_BASE_API = ''
VITE_APP_TOKEN_KEY = 'onlineAccessSystemAppToken'
VITE_APP_SJZT_URL = 'http://120.224.6.6:29911/prod-api'
VITE_OFFICE_HOST='https://gyhlw.hxgk.group/kkpreview'

1
.env.staging

@ -4,3 +4,4 @@ NODE_ENV='staging'
VITE_APP_TITLE = '数通智联化工云平台'
VITE_APP_PORT = 3000
VITE_APP_BASE_API = '/prod--api'
VITE_OFFICE_HOST=''

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

3
src/api/doc/type.ts

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

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

@ -0,0 +1,88 @@
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,
maindeparmentname: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<{permited:string[],infos: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,permitInfos: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
});
}

69
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,16 +37,16 @@ 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"
const matterList = ref<matterInfo[]>([])
const searchname=ref("")
const newdir=ref("")
const currentHoverRow=ref("")
const selectedValue = ref("sixhour")
const tabSelected=ref<matterInfo[]>([])
const newdir=ref("") //
const currentHoverRow=ref("") //table
const selectedValue = ref("sixhour") //
const tabSelected=ref<matterInfo[]>([]) //table
//to support tree mode refactor
const treeData=ref<matterTree[]>([{name:'root',uuid:'root',children:[]}])
const treeRef = ref();
@ -66,17 +67,23 @@ const fileList=ref([])//upload files
//---------------------------
function onShareMatter(row?:matterInfo){
const showSharePermission=ref(false)
let permited =""
let infos=""
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 +93,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,
confirmFunc: (_list: string[],_infos:string[]) => {
//
_len=_list.length
permited = btoa(_list.join("|"))
infos=_infos.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,permitInfos:infos}
}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,permitInfos:infos}
}
if(param){
@ -101,7 +134,7 @@ function onShareMatter(row?:matterInfo){
}else{
param.expireTime=getExpirTime(selectedValue.value)
}
postCreateShare(uid,param).then((resp)=>{
showShareMessage(resp.data)
})

35
src/views/doc/preview.vue

@ -0,0 +1,35 @@
<script lang="ts" setup>
import { ElDialog } from 'element-plus';
const props = withDefaults(defineProps<{
url:string,
closeFunc:()=>void, //
}>(),{})
onMounted(()=>{})
</script>
<template>
<el-dialog :model-value="true" :style="{height: '90%',width:'90%'}" v-on:close="closeFunc()">
<template #default>
<iframe id="preivew" width="100%" height="100%" :src="props.url"></iframe>
</template>
</el-dialog>
</template>
<style>
/* dialog的body内容样式设置*/
.el-dialog__body{
height: 90%;
display: flex;
flex-direction: column;
align-items: center;
}
.el-dialog{
/* 让整个弹出窗口位置更高一些*/
--el-dialog-margin-top:7vh;
}
</style>

115
src/views/doc/share.vue

@ -15,18 +15,29 @@ import {
Delete,
Folder,
Share,
Avatar,
View,
} from '@element-plus/icons-vue'
import {ElText } from "element-plus";
import { getExpirTime, getFileIcon,checkExpirTime } from "./tools"
import {getFileIcon,checkExpirTime } from "./tools"
import sharePermission from './sharePermission.vue';
import preview from './preview.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[]>()
const officeHost=import.meta.env.VITE_OFFICE_HOST
const matterList = ref<matterInfo[]>() //
const browerMode=ref(false) //share 1)self-list(default) 2)brower
const currentHoverRow=ref("")
const currentHoverRow=ref("") //table
const drawerModel=ref(false) //
const permitListRef=ref("") //key
import type { VNode } from 'vue'
const dynamicVNode = ref<VNode | null>(null) //permission
function showShareMessage(row:{uuid:string,code:string,name:string,expireTime:string}){
@ -38,14 +49,23 @@ function showShareMessage(row:{uuid:string,code:string,name:string,expireTime:st
h(ElText,{style:{'align-self':'flex-start'}},()=>row.name),
h(ElText,{style:{'align-self':'flex-start'}},()=>"失效时间:"+row.expireTime),
h(ElText,{style:{'align-self':'flex-start'}},()=>"链接:"+_shareURL),
h(ElButton, {
type: 'primary',
style: { width: '20%' },
onClick: () => {
let _url=apiURL+`/share/zip?shareUuid=${row.uuid}&code=${row.code}&puuid=root&rootUuid=root`
window.open(_url)
}
},()=>'下载')
h('div',[
h(ElButton, {
type: 'primary',
style: { width: '100px' },
onClick: () => {
let _url=apiURL+`/share/zip?shareUuid=${row.uuid}&code=${row.code}&puuid=root&rootUuid=root`
window.open(_url)
}
},()=>'下载'),
h(ElButton, {
type: 'primary',
style: { width: '100px',margin:'0 10px' },
onClick: () => {
onShareView(row)
}
},()=>'预览')
])
]),
confirmButtonText: '复制分享链接',
showCancelButton: true
@ -74,6 +94,44 @@ function onShareDelete(row:matterInfo){
}
}
//
function onShareMember(row:matterInfo){
dynamicVNode.value=h(sharePermission,{
uid:uid,
uuid:row.uuid,
closeFunc:(refresh?:boolean)=>{
dynamicVNode.value=null
if (refresh) {
permitListRef.value=""
drawerModel.value=false
onLoadShareList()
}
}
})
}
//
function onShareView(row:matterInfo){
let a = row.name ?? '';
if(a.endsWith('...')){
a=`${row.uuid}-${row.code}.zip`
}
//
a=a.match("(\.[a-zA-Z]+)$")
if (a && a.length>0) {
a=`${row.uuid}-${row.code}${a[0]}`
}else{
a=`${row.uuid}${row.name}`
}
let _url=`${siteHost}${apiURL}/share/zip?shareUuid=${row.uuid}&code=${row.code}&uid=${uid}&puuid=root&rootUuid=root&fullfilename=${a}`
dynamicVNode.value=h(preview,{
url:`${officeHost}/onlinePreview?url=`+window.btoa(unescape(encodeURIComponent(_url))),
closeFunc:()=>dynamicVNode.value=null
})
}
//
function onLoadShareList(){
let _page: matterPage = {
@ -89,7 +147,7 @@ function onLoadShareList(){
}
function handleMouseEnter(row:any){
currentHoverRow.value=row.name
currentHoverRow.value=row.uuid
}
onMounted(() => {
@ -99,8 +157,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 +173,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 +189,9 @@ 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="()=>{drawerModel=true; permitListRef=scope.row.permitInfos}"></el-button>
<el-button size="small" :icon="View" circle @click="onShareView(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 +206,28 @@ onMounted(() => {
</el-table>
</el-row>
</div>
<el-drawer
v-model="drawerModel"
title="文档成员列表"
direction="rtl"
size="20%"
:style="{padding:'17px'}">
<template #header>
<span>文档成员列表</span>
<el-button style="width:30px;margin-right:20px;"
:icon=Avatar
@click="()=>onShareMember({uuid:currentHoverRow})">
</el-button>
</template>
<ul v-if="drawerModel &&permitListRef!=''" style="line-height: 26px;">
<li class="el-text" v-for="item in permitListRef.split('|')"> {{ item }}</li>
</ul>
<span v-else-if="permitListRef==''"> 所有人员都可访问</span>
</el-drawer>
<div v-if="dynamicVNode">
<component :is="dynamicVNode" />
</div>
</template>
<style lang="scss" scoped>

156
src/views/doc/sharePermission.vue

@ -0,0 +1,156 @@
<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[],infos:string[])=>void, //
closeFunc:(refresh?:boolean)=>void, //
}>(),{})
const treeData =ref<shareOrgInfo[]>([]) //
const members=ref<memberInfo[]>([]) //tablelist's data
const permited=new Set<string>() //id
const permitedInfos=new Set<string>() //
const tableMembersRef=ref<TableInstance>() //table
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!=='') //key
let _infos = permitedInfos.keys().toArray().filter(val=>val!=='') //
//
if(props.confirmFunc&&_list){
props.confirmFunc(_list,_infos)
props.closeFunc() //
return
}
//btoa base64
postPermitedList(props.uid,{
permitList: btoa(_list.join("|")),
permitInfos:_infos.join("|"),
update: "true",
uid: props.uid,
uuid: props.uuid,
len: _list.length
}).then(resp=>{
props.closeFunc(true)
}).catch(()=>{
ElMessageBox.alert("处理失败")
return
})
}
function onManualSelect(select:[],row:memberInfo){
if(permited.has('p0'+row.keystr)){ //
permited.delete('p0'+row.keystr)
permitedInfos.delete(`${row.name}-${row.maindeparmentname}-${row.positionname}`)
}else{
permited.add('p0'+row.keystr) //
permitedInfos.add(`${row.name}-${row.maindeparmentname}-${row.positionname}`)
}
}
function onSelectionAll(news:memberInfo[]){
if(news.length>0){
news.forEach((item)=>{
permited.add('p0'+item.keystr)
permitedInfos.add(`${item.name}-${item.maindeparmentname}-${item.positionname}`)
})
}else{
news.forEach((item)=>{
permited.delete('p0'+item.keystr)
permitedInfos.delete(`${item.name}-${item.maindeparmentname}-${item.positionname}`)
})
}
}
onMounted(()=>{
//uuiduuid should not null
if(props.uuid!==""){
getPermitedList(props.uid,{uuid:props.uuid}).then(resp=>{
resp.data?.permited?.forEach(item=>{
permited.add(item) //userUuids constitue the permited list
})
resp.data?.infos?.forEach(item=>{
permitedInfos.add(item)
})
})
}
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="row => row.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