389 lines
11 KiB
Vue
389 lines
11 KiB
Vue
<script setup lang="ts">
|
|
import { useMessage } from 'naive-ui'
|
|
import { onMounted } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
|
|
interface MemberItem {
|
|
userId: number | string
|
|
id: number | string
|
|
tenantId: number | string
|
|
avatar: string
|
|
nickname: string
|
|
role: '星主' | '管理人' | '成员'
|
|
type: '付费' | '免费'
|
|
joinTime: string
|
|
expireTime: string
|
|
lastLoginTime: string
|
|
isBlack: '0' | '1'
|
|
userType: number
|
|
communityId: number | string
|
|
joinType: string
|
|
}
|
|
definePageMeta({
|
|
layout: 'planet',
|
|
})
|
|
|
|
const route = useRoute()
|
|
const message = useMessage()
|
|
const memberList = ref<MemberItem[]>([])
|
|
const loading = ref(false)
|
|
const isInitialized = ref(false)
|
|
const params = ref({
|
|
orderByColum: '',
|
|
pageNum: 1,
|
|
pageSize: 10,
|
|
communityId: route.query.communityId,
|
|
tenantId: route.query.tenantId,
|
|
searchContent: '',
|
|
})
|
|
|
|
// 添加分页数据
|
|
const pagination = ref({
|
|
page: 1,
|
|
pageSize: 10,
|
|
itemCount: 0,
|
|
showSizePicker: false,
|
|
})
|
|
|
|
// 拉黑表单
|
|
const showBlackModal = ref(false)
|
|
const blackForm = ref({
|
|
blackDay: undefined,
|
|
blackReason: '',
|
|
userId: '',
|
|
})
|
|
|
|
// 添加表单验证规则
|
|
const rules = {
|
|
blackDay: {
|
|
required: true,
|
|
message: '请输入拉黑时长',
|
|
trigger: ['blur', 'change'],
|
|
type: 'number',
|
|
validator: (rule: any, value: any) => {
|
|
if (value === undefined || value === null)
|
|
return new Error('请输入拉黑时长')
|
|
return true
|
|
},
|
|
},
|
|
blackReason: {
|
|
required: true,
|
|
message: '请输入拉黑原因',
|
|
trigger: ['blur', 'change'],
|
|
},
|
|
}
|
|
|
|
// 表单ref
|
|
const formRef = ref()
|
|
|
|
// 处理分页变化
|
|
function handlePageChange(page: number) {
|
|
pagination.value.page = page
|
|
params.value.pageNum = page
|
|
getMemberList()
|
|
}
|
|
|
|
// 处理搜索
|
|
function handleSearch(e: KeyboardEvent) {
|
|
if (e.key === 'Enter') {
|
|
params.value.pageNum = 1
|
|
pagination.value.page = 1
|
|
getMemberList()
|
|
}
|
|
}
|
|
|
|
// 获取成员列表
|
|
async function getMemberList() {
|
|
try {
|
|
loading.value = true
|
|
const res = await request.post('/communityUser/list', params.value)
|
|
if (res.code === 200) {
|
|
memberList.value = res.rows
|
|
pagination.value.itemCount = res.total
|
|
isInitialized.value = true
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.error(error)
|
|
}
|
|
finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
getMemberList()
|
|
})
|
|
|
|
// 拉黑/解除拉黑
|
|
async function handleRemove(item: MemberItem) {
|
|
if (item.userType === 2)
|
|
return
|
|
if (item.isBlack === '1') {
|
|
// 直接解除拉黑
|
|
try {
|
|
const res = await request.post('/communityUser/unBlack', {
|
|
communityId: route.query.communityId,
|
|
tenantId: route.query.tenantId, // 用户userId
|
|
userId: item.userId,
|
|
})
|
|
if (res.code === 200) {
|
|
message.success('解除拉黑成功')
|
|
params.value.pageNum = 1
|
|
pagination.value.page = 1
|
|
getMemberList()
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|
|
else {
|
|
// 显示拉黑弹窗
|
|
blackForm.value = {
|
|
blackDay: undefined,
|
|
blackReason: '',
|
|
userId: item.userId,
|
|
}
|
|
showBlackModal.value = true
|
|
}
|
|
}
|
|
|
|
// 确认拉黑
|
|
async function handleBlack() {
|
|
try {
|
|
await formRef.value?.validate()
|
|
const res = await request.post('/communityUser/black', {
|
|
communityId: route.query.communityId,
|
|
tenantId: route.query.tenantId,
|
|
userId: blackForm.value.userId,
|
|
blackDay: blackForm.value.blackDay,
|
|
blackReason: blackForm.value.blackReason,
|
|
})
|
|
if (res.code === 200) {
|
|
message.success('拉黑成功')
|
|
showBlackModal.value = false
|
|
params.value.pageNum = 1
|
|
pagination.value.page = 1
|
|
getMemberList()
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|
|
|
|
// 设置管理员
|
|
async function handleSetAdmin(item: MemberItem) {
|
|
if (item.userType === 2)
|
|
return
|
|
const { tenantId, communityId, userId } = item
|
|
try {
|
|
const res = await request.post('/communityUser/manage', {
|
|
communityId,
|
|
tenantId,
|
|
userId,
|
|
})
|
|
if (res.code === 200) {
|
|
message.success('设置成功')
|
|
params.value.pageNum = 1
|
|
pagination.value.page = 1
|
|
getMemberList()
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|
|
|
|
// 复制文本到剪贴板
|
|
function copyToClipboard(text: string) {
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
message.success('复制成功')
|
|
}).catch(() => {
|
|
message.error('复制失败')
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="min-h-screen bg-[#F7F8FA] px-10 py-6 flex gap-4">
|
|
<div class="bg-white rounded-lg flex-1">
|
|
<div class="flex justify-between items-center m-3 text-sm">
|
|
<div class="bg-[#328afe] text-white px-3 py-1 rounded-sm cursor-pointer">
|
|
分享星球
|
|
</div>
|
|
<div class="relative flex items-center w-[300px]">
|
|
<input
|
|
v-model="params.searchContent"
|
|
type="text"
|
|
placeholder="请输入用户名称"
|
|
class="w-full h-9 pl-4 pr-14 border border-[#eee] rounded-lg text-sm placeholder-[#878D95] outline-none focus:border-[#3f7ef7] focus:ring-1 focus:ring-[#3f7ef7] transition-colors"
|
|
@keyup="handleSearch"
|
|
>
|
|
<button class="absolute right-3 flex items-center space-x-1 text-[#4A5563]">
|
|
<svg class="w-4 h-4" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M7.333 12.667A5.333 5.333 0 1 0 7.333 2a5.333 5.333 0 0 0 0 10.667zM14 14l-2.9-2.9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
<!-- <span class="text-sm font-bold">搜索</span> -->
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-[200px_120px_120px_200px_200px_200px] border-b border-[#eee]">
|
|
<div class="p-3 text-[#1f2329] font-medium">
|
|
全部成员
|
|
</div>
|
|
<div class="p-3 text-[#1f2329] font-medium">
|
|
权限
|
|
</div>
|
|
<div class="p-3 text-[#1f2329] font-medium">
|
|
加入类型
|
|
</div>
|
|
<div class="p-3 text-[#1f2329] font-medium">
|
|
首次加入时间
|
|
</div>
|
|
<div class="p-3 text-[#1f2329] font-medium">
|
|
到期时间
|
|
</div>
|
|
<div class="p-3 text-[#1f2329] font-medium">
|
|
操作
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="loading" class="p-10">
|
|
<n-spin />
|
|
</div>
|
|
|
|
<template v-else>
|
|
<div
|
|
v-for="item in memberList"
|
|
:key="item.id"
|
|
class="grid grid-cols-[200px_120px_120px_200px_200px_200px] border-b border-[#eee] hover:bg-gray-50"
|
|
>
|
|
<div class="p-3 flex items-center gap-2 w-[200px]">
|
|
<img :src="item.avatar" class="w-8 h-8 rounded-full" :alt="item.nickname">
|
|
<span
|
|
class="truncate flex-1 cursor-pointer"
|
|
title="双击复制"
|
|
@dblclick="copyToClipboard(item.nickName)"
|
|
>
|
|
{{ item.nickName }}
|
|
</span>
|
|
</div>
|
|
<div class="p-3 flex items-center">
|
|
{{ item.userType === 0 ? '成员' : item.userType === 1 ? '管理员' : '群主' }}
|
|
</div>
|
|
<div class="p-3 flex items-center">
|
|
{{ item.userType !== 2 ? item.joinType : '-' }}
|
|
</div>
|
|
<div class="p-3 flex items-center">
|
|
{{ item.startTime || '-' }}
|
|
</div>
|
|
<div class="p-3 flex items-center">
|
|
{{ item.endTime || '-' }}
|
|
</div>
|
|
<div class="p-3 w-[300px] flex items-center">
|
|
<div class="w-[100px]">
|
|
<button
|
|
class="text-[#1e80ff] hover:text-[#3b8fff]"
|
|
@click="handleSetAdmin(item)"
|
|
>
|
|
{{ item.userType === 2 ? '-' : item.userType === 0 ? '设为管理员' : '取消管理员' }}
|
|
</button>
|
|
</div>
|
|
<div class="w-[100px]">
|
|
<button
|
|
class="text-[#f85149] hover:text-[#ff6b64]"
|
|
@click="handleRemove(item)"
|
|
>
|
|
{{ item.userType === 2 ? '-' : item.isBlack === '0' ? '拉黑' : '解除拉黑' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<div v-if="isInitialized" class="flex justify-center mt-4">
|
|
<n-pagination
|
|
v-model:page="pagination.page"
|
|
v-model:page-size="pagination.pageSize"
|
|
:item-count="pagination.itemCount"
|
|
:show-size-picker="false"
|
|
@update:page="handlePageChange"
|
|
/>
|
|
</div>
|
|
<n-modal
|
|
v-model:show="showBlackModal"
|
|
:style="{ width: '480px' }"
|
|
:mask-closable="false"
|
|
class="rounded-lg"
|
|
>
|
|
<div class="p-6 bg-white rounded-lg">
|
|
<div class="text-center text-lg font-medium mb-6">
|
|
拉黑成员
|
|
</div>
|
|
<n-form
|
|
ref="formRef"
|
|
:model="blackForm"
|
|
:rules="rules"
|
|
label-placement="left"
|
|
label-width="auto"
|
|
require-mark-placement="right-hanging"
|
|
class="space-y-4"
|
|
>
|
|
<n-form-item label="拉黑时长" path="blackDay">
|
|
<div class="flex items-center gap-2">
|
|
<n-input-number
|
|
v-model:value="blackForm.blackDay"
|
|
placeholder="请输入"
|
|
:min="1"
|
|
@update:value="() => formRef.value?.validate(['blackDay'])"
|
|
/>
|
|
<span class="text-sm">天</span>
|
|
<div class="relative group">
|
|
<div class="i-carbon-information text-gray-400 cursor-help" />
|
|
<div class="absolute left-6 top-0 hidden group-hover:block w-64 p-3 bg-black bg-opacity-75 text-white text-xs rounded-lg">
|
|
拉黑后该成员将不能对星球进行内容发布、点赞、评论内容等操作!拉黑时长结束后将自动解除
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</n-form-item>
|
|
<n-form-item label="拉黑原因" path="blackReason">
|
|
<n-input
|
|
v-model:value="blackForm.blackReason"
|
|
type="textarea"
|
|
placeholder="请输入内容"
|
|
:autosize="{ minRows: 3, maxRows: 5 }"
|
|
class="w-full"
|
|
/>
|
|
</n-form-item>
|
|
</n-form>
|
|
<div class="flex justify-center gap-4 mt-8">
|
|
<n-button
|
|
class="w-24 h-9 hover:opacity-90"
|
|
@click="showBlackModal = false"
|
|
>
|
|
取消
|
|
</n-button>
|
|
<n-button
|
|
type="primary"
|
|
class="w-24 h-9 hover:opacity-90"
|
|
:theme-overrides="{
|
|
common: {
|
|
primaryColor: '#3f7ef7',
|
|
primaryColorHover: '#3f7ef7',
|
|
},
|
|
}"
|
|
@click="handleBlack"
|
|
>
|
|
确定拉黑
|
|
</n-button>
|
|
</div>
|
|
</div>
|
|
</n-modal>
|
|
</div>
|
|
<div class="w-[300px]">
|
|
<PlanetBaseInfo :community-id="route.query.communityId" :tenant-id="route.query.tenantId" />
|
|
</div>
|
|
</div>
|
|
</template>
|