mcwl-pc/app/pages/planetAllFile/index.vue

368 lines
11 KiB
Vue

<script setup lang="ts">
import { formatFileSize } from '@/utils/index.ts'
import { uploadFileBatches } from '@/utils/uploadImg'
import { useMessage } from 'naive-ui'
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
interface MemberItem {
communityId: number
createTime: string
downloadFileUser: {
avatarList: string[]
count: number
}
fileName: string
fileSize: number
id: number
tenantId: number
uploadUserName: 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: 2,
communityId: route.query.communityId,
tenantId: route.query.tenantId,
search: '',
})
// 添加分页数据
const pagination = ref({
page: 1,
pageSize: 2,
itemCount: 0,
showSizePicker: false,
})
// 处理分页变化
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('/communityFile/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 handleSetAdmin(item: MemberItem) {
const { id, fileName } = item
const res = await request.post('/communityFile/download', {
communityId: route.query.communityId,
tenantId: route.query.tenantId,
fileId: id,
})
if (res.code === 200) {
const { data } = res
// 创建临时下载链接
const link = document.createElement('a')
link.href = data
link.download = fileName // 使用原始文件名
link.style.display = 'none'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
}
// 复制文本到剪贴板
function copyToClipboard(text: string) {
navigator.clipboard.writeText(text).then(() => {
message.success('复制成功')
}).catch(() => {
message.error('复制失败')
})
}
const pictureInput = ref<HTMLInputElement | null>(null)
function handlePictureInput() {
pictureInput.value?.click()
}
// 允许的文件类型
const allowedFileTypes = [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-powerpoint',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'text/plain',
'application/zip',
]
async function handlePictureChange(event: Event) {
const files = (event.target as HTMLInputElement).files
if (!files || files.length === 0)
return
if (files.length > 1) {
message.error('只能选择 1 个文件')
return
}
const file = files[0]
if (!allowedFileTypes.includes(file.type)) {
message.error('只支持 PDF、Word、Excel、PPT、TXT 和 ZIP 文件')
return
}
try {
const res = await uploadFileBatches([file])
;(event.target as HTMLInputElement).value = ''
const { fileName, objectKey, path, size } = res[0]
const res1 = await request.post('/communityFile/upload', {
communityId: route.query.communityId,
tenantId: route.query.tenantId,
fileName,
objectKey,
fileSize: size,
fileUrl: path,
})
if (res1.code === 200) {
message.success('文件上传成功')
params.value.search = ''
params.value.pageNum = 1
pagination.value.page = 1
getMemberList()
}
}
catch (error) {
console.error(error)
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="flex items-center gap-2">
<div class="bg-[#328afe] text-white px-3 py-1 rounded-sm cursor-pointer" @click="handlePictureInput">
</div>
<div>
<!-- 111 -->
</div>
</div>
<div class="relative flex items-center w-[300px]">
<input
v-model="params.search"
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-[300px_150px_150px_200px_130px_100px] 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-[300px_150px_150px_200px_130px_100px] border-b border-[#eee] hover:bg-gray-50"
>
<div class="p-3 flex items-center gap-2">
<!-- <img :src="item.avatar" class="w-8 h-8 rounded-full" :alt="item.nickname"> -->
<span
class="truncate flex-1 cursor-pointer"
:title="item.fileName"
@dblclick="copyToClipboard(item.fileName)"
>
{{ item.fileName }}
</span>
</div>
<div class="p-3 flex items-center">
{{ formatFileSize(item.fileSize) }}
</div>
<div class="p-3 flex items-center">
{{ item.uploadUserName || '-' }}
</div>
<div class="p-3 flex items-center">
{{ item.createTime }}
</div>
<div class="p-3 flex items-center">
{{ item.downloadFileUser.count }}
</div>
<div class="p-3 flex items-center">
<div class="w-[100px]">
<button
class="text-[#1e80ff] hover:text-[#3b8fff]"
@click="handleSetAdmin(item)"
>
下载
</button>
</div>
</div>
</div>
</template>
<div v-if="isInitialized && memberList.length > 0" 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>
<div v-else class="flex justify-center mt-10">
暂无数据
</div>
<input
ref="pictureInput"
type="file"
accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip"
class="hidden"
@change="handlePictureChange"
>
</div>
<div class="w-[300px]">
<PlanetBaseInfo :community-id="route.query.communityId" :tenant-id="route.query.tenantId" />
</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>
</template>