|
@@ -1,7 +1,9 @@
|
|
|
<script setup>
|
|
|
-import { onMounted, ref, getCurrentInstance } from 'vue'
|
|
|
+import { onMounted, ref, getCurrentInstance, watch } from 'vue'
|
|
|
import Search from '@/components/icon/search.vue'
|
|
|
import Warning from '@/components/icon/warning.vue'
|
|
|
+import Close from '@/components/icon/close.vue'
|
|
|
+import Empty from '@/components/icon/empty.vue'
|
|
|
import { get, downLoad, post } from '../../../utils/request'
|
|
|
import { productListNameMapping } from '../../../utils/mapping'
|
|
|
|
|
@@ -14,48 +16,134 @@ const queryString = ref('')
|
|
|
const dialogVisible = ref(false)
|
|
|
const MemberName = ref('')
|
|
|
const total = ref(0)
|
|
|
+const directoryTotal = ref(0)
|
|
|
+const deleteDirectoryTotal = ref(0)
|
|
|
const teamId = ref('')
|
|
|
const status = ref('')
|
|
|
+const directoryStatus = ref('')
|
|
|
const product = ref('')
|
|
|
const size = ref(5)
|
|
|
const memberId = ref('')
|
|
|
+const tag = ref('invited')
|
|
|
+const tagSecond = ref('all')
|
|
|
+const userList = ref([])
|
|
|
+const directoryEmail = ref('')
|
|
|
+const directoryMemberId = ref('')
|
|
|
+const deleteList = ref([])
|
|
|
+const domainList = ref([])
|
|
|
+const directoryData = ref([])
|
|
|
+const deleteDirectoryData = ref([])
|
|
|
+const directoryId = ref('')
|
|
|
+const revokeDialogVisible = ref(false)
|
|
|
+const deleteDialogVisible = ref(false)
|
|
|
+const restoreDialogVisible = ref(false)
|
|
|
+const loading = ref(true)
|
|
|
+const multipleTable = ref()
|
|
|
let click = true
|
|
|
|
|
|
-//打开删除对话框
|
|
|
+onMounted(() => {
|
|
|
+ let pageText = document.getElementsByClassName('el-pagination__jump')[0]
|
|
|
+ if (pageText) {
|
|
|
+ pageText.childNodes[0].nodeValue = 'Jump to Page'
|
|
|
+ }
|
|
|
+ getManageMemberList()
|
|
|
+ getTeamList()
|
|
|
+ getProductList()
|
|
|
+ getDomainList()
|
|
|
+})
|
|
|
+// 获取域列表
|
|
|
+const getDomainList = async () => {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const { data } = await get('/pdf-tech/domain/list')
|
|
|
+ data.result.forEach(item => {
|
|
|
+ if (Number(item.verified)) {
|
|
|
+ domainList.value.push(item)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+}
|
|
|
+// 获取目录用户列表
|
|
|
+const getDirectoryUser = async () => {
|
|
|
+ const { data } = await get('/pdf-tech/vppRTeamMemberRole/pageForSSOMember?page=' +
|
|
|
+ currentPage.value +
|
|
|
+ '&pageSize=' +
|
|
|
+ size.value +
|
|
|
+ '&status=' +
|
|
|
+ directoryStatus.value +
|
|
|
+ '&queryString=' +
|
|
|
+ queryString.value +
|
|
|
+ '&directoryId=' +
|
|
|
+ directoryId.value)
|
|
|
+ loading.value = false
|
|
|
+ directoryData.value = data.result.list
|
|
|
+ directoryTotal.value = data.result.total
|
|
|
+}
|
|
|
+// 获取删除目录用户列表
|
|
|
+const getDeleteDirectoryUser = async () => {
|
|
|
+ const { data } = await get('/pdf-tech/vppRTeamMemberRole/pageForSSOMember?page=' +
|
|
|
+ currentPage.value +
|
|
|
+ '&pageSize=' +
|
|
|
+ size.value +
|
|
|
+ '&status=0' +
|
|
|
+ '&queryString=' +
|
|
|
+ queryString.value +
|
|
|
+ '&directoryId=' +
|
|
|
+ directoryId.value)
|
|
|
+ loading.value = false
|
|
|
+ deleteDirectoryData.value = data.result.list
|
|
|
+ deleteDirectoryTotal.value = data.result.total
|
|
|
+}
|
|
|
+// 打开删除对话框
|
|
|
const handleClick = (val) => {
|
|
|
dialogVisible.value = true
|
|
|
MemberName.value = val.email
|
|
|
memberId.value = val.id
|
|
|
}
|
|
|
-//确认删除
|
|
|
-function deleteMember(){
|
|
|
- if(!click){return}
|
|
|
+// 确认删除
|
|
|
+const deleteMember = (val) => {
|
|
|
+ if (!click) {
|
|
|
+ return
|
|
|
+ }
|
|
|
click = false
|
|
|
setTimeout(() => {
|
|
|
click = true
|
|
|
}, 2000)
|
|
|
var urlencoded = new URLSearchParams()
|
|
|
- urlencoded.append("memberId", memberId.value)
|
|
|
- post("/pdf-tech/vppTeam/deleteMember",urlencoded).then((res)=>{
|
|
|
- if(res.data.code === 200){
|
|
|
+ urlencoded.append('memberId', memberId.value)
|
|
|
+ post('/pdf-tech/vppTeam/deleteMember', urlencoded).then((res) => {
|
|
|
+ if (res.data.code === 200) {
|
|
|
dialogVisible.value = false
|
|
|
proxy.$message({
|
|
|
- message: 'Delete Successfully',
|
|
|
- type: "success"
|
|
|
+ message: 'Delete Successfully',
|
|
|
+ type: 'success'
|
|
|
})
|
|
|
getManageMemberList()
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
-
|
|
|
-function handleSizeChange(val) {
|
|
|
+// 改变一页显示个数
|
|
|
+const handleSizeChange = (val) => {
|
|
|
size.value = val
|
|
|
currentPage.value = 1
|
|
|
- getManageMemberList()
|
|
|
+ if (tag.value === 'invited') {
|
|
|
+ getManageMemberList()
|
|
|
+ } else {
|
|
|
+ loading.value = true
|
|
|
+ getDirectoryUser()
|
|
|
+ }
|
|
|
}
|
|
|
-function handleCurrentChange(val) {
|
|
|
+// 切换页数
|
|
|
+const handleCurrentChange = (val) => {
|
|
|
currentPage.value = val
|
|
|
- getManageMemberList()
|
|
|
+ if (tag.value === 'invited') {
|
|
|
+ getManageMemberList()
|
|
|
+ } else {
|
|
|
+ loading.value = true
|
|
|
+ getDirectoryUser()
|
|
|
+ }
|
|
|
}
|
|
|
// 获取团队管理列表
|
|
|
const getTeamList = () => {
|
|
@@ -68,37 +156,28 @@ const getTeamList = () => {
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
-//获取已购买产品
|
|
|
-const getproductList = () => {
|
|
|
- get('/pdf-tech/product/listWithAdmin').then(
|
|
|
- (res) => {
|
|
|
- productList.value = productListNameMapping(res.data.result)
|
|
|
- }
|
|
|
- )
|
|
|
+// 获取已购买产品
|
|
|
+const getProductList = () => {
|
|
|
+ get('/pdf-tech/product/listWithAdmin').then((res) => {
|
|
|
+ productList.value = productListNameMapping(res.data.result)
|
|
|
+ })
|
|
|
}
|
|
|
// 获取成员列表
|
|
|
-function getManageMemberList() {
|
|
|
- //初始化表格
|
|
|
+const getManageMemberList = () => {
|
|
|
+ // 初始化表格
|
|
|
tableData.value = []
|
|
|
- get(
|
|
|
- '/pdf-tech/vppRTeamMemberRole/pageForMember?page=' +
|
|
|
+ get('/pdf-tech/vppRTeamMemberRole/pageForMember?page=' +
|
|
|
currentPage.value +
|
|
|
- '&' +
|
|
|
- 'pageSize=' +
|
|
|
+ '&pageSize=' +
|
|
|
size.value +
|
|
|
- '&' +
|
|
|
- 'teamId=' +
|
|
|
+ '&teamId=' +
|
|
|
teamId.value +
|
|
|
- '&' +
|
|
|
- 'status=' +
|
|
|
+ '&status=' +
|
|
|
status.value +
|
|
|
- '&' +
|
|
|
- 'queryString=' +
|
|
|
+ '&queryString=' +
|
|
|
queryString.value +
|
|
|
- '&' +
|
|
|
- 'productCode=' +
|
|
|
- product.value
|
|
|
- ).then((res) => {
|
|
|
+ '&productCode=' +
|
|
|
+ product.value).then((res) => {
|
|
|
let data = res.data.result.list
|
|
|
data = productListNameMapping(data)
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -109,246 +188,497 @@ function getManageMemberList() {
|
|
|
} else {
|
|
|
data[i].validFlag = 'Invited'
|
|
|
}
|
|
|
- data[i].productNames = res.data.result.list[i].productNames?.replace(/,/g, ",|").split("|")
|
|
|
+ data[i].productNames = res.data.result.list[i].productNames
|
|
|
+ ?.replace(/,/g, ',|')
|
|
|
+ .split('|')
|
|
|
}
|
|
|
tableData.value = data
|
|
|
total.value = res.data.result.total
|
|
|
})
|
|
|
}
|
|
|
// 团队成员列表导出
|
|
|
-function exportManageMemberList() {
|
|
|
+const exportManageMemberList = () => {
|
|
|
var urlencoded = new URLSearchParams()
|
|
|
- urlencoded.append("queryString", queryString.value)
|
|
|
- urlencoded.append("productId", product.value)
|
|
|
- urlencoded.append("teamId", teamId.value)
|
|
|
- urlencoded.append("status", status.value)
|
|
|
- if(click){
|
|
|
+ urlencoded.append('queryString', queryString.value)
|
|
|
+ urlencoded.append('productId', product.value)
|
|
|
+ urlencoded.append('teamId', teamId.value)
|
|
|
+ urlencoded.append('status', status.value)
|
|
|
+ if (click) {
|
|
|
click = false
|
|
|
- downLoad("/pdf-tech/vppRTeamMemberRole/download", urlencoded).then((res)=>{
|
|
|
+ downLoad('/pdf-tech/vppRTeamMemberRole/download', urlencoded).then(
|
|
|
+ (res) => {
|
|
|
//限制点击
|
|
|
setTimeout(() => {
|
|
|
click = true
|
|
|
}, 2000)
|
|
|
- let url = window.URL.createObjectURL(new Blob([res.data], { type: '.xlsx' }))
|
|
|
- let a= document.createElement('a')
|
|
|
+ let url = window.URL.createObjectURL(
|
|
|
+ new Blob([res.data], { type: '.xlsx' })
|
|
|
+ )
|
|
|
+ let a = document.createElement('a')
|
|
|
a.style.display = 'none'
|
|
|
a.href = url
|
|
|
// 自定义文件名
|
|
|
a.setAttribute('download', `User Information.xlsx`)
|
|
|
- document.body.appendChild(a)
|
|
|
- // 下载文件
|
|
|
- a.click()
|
|
|
- // 释放内存
|
|
|
- url = window.URL.revokeObjectURL(url)
|
|
|
- document.body.removeChild(a)
|
|
|
- })
|
|
|
+ document.body.appendChild(a)
|
|
|
+ // 下载文件
|
|
|
+ a.click()
|
|
|
+ // 释放内存
|
|
|
+ url = window.URL.revokeObjectURL(url)
|
|
|
+ document.body.removeChild(a)
|
|
|
+ }
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
-//筛选
|
|
|
+// 筛选
|
|
|
const searchInfo = () => {
|
|
|
- currentPage.value = 1
|
|
|
+ currentPage.value = 1
|
|
|
+ if (tag.value === 'invited') {
|
|
|
getManageMemberList()
|
|
|
+ } else {
|
|
|
+ loading.value = true
|
|
|
+ if (tagSecond.value === 'delete') {
|
|
|
+ directoryStatus.value = ''
|
|
|
+ directoryId.value = ''
|
|
|
+ getDeleteDirectoryUser()
|
|
|
+ } else getDirectoryUser()
|
|
|
+ }
|
|
|
}
|
|
|
-onMounted(() => {
|
|
|
- let pageText = document.getElementsByClassName('el-pagination__jump')[0]
|
|
|
- if (pageText) {
|
|
|
- pageText.childNodes[0].nodeValue = 'Jump to Page'
|
|
|
+// 获取用户多选操作
|
|
|
+const handleSelectionChange = (val) => {
|
|
|
+ userList.value = []
|
|
|
+ val.forEach(item => {
|
|
|
+ userList.value.push(item.id)
|
|
|
+ })
|
|
|
+}
|
|
|
+// 打开删除对话框
|
|
|
+const openDeleteDialog = () => {
|
|
|
+ if (userList.value.length) {
|
|
|
+ userList.value = []
|
|
|
}
|
|
|
- getManageMemberList()
|
|
|
- getTeamList()
|
|
|
- getproductList()
|
|
|
-})
|
|
|
+ deleteDialogVisible.value = true
|
|
|
+}
|
|
|
+// 吊销用户
|
|
|
+const revokeUser = async () => {
|
|
|
+ try {
|
|
|
+ const { data } = await post('/pdf-tech/vppRTeamMemberRole/revokeSSOMember?memberId=' + directoryMemberId.value)
|
|
|
+ if (data.code === 200) {
|
|
|
+ proxy.$message({
|
|
|
+ duration: 5000,
|
|
|
+ message: 'Revoke Success',
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ proxy.$message({
|
|
|
+ duration: 5000,
|
|
|
+ message: data.msg,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ revokeDialogVisible.value = false
|
|
|
+ loading.value = true
|
|
|
+ getDirectoryUser()
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+}
|
|
|
+// 删除用户
|
|
|
+const deleteUser = async (type) => {
|
|
|
+ console.log(type)
|
|
|
+ let directoryMemberIdList = []
|
|
|
+ if (userList.value.length && type === 'multiple') {
|
|
|
+ directoryMemberIdList = userList.value
|
|
|
+ } else directoryMemberIdList.push(directoryMemberId.value)
|
|
|
+ try {
|
|
|
+ const { data } = await post('/pdf-tech/vppRTeamMemberRole/removeSSOMember?memberIds=' + directoryMemberIdList)
|
|
|
+ if (data.code === 200) {
|
|
|
+ proxy.$message({
|
|
|
+ duration: 5000,
|
|
|
+ message: 'Remove Success',
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ proxy.$message({
|
|
|
+ duration: 5000,
|
|
|
+ message: data.msg,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ deleteDialogVisible.value = false
|
|
|
+ loading.value = true
|
|
|
+ getDirectoryUser()
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+}
|
|
|
+// 还原用户
|
|
|
+const restore = async (val, type) => {
|
|
|
+ let directoryMemberIdList = []
|
|
|
+ if (userList.value.length && type === 'multiple') {
|
|
|
+ directoryMemberIdList = userList.value
|
|
|
+ } else directoryMemberIdList.push(val.id)
|
|
|
+ try {
|
|
|
+ const { data } = await post('/pdf-tech/vppRTeamMemberRole/reductionSSOMember?memberIds=' + directoryMemberIdList)
|
|
|
+ if (data.code === 200) {
|
|
|
+ proxy.$message({
|
|
|
+ duration: 5000,
|
|
|
+ message: 'Restore Success',
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ proxy.$message({
|
|
|
+ duration: 5000,
|
|
|
+ message: data.msg,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ loading.value = true
|
|
|
+ getDeleteDirectoryUser()
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+}
|
|
|
+// 取消吊销用户
|
|
|
+const unRevoke = async () => {
|
|
|
+ try {
|
|
|
+ const directoryMemberIdList = []
|
|
|
+ console.log(directoryMemberId.value)
|
|
|
+ directoryMemberIdList.push(directoryMemberId.value)
|
|
|
+ const { data } = await post('/pdf-tech/vppRTeamMemberRole/reductionSSOMember?memberIds=' + directoryMemberIdList)
|
|
|
+ if (data.code === 200) {
|
|
|
+ proxy.$message({
|
|
|
+ duration: 5000,
|
|
|
+ message: 'Restore Success',
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ proxy.$message({
|
|
|
+ duration: 5000,
|
|
|
+ message: data.msg,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ loading.value = true
|
|
|
+ getDirectoryUser()
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+}
|
|
|
+// 切换一级tag重置查询字段
|
|
|
+const changeTag = (val) => {
|
|
|
+ size.value = 5
|
|
|
+ tag.value = val
|
|
|
+ status.value = ''
|
|
|
+ currentPage.value = 1
|
|
|
+ queryString.value = ''
|
|
|
+ directoryId.value = ''
|
|
|
+ directoryStatus.value = ''
|
|
|
+ if (val === 'directory') {
|
|
|
+ getDirectoryUser()
|
|
|
+ } else {
|
|
|
+ getManageMemberList()
|
|
|
+ }
|
|
|
+}
|
|
|
+// 切换二级tag重置查询字段
|
|
|
+const changeSecondTag = (val) => {
|
|
|
+ size.value = 5
|
|
|
+ tagSecond.value = val
|
|
|
+ loading.value = true
|
|
|
+ currentPage.value = 1
|
|
|
+ queryString.value = ''
|
|
|
+ directoryId.value = ''
|
|
|
+ directoryStatus.value = ''
|
|
|
+ if (val === 'all') {
|
|
|
+ getDirectoryUser()
|
|
|
+ } else {
|
|
|
+ getDeleteDirectoryUser()
|
|
|
+ }
|
|
|
+}
|
|
|
+// 批量操作
|
|
|
+const handleClickSecond = () => {
|
|
|
+ if (tagSecond.value === 'all') {
|
|
|
+ deleteUser('multiple')
|
|
|
+ } else restore('', 'multiple')
|
|
|
+}
|
|
|
+// 导出目录用户
|
|
|
+const handleDownload = () => {
|
|
|
+ if (click) {
|
|
|
+ click = false
|
|
|
+ let url = ''
|
|
|
+ if (tagSecond.value === 'all') {
|
|
|
+ url = '/pdf-tech/vppRTeamMemberRole/downloadSSOMember'
|
|
|
+ } else url = '/pdf-tech/vppRTeamMemberRole/downloadUnValidSSOMember'
|
|
|
+ downLoad(url).then(
|
|
|
+ (res) => {
|
|
|
+ //限制点击
|
|
|
+ setTimeout(() => {
|
|
|
+ click = true
|
|
|
+ }, 2000)
|
|
|
+ let url = window.URL.createObjectURL(
|
|
|
+ new Blob([res.data], { type: '.xlsx' })
|
|
|
+ )
|
|
|
+ let a = document.createElement('a')
|
|
|
+ a.style.display = 'none'
|
|
|
+ a.href = url
|
|
|
+ // 自定义文件名
|
|
|
+ a.setAttribute('download', `UserData.xlsx`)
|
|
|
+ document.body.appendChild(a)
|
|
|
+ // 下载文件
|
|
|
+ a.click()
|
|
|
+ // 释放内存
|
|
|
+ url = window.URL.revokeObjectURL(url)
|
|
|
+ document.body.removeChild(a)
|
|
|
+ }
|
|
|
+ ).catch((error) => {
|
|
|
+ console.log(error)
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
<div>
|
|
|
- <h1>Manage Member</h1>
|
|
|
- <div class="mt-36px mb-16px flex justify-between">
|
|
|
- <h2>Content</h2>
|
|
|
- <div class="flex">
|
|
|
- <el-tooltip
|
|
|
- class="item"
|
|
|
- effect="dark"
|
|
|
- content="Export Data (.xlsx)"
|
|
|
- placement="bottom"
|
|
|
- >
|
|
|
- <a
|
|
|
- class="
|
|
|
- w-28px
|
|
|
- h-28px
|
|
|
- border-1 border-[#D9D9D9]
|
|
|
- rounded-4px
|
|
|
- bg-[#F9FAFB]
|
|
|
- flex
|
|
|
- justify-center
|
|
|
- items-center
|
|
|
- mr-12px
|
|
|
- cursor-pointer
|
|
|
- "
|
|
|
- @click="exportManageMemberList"
|
|
|
- >
|
|
|
+ <h1 class="mb-16px">Manage Member</h1>
|
|
|
+ <div class="flex">
|
|
|
+ <span
|
|
|
+ class="flex justify-center bg-[#C6C9CC] rounded-t-8px items-center font-bold w-200px h-32px cursor-pointer"
|
|
|
+ @click="changeTag('directory')" :class="tag === 'directory' && 'active'">Directory users</span>
|
|
|
+ <span
|
|
|
+ class="flex justify-center bg-[#C6C9CC] rounded-t-8px items-center font-bold w-200px h-32px cursor-pointer ml-8px"
|
|
|
+ @click="changeTag('invited')" :class="tag === 'invited' && 'active'">Invited users</span>
|
|
|
+ </div>
|
|
|
+ <div v-show="tag === 'invited'" class="block p-40px">
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <h2>Content</h2>
|
|
|
+ <div class="flex">
|
|
|
+ <a class="w-28px h-28px border-1 border-[#D9D9D9] rounded-4px bg-[#F9FAFB] flex justify-center items-center mr-12px cursor-pointer relative"
|
|
|
+ @click="exportManageMemberList">
|
|
|
<img src="@/assets/images/download.svg" alt="download" />
|
|
|
+ <div class="hidden absolute w-110px bg-[#373A47] rounded-4px px-8px py-2px text-14px leading-20px text-white top-33px z-3 left-[-40px]">Download data</div>
|
|
|
</a>
|
|
|
- </el-tooltip>
|
|
|
- <router-link :to="{ name: 'AddManageMember' }">
|
|
|
- <div
|
|
|
- class="
|
|
|
- h-28px
|
|
|
- px-10px
|
|
|
- py-4px
|
|
|
- bg-[#1460F3]
|
|
|
- rounded-4px
|
|
|
- text-14px
|
|
|
- leading-20px
|
|
|
- font-400
|
|
|
- text-[#fff]
|
|
|
- cursor-pointer
|
|
|
- hover:opacity-80
|
|
|
- "
|
|
|
- >
|
|
|
- Add Member
|
|
|
+ <router-link :to="{ name: 'AddManageMember' }">
|
|
|
+ <div class="h-28px px-10px py-4px bg-[#1460F3] rounded-4px text-14px leading-20px font-400 text-[#fff] cursor-pointer hover:opacity-80">
|
|
|
+ Add Member
|
|
|
+ </div>
|
|
|
+ </router-link>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="pt-36px pb-40px">
|
|
|
+ <div class="flex">
|
|
|
+ <select name="team" class="min-w-50px mr-16px" v-model="teamId" :class="{ '!text-[#232A40]': teamId !== '' }">
|
|
|
+ <option value="" selected>Team</option>
|
|
|
+ <option v-for="item in teamList" :value="item.id" :key="item.id">
|
|
|
+ {{ item.name }}
|
|
|
+ </option>
|
|
|
+ </select>
|
|
|
+ <select name="status" class="min-w-100px mr-16px" v-model="status" :class="{ '!text-[#232A40]': status !== '' }">
|
|
|
+ <option value="" selected>Status</option>
|
|
|
+ <option value="1">Joined</option>
|
|
|
+ <option value="0">Deleted</option>
|
|
|
+ </select>
|
|
|
+ <select name="Assigned Product" class="min-w-100px mr-16px" v-model="product" :class="{ '!text-[#232A40]': product !== '' }">
|
|
|
+ <option value="" selected>Assigned Product</option>
|
|
|
+ <option v-for="item in productList" :key="item.value" :value="item.code">
|
|
|
+ {{ item.name }}
|
|
|
+ </option>
|
|
|
+ </select>
|
|
|
+ <div class="relative mr-16px">
|
|
|
+ <el-input v-model="queryString" size="mini" clearable class="!w-316px input-with-select" placeholder="Search Member Name/Email">
|
|
|
+ </el-input>
|
|
|
+ <button class="absolute top-8px right-8px" @click="searchInfo()">
|
|
|
+ <Search />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <button type="button" @click="searchInfo()"
|
|
|
+ class="w-70px h-28px border-[#1460F3] border-1px rounded-4px px-10px py-4px text-14px leading-20px text-[#1460F3] cursor-pointer hover:opacity-80">
|
|
|
+ Confirm
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <el-table :data="tableData" style="width: 100%">
|
|
|
+ <el-table-column prop="fullName" label="Member Name" min-width="100px">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="email" label="Member Email" min-width="100px">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="teamName" label="Team" min-width="130px">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="validFlag" label="Status" min-width="80px">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="Assigned Product" min-width="150px">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span v-for="(item, index) in scope.row.productNames" :key="index">
|
|
|
+ {{ item }}<br/>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="Action" min-width="100px">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>
|
|
|
+ <router-link :to="{ name: 'EditManageMember', query: { MemberName: scope.row.fullName, Email: scope.row.email, Team: scope.row.teamName, Id: scope.row.id } }">
|
|
|
+ <div class="w-61px h-20px border-1 border-[#1460F3] rounded-4px text-center text-14px leading-20px text-[#1460F3] cursor-pointer mb-8px">
|
|
|
+ Edit
|
|
|
+ </div>
|
|
|
+ </router-link>
|
|
|
+ <div class="w-61px h-20px border-1 border-[#1460F3] rounded-4px text-center text-14px leading-20px text-[#1460F3] cursor-pointer"
|
|
|
+ @click="handleClick(scope.row)">
|
|
|
+ Delete
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <div slot="empty" class="flex flex-col items-center py-12px">
|
|
|
+ <Empty class="mb-8px" />
|
|
|
+ <p class="text-14px leading-20px">No Data</p>
|
|
|
</div>
|
|
|
- </router-link>
|
|
|
+ </el-table>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="block px-24px pt-32px pb-40px">
|
|
|
- <div class="flex">
|
|
|
- <select name="team" class="min-w-50px mr-16px" v-model="teamId" :class="{ '!text-[#232A40]': teamId !== '' }">
|
|
|
- <option value="" selected>Team</option>
|
|
|
- <option v-for="item in teamList" :value="item.id" :key="item.id">
|
|
|
- {{ item.name }}
|
|
|
- </option>
|
|
|
- </select>
|
|
|
- <select name="status" class="min-w-100px mr-16px" v-model="status" :class="{ '!text-[#232A40]': status !== '' }">
|
|
|
- <option value="" selected>Status</option>
|
|
|
- <!-- <option value="2">Invited</option> -->
|
|
|
- <option value="1">Joined</option>
|
|
|
- <option value="0">Deleted</option>
|
|
|
- </select>
|
|
|
- <select name="Assigned Product" class="min-w-100px mr-16px" v-model="product" :class="{ '!text-[#232A40]': product !== '' }">
|
|
|
- <option value="" selected>Assigned Product</option>
|
|
|
- <option
|
|
|
- v-for="item in productList"
|
|
|
- :key="item.value"
|
|
|
- :value="item.code"
|
|
|
- >
|
|
|
- {{ item.name }}
|
|
|
- </option>
|
|
|
- </select>
|
|
|
- <div class="relative mr-16px">
|
|
|
- <el-input
|
|
|
- v-model="queryString"
|
|
|
- size="mini"
|
|
|
- class="!w-316px input-with-select"
|
|
|
- placeholder="Search Member Name/Email"
|
|
|
- >
|
|
|
- </el-input>
|
|
|
- <button class="absolute top-8px right-8px" @click="searchInfo()"><Search /></button>
|
|
|
+ <div v-show="tag === 'directory'" class="block directory p-40px">
|
|
|
+ <h2 class="!text-28px !leading-40px mb-12px">Content</h2>
|
|
|
+ <div class="border-b-2px border-[#F1F1F2] text-[#404653] flex mb-12px">
|
|
|
+ <div class="py-12px tet-14px leading-20px mb-[-2px] cursor-pointer mr-20px" :class="tagSecond === 'all' && 'border-b-2px border-[#1460F3] text-[#065CBC]'" @click="changeSecondTag('all')">All Users</div>
|
|
|
+ <div class="py-12px tet-14px leading-20px mb-[-2px] cursor-pointer" :class="tagSecond === 'delete' && 'border-b-2px border-[#1460F3] text-[#065CBC]'" @click="changeSecondTag('delete')">Removed Users</div>
|
|
|
+ </div>
|
|
|
+ <!-- 筛选模块 -->
|
|
|
+ <div class="flex justify-between mb-12px pt-24px">
|
|
|
+ <div class="flex">
|
|
|
+ <div class="relative mr-16px">
|
|
|
+ <el-input v-model="queryString" size="mini" clearable class="!w-316px input-with-select" placeholder="Search user name or email">
|
|
|
+ </el-input>
|
|
|
+ <button class="absolute top-8px right-8px" @click="searchInfo()">
|
|
|
+ <Search />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <select name="Status" v-show="tagSecond === 'all'" class="min-w-50px mr-16px" v-model="directoryStatus" :class="{ '!text-[#232A40]': teamId !== '' }">
|
|
|
+ <option value="" selected>Status</option>
|
|
|
+ <option value="">All</option>
|
|
|
+ <option value="1">Available access</option>
|
|
|
+ <option value="3">Revoked</option>
|
|
|
+ </select>
|
|
|
+ <select name="Domains" v-show="tagSecond === 'all'" class="min-w-100px mr-16px" v-model="directoryId" :class="{ '!text-[#232A40]': status !== '' }">
|
|
|
+ <option value="" selected>Domains</option>
|
|
|
+ <option v-for="(item, index) in domainList" :key="index" :value="item.directoryId">{{ item.domain }}</option>
|
|
|
+ </select>
|
|
|
+ <button type="button" @click="searchInfo()"
|
|
|
+ class="w-70px h-28px border-[#1460F3] border-1px rounded-4px px-10px py-4px text-14px leading-20px text-[#1460F3] cursor-pointer hover:opacity-80">
|
|
|
+ Confirm
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div class="flex">
|
|
|
+ <a class="w-28px h-28px border-1 border-[#D9D9D9] rounded-4px bg-[#F9FAFB] flex justify-center items-center mr-12px cursor-pointer relative"
|
|
|
+ @click="handleDownload">
|
|
|
+ <img src="@/assets/images/download.svg" alt="download" />
|
|
|
+ <div class="hidden absolute bg-[#373A47] rounded-4px px-8px py-2px text-14px leading-20px text-white top-33px z-3 left-[-16px]">Export</div>
|
|
|
+ </a>
|
|
|
+ <button v-show="tagSecond === 'all'" :disabled="!userList.length" @click="handleClickSecond"
|
|
|
+ class="h-28px px-10px py-4px bg-[#1460F3] rounded-4px text-14px leading-20px font-400 text-[#fff] cursor-pointer hover:opacity-80"
|
|
|
+ :class="!userList.length && '!bg-[#1460F333] cursor-not-allowed'">Remove</button>
|
|
|
+ <button v-show="tagSecond === 'delete'" :disabled="!userList.length" @click="handleClickSecond"
|
|
|
+ class="h-28px px-10px py-4px bg-[#1460F3] rounded-4px text-14px leading-20px font-400 text-[#fff] cursor-pointer hover:opacity-80"
|
|
|
+ :class="!userList.length && '!bg-[#1460F333] cursor-not-allowed'">Restore</button>
|
|
|
</div>
|
|
|
- <button
|
|
|
- type="button"
|
|
|
- @click="searchInfo()"
|
|
|
- class="
|
|
|
- w-70px
|
|
|
- h-28px
|
|
|
- border-[#1460F3] border-1px
|
|
|
- rounded-4px
|
|
|
- px-10px
|
|
|
- py-4px
|
|
|
- text-14px
|
|
|
- leading-20px
|
|
|
- text-[#1460F3]
|
|
|
- cursor-pointer
|
|
|
- hover:opacity-80
|
|
|
- "
|
|
|
- >
|
|
|
- Confirm
|
|
|
- </button>
|
|
|
</div>
|
|
|
- <el-table :data="tableData" style="width: 100%">
|
|
|
- <el-table-column prop="fullName" label="Member Name" min-width="100px">
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="email" label="Member Email" min-width="100px">
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="teamName" label="Team" min-width="130px">
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="validFlag" label="Status" min-width="80px">
|
|
|
+ <!-- 所有用户 -->
|
|
|
+ <el-table
|
|
|
+ v-show="tagSecond === 'all'"
|
|
|
+ ref="multipleTable"
|
|
|
+ v-loading="loading"
|
|
|
+ :data="directoryData"
|
|
|
+ tooltip-effect="dark"
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="55"></el-table-column>
|
|
|
+ <el-table-column prop="fullName" label="User Name" min-width="100px"></el-table-column>
|
|
|
+ <el-table-column prop="email" label="Email" min-width="100px"></el-table-column>
|
|
|
+ <el-table-column label="Status" min-width="100px">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div class="text-14px leading-20px flex items-center" :class="Number(scope.row.validFlag) === 1 ? 'text-[#41CC00]' : 'text-[#808185]'">
|
|
|
+ <span class="flex w-6px h-6px rounded-[50%] mr-8px" :class="Number(scope.row.validFlag) === 1 ? 'bg-[#41CC00]' : 'bg-[#808185]'"></span>
|
|
|
+ <template v-if="Number(scope.row.validFlag) === 1">
|
|
|
+ Available access
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ {{ Number(scope.row.validFlag) ? 'Revoked' : 'Removed Users' }}
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column
|
|
|
- label="Assigned Product"
|
|
|
- min-width="150px"
|
|
|
- >
|
|
|
- <template slot-scope="scope">
|
|
|
- <span v-for="(item, index) in scope.row.productNames" :key="index">{{item}}<br></span>
|
|
|
- </template>
|
|
|
+ <el-table-column prop="updatedAt" label="Login Time" min-width="100px"></el-table-column>
|
|
|
+ <el-table-column prop="action" label="Actions" min-width="100px">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div class="flex">
|
|
|
+ <div class="h-20px rounded-4px text-center text-14px leading-20px text-[#1460F3] cursor-pointer"
|
|
|
+ @click="directoryEmail = scope.row.email, directoryMemberId = scope.row.id">
|
|
|
+ <span @click="unRevoke" v-if="Number(scope.row.validFlag) === 3">Access</span>
|
|
|
+ <span @click="revokeDialogVisible = true" v-else>Revoke</span>
|
|
|
+ </div>
|
|
|
+ <span class="text-[#D9D9D9]">丨</span>
|
|
|
+ <div class="h-20px rounded-4px text-center text-14px leading-20px text-[#1460F3] cursor-pointer"
|
|
|
+ @click="openDeleteDialog(), directoryEmail = scope.row.email, directoryMemberId = scope.row.id">
|
|
|
+ Remove
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</el-table-column>
|
|
|
- <!-- <el-table-column
|
|
|
- prop="id"
|
|
|
- class="hidden"
|
|
|
- label="UUID of Activated Device"
|
|
|
- min-width="178px"
|
|
|
- >
|
|
|
- </el-table-column> -->
|
|
|
- <el-table-column label="Action" min-width="100px">
|
|
|
+ <div slot="empty" class="flex flex-col items-center py-12px">
|
|
|
+ <Empty class="mb-8px" />
|
|
|
+ <p class="text-14px leading-20px">No Data</p>
|
|
|
+ </div>
|
|
|
+ </el-table>
|
|
|
+ <!-- 吊销对话框 -->
|
|
|
+ <el-dialog :visible.sync="revokeDialogVisible" width="556px" top="30vh" center :show-close="false">
|
|
|
+ <h5 class="w-full text-24px leading-32px font-bold text-[#232A40] flex justify-between"><p>Revoke</p><Close class="cursor-pointer" @click.native="revokeDialogVisible = false" /></h5>
|
|
|
+ <p class="text-left mt-12px text-14px leading-20px text-[#808185]">
|
|
|
+ You are about to revoke user access for:
|
|
|
+ <ul class="py-12px">
|
|
|
+ <li class="flex items-center pl-12px"><span class="flex w-4px h-4px rounded-[50%] bg-[#808185] mr-8px"></span>{{ directoryEmail }}</li>
|
|
|
+ </ul>
|
|
|
+ This user won't be able to use your site. You can give them access again at any time.
|
|
|
+ </p>
|
|
|
+ <div slot="footer" class="dialog-footer flex justify-end">
|
|
|
+ <el-button @click="revokeDialogVisible = false" class="!font-700">Cancel</el-button>
|
|
|
+ <el-button type="primary" @click="revokeUser" class="!font-700">Revoke</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <!-- 移除对话框 -->
|
|
|
+ <el-dialog :visible.sync="deleteDialogVisible" width="556px" top="30vh" center :show-close="false">
|
|
|
+ <h5 class="w-full text-24px leading-32px font-bold text-[#232A40] flex justify-between"><p>Remove</p><Close class="cursor-pointer" @click.native="deleteDialogVisible = false" /></h5>
|
|
|
+ <p class="text-left mt-12px text-14px leading-20px text-[#808185]">
|
|
|
+ The licenses of these users will be removed. They will no longer have access to this site and won't be able to collaborate with your team. You can restore these users in removed users list.
|
|
|
+ </p>
|
|
|
+ <div slot="footer" class="dialog-footer flex justify-end">
|
|
|
+ <el-button @click="deleteDialogVisible = false" class="!font-700">Cancel</el-button>
|
|
|
+ <el-button type="primary" @click="deleteUser" class="!font-700">Remove</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <!-- 已删除用户 -->
|
|
|
+ <el-table
|
|
|
+ v-show="tagSecond === 'delete'"
|
|
|
+ ref="multipleTable"
|
|
|
+ v-loading="loading"
|
|
|
+ :data="deleteDirectoryData"
|
|
|
+ tooltip-effect="dark"
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="55"> </el-table-column>
|
|
|
+ <el-table-column prop="fullName" label="User Name" min-width="100px"></el-table-column>
|
|
|
+ <el-table-column prop="email" label="Email" min-width="275px"></el-table-column>
|
|
|
+ <el-table-column prop="action" label="Actions" min-width="100px">
|
|
|
<template slot-scope="scope">
|
|
|
- <div>
|
|
|
- <router-link
|
|
|
- :to="{
|
|
|
- name: 'EditManageMember',
|
|
|
- query: {
|
|
|
- MemberName: scope.row.fullName,
|
|
|
- Email: scope.row.email,
|
|
|
- Team: scope.row.teamName,
|
|
|
- Id: scope.row.id,
|
|
|
- },
|
|
|
- }"
|
|
|
- >
|
|
|
- <div
|
|
|
- class="
|
|
|
- w-61px
|
|
|
- h-20px
|
|
|
- border-1 border-[#1460F3]
|
|
|
- rounded-4px
|
|
|
- text-center text-14px
|
|
|
- leading-20px
|
|
|
- text-[#1460F3]
|
|
|
- cursor-pointer
|
|
|
- mb-8px
|
|
|
- "
|
|
|
- >
|
|
|
- Edit
|
|
|
- </div>
|
|
|
- </router-link>
|
|
|
- <div
|
|
|
- class="
|
|
|
- w-61px
|
|
|
- h-20px
|
|
|
- border-1 border-[#1460F3]
|
|
|
- rounded-4px
|
|
|
- text-center text-14px
|
|
|
- leading-20px
|
|
|
- text-[#1460F3]
|
|
|
- cursor-pointer
|
|
|
- "
|
|
|
- @click="handleClick(scope.row)"
|
|
|
- >
|
|
|
- Delete
|
|
|
+ <div class="flex">
|
|
|
+ <div class="h-20px rounded-4px text-center text-14px leading-20px text-[#1460F3] cursor-pointer"
|
|
|
+ @click="restore(scope.row)">
|
|
|
+ Restore
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <p slot="empty">No Data Available</p>
|
|
|
+ <div slot="empty" class="flex flex-col items-center py-12px">
|
|
|
+ <Empty class="mb-8px" />
|
|
|
+ <p class="text-14px leading-20px">No Data</p>
|
|
|
+ </div>
|
|
|
</el-table>
|
|
|
</div>
|
|
|
<!-- 删除框 -->
|
|
|
- <el-dialog
|
|
|
- title=""
|
|
|
- :visible.sync="dialogVisible"
|
|
|
- width="376px"
|
|
|
- top="30vh"
|
|
|
- center
|
|
|
- :show-close="false"
|
|
|
- >
|
|
|
+ <el-dialog :visible.sync="dialogVisible" width="376px" top="30vh" center :show-close="false">
|
|
|
<Warning class="inline-block" />
|
|
|
<div class="mt-16px text-16px leading-24px text-[#232A40]">
|
|
|
<p>Are you sure you want to delete this member?</p>
|
|
@@ -367,7 +697,7 @@ onMounted(() => {
|
|
|
:page-size="1"
|
|
|
:background="true"
|
|
|
layout="prev, pager, next, sizes, jumper"
|
|
|
- :total="total"
|
|
|
+ :total="tag === 'invited' ? total : tagSecond === 'all' ? directoryTotal : deleteDirectoryTotal"
|
|
|
class="px-24px !rounded-0 rounded-b-8px flex justify-end"
|
|
|
>
|
|
|
</el-pagination>
|
|
@@ -375,20 +705,43 @@ onMounted(() => {
|
|
|
</template>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
+.block {
|
|
|
+ border-top-left-radius: 0px;
|
|
|
+}
|
|
|
+.active {
|
|
|
+ color: #1460f3;
|
|
|
+ background-color: #fff;
|
|
|
+}
|
|
|
+.relative:hover {
|
|
|
+ .hidden {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+}
|
|
|
.el-table::v-deep thead {
|
|
|
color: #000 !important;
|
|
|
}
|
|
|
|
|
|
-.el-table::v-deep .el-table__cell{
|
|
|
+.el-table::v-deep .el-table__cell {
|
|
|
padding-right: 20px !important;
|
|
|
padding-left: 20px !important;
|
|
|
}
|
|
|
|
|
|
+::v-deep .directory {
|
|
|
+ .el-table {
|
|
|
+ .el-table__header-wrapper {
|
|
|
+ th.is-leaf.el-table__cell {
|
|
|
+ background: #F6F7F9;
|
|
|
+ border-color: #D9D9D9;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
::v-deep .input-with-select .el-input__inner {
|
|
|
padding: 0 20px 0 8px;
|
|
|
border-color: #d9d9d9;
|
|
|
font-size: 14px;
|
|
|
- color: #232A40;
|
|
|
+ color: #232a40;
|
|
|
}
|
|
|
|
|
|
::v-deep .input-with-select .el-input__inner::placeholder {
|
|
@@ -396,7 +749,12 @@ onMounted(() => {
|
|
|
font-weight: 400;
|
|
|
color: #808185;
|
|
|
}
|
|
|
-.el-table::v-deep .cell{
|
|
|
+.el-table::v-deep .cell {
|
|
|
word-break: break-word;
|
|
|
}
|
|
|
+.dialog-footer {
|
|
|
+ ::v-deep .el-button {
|
|
|
+ height: 40px;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|