增加文档中心页面

This commit is contained in:
BianLzhaoMin 2025-10-22 17:04:21 +08:00
parent f75931d21c
commit ab6e3eb89d
9 changed files with 1885 additions and 10 deletions

View File

@ -0,0 +1,238 @@
<template>
<div class="left-tree-container">
<el-tree
:data="treeData"
:props="defaultProps"
:expand-on-click-node="false"
:highlight-current="true"
node-key="id"
ref="tree"
@node-click="handleNodeClick"
class="doc-tree"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<i :class="getNodeIcon(data)" class="node-icon"></i>
<span class="node-label">{{ node.label }}</span>
</span>
</el-tree>
</div>
</template>
<script>
export default {
name: 'LeftTree',
data() {
return {
defaultProps: {
children: 'children',
label: 'label',
},
treeData: [
{
id: '1',
label: '我的文档',
type: 'folder',
children: [
{
id: '1-1',
label: '二级菜单一',
type: 'folder',
children: [
{
id: '1-1-1',
label: '三级菜单一',
type: 'folder',
},
{
id: '1-1-2',
label: '三级菜单二',
type: 'folder',
},
],
},
{
id: '1-2',
label: '二级菜单二',
type: 'folder',
children: [
{
id: '1-2-1',
label: '三级菜单一',
type: 'folder',
},
{
id: '1-2-2',
label: '三级菜单二',
type: 'folder',
},
],
},
],
},
{
id: '2',
label: '文档库',
type: 'folder',
children: [
{
id: '2-1',
label: '项目文档',
type: 'folder',
children: [
{
id: '2-1-1',
label: '三级菜单一',
type: 'folder',
},
{
id: '2-1-2',
label: '三级菜单二',
type: 'folder',
},
],
},
{
id: '2-2',
label: '营销文档',
type: 'folder',
children: [
{
id: '2-2-1',
label: '三级菜单一',
type: 'folder',
},
{
id: '2-2-2',
label: '三级菜单二',
type: 'folder',
},
],
},
{
id: '2-3',
label: '财务文档',
type: 'folder',
children: [
{
id: '2-3-1',
label: '三级菜单一',
type: 'folder',
},
{
id: '2-3-2',
label: '三级菜单二',
type: 'folder',
},
],
},
],
},
],
}
},
mounted() {
//
this.$nextTick(() => {
this.expandAll()
})
},
methods: {
//
getNodeIcon(data) {
if (data.type === 'folder') {
return 'el-icon-folder'
}
return 'el-icon-document'
},
//
handleNodeClick(data, node) {
this.$emit('node-click', data, node)
},
//
expandAll() {
const expandKeys = []
const getExpandKeys = (nodes) => {
nodes.forEach((node) => {
if (node.children && node.children.length > 0) {
expandKeys.push(node.id)
getExpandKeys(node.children)
}
})
}
getExpandKeys(this.treeData)
// this.$refs.tree.setExpandedKeys(expandKeys)
},
//
collapseAll() {
// this.$refs.tree.setExpandedKeys([])
},
},
}
</script>
<style scoped lang="scss">
.left-tree-container {
width: 100%;
height: 100%;
background: #fff;
border-radius: 8px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.doc-tree {
.custom-tree-node {
display: flex;
align-items: center;
width: 100%;
.node-icon {
margin-right: 8px;
color: #409eff;
font-size: 16px;
}
.node-label {
flex: 1;
font-size: 14px;
color: #333;
font-family: 'PingFang SC', sans-serif;
}
}
}
//
:deep(.el-tree-node__content) {
height: 40px;
line-height: 40px;
padding: 0 8px;
border-radius: 4px;
margin-bottom: 2px;
transition: all 0.2s ease;
&:hover {
background-color: #f0f7ff;
}
}
:deep(.el-tree-node__content.is-current) {
background-color: #e6f7ff;
color: #1890ff;
}
:deep(.el-tree-node__expand-icon) {
color: #666;
font-size: 14px;
}
:deep(.el-tree-node__expand-icon.is-leaf) {
color: transparent;
}
:deep(.el-tree-node__children) {
padding-left: 16px;
}
</style>

View File

@ -0,0 +1,695 @@
<template>
<div class="right-table-container">
<!-- 顶部操作栏 -->
<div class="action-bar">
<div class="action-buttons">
<el-button
size="small"
:key="item.label"
:type="item.type"
@click="item.click"
v-for="item in buttonList"
>
<i :class="item.icon"></i>
{{ item.label }}
</el-button>
</div>
<div class="search-container">
<el-input placeholder="请输入" clearable class="search-input">
<i slot="suffix" class="el-input__icon el-icon-search"></i>
</el-input>
<el-button type="primary" class="tag-filter-btn">
标签筛选
<i class="el-icon-arrow-down"></i>
</el-button>
</div>
</div>
<!-- 面包屑导航 -->
<div class="breadcrumb-container">
<el-breadcrumb separator=">">
<el-breadcrumb-item>文档库</el-breadcrumb-item>
<el-breadcrumb-item>一级文档</el-breadcrumb-item>
<el-breadcrumb-item>二级文档</el-breadcrumb-item>
<el-breadcrumb-item>×××方案</el-breadcrumb-item>
</el-breadcrumb>
</div>
<!-- 表格内容 -->
<div class="table-container">
<el-table
ref="tableRef"
:data="tableData"
v-loading="loading"
@selection-change="handleSelectionChange"
style="width: 100%"
>
<el-table-column
type="selection"
width="55"
align="center"
></el-table-column>
<el-table-column prop="name" label="名称" min-width="200">
<template slot-scope="scope">
<div class="name-cell">
<i
:class="getFileIcon(scope.row.type)"
class="file-icon"
></i>
<span class="file-name">{{ scope.row.name }}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop="type"
label="类型"
width="100"
align="center"
>
<template slot-scope="scope">
<el-tag
:type="getTypeTagType(scope.row.type)"
size="small"
>
{{ scope.row.type }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="tags" label="标签" width="150">
<template slot-scope="scope">
<div class="tags-cell">
<el-tag
v-for="tag in scope.row.tags"
:key="tag"
size="mini"
type="info"
class="tag-item"
>
{{ tag }}
</el-tag>
</div>
</template>
</el-table-column>
<el-table-column
prop="creator"
label="创建人"
width="100"
align="center"
></el-table-column>
<el-table-column
prop="modifyTime"
label="修改时间"
width="120"
align="center"
></el-table-column>
<el-table-column
prop="createTime"
label="创建时间"
width="120"
align="center"
></el-table-column>
<el-table-column
prop="readCount"
label="阅读"
width="80"
align="center"
>
<template slot-scope="scope">
<span class="count-text">{{
scope.row.readCount
}}</span>
</template>
</el-table-column>
<el-table-column
prop="downloadCount"
label="下载"
width="80"
align="center"
>
<template slot-scope="scope">
<span class="count-text">{{
scope.row.downloadCount
}}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
width="120"
align="center"
fixed="right"
>
<template slot-scope="scope">
<el-button
type="text"
size="mini"
@click="handleView(scope.row)"
>
查看
</el-button>
<el-button
type="text"
size="mini"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页组件 -->
<div class="pagination-container">
<Pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
<!-- 批量下载弹框 -->
<DialogModel
:dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseDialogOuter"
>
<template #outerContent>
<DownloadTags
v-if="dialogConfig.outerTitle === '批量下载'"
:selectedFiles="selectedFilesForDownload"
@remove-file="handleRemoveFile"
/>
<SharePermissionForm
v-if="dialogConfig.outerTitle === '共享'"
:selectedFiles="selectedFilesForShare"
@cancel="handleCloseShareDialog"
@confirm="handleShareConfirm"
/>
<AddWord v-if="dialogConfig.outerTitle === '新建文档夹'" />
<Upload v-if="dialogConfig.outerTitle === '上传文件'" />
<Move v-if="dialogConfig.outerTitle === '移动'" />
<AddCopy v-if="dialogConfig.outerTitle === '添加副本'" />
<div class="button-footer">
<el-button type="info" size="mini" @click="onHandleCancel">
取消
</el-button>
<el-button
type="primary"
size="mini"
@click="onHandleConfirm"
>
确定
</el-button>
</div>
</template>
</DialogModel>
</div>
</template>
<script>
import Pagination from '@/components/Pagination'
import DialogModel from '@/components/DialogModel'
import DownloadTags from './tableCom/downLoad.vue'
import SharePermissionForm from './tableCom/share.vue'
import AddWord from './tableCom/addWord.vue'
import Upload from './tableCom/upload.vue'
import Move from './tableCom/move.vue'
import AddCopy from './tableCom/addCopy.vue'
export default {
name: 'RightTable',
components: {
Pagination,
DialogModel,
DownloadTags,
SharePermissionForm,
AddWord,
Upload,
Move,
AddCopy,
},
data() {
return {
loading: false,
total: 0,
selectedRows: [],
queryParams: {
pageNum: 1,
pageSize: 10,
},
tableData: [
{
id: 1,
name: '资质文件',
type: '文件夹',
tags: [],
creator: '李林',
modifyTime: '2024-10-21 17:10',
createTime: '2024-10-21 17:10',
readCount: 1,
downloadCount: 1,
},
{
id: 2,
name: '×××建设方案.docx',
type: 'docx',
tags: ['基建'],
creator: '李林',
modifyTime: '2024-10-21 17:10',
createTime: '2024-10-21 17:10',
readCount: 1,
downloadCount: 1,
},
{
id: 3,
name: '×××可行方案.pdf',
type: 'pdf',
tags: ['基建', '巡检'],
creator: '李林',
modifyTime: '2024-10-21 17:10',
createTime: '2024-10-21 17:10',
readCount: 0,
downloadCount: 0,
},
{
id: 4,
name: '×××可行方案.pdf',
type: 'pdf',
tags: ['基建', '巡检'],
creator: '李林',
modifyTime: '2024-10-21 17:10',
createTime: '2024-10-21 17:10',
},
{
id: 5,
name: '×××可行方案.pdf',
type: 'pdf',
tags: ['基建', '巡检'],
creator: '李林',
modifyTime: '2024-10-21 17:10',
createTime: '2024-10-21 17:10',
},
{
id: 6,
name: '×××可行方案.pdf',
type: 'pdf',
tags: ['基建', '巡检'],
creator: '李林',
modifyTime: '2024-10-21 17:10',
createTime: '2024-10-21 17:10',
},
{
id: 7,
name: '×××可行方案.pdf',
type: 'pdf',
tags: ['基建', '巡检'],
creator: '李林',
modifyTime: '2024-10-21 17:10',
createTime: '2024-10-21 17:10',
},
],
buttonList: [
{
label: '新建',
icon: 'el-icon-plus',
type: 'primary',
click: this.handleNew,
},
{
label: '上传',
icon: 'el-icon-upload',
type: 'success',
click: this.handleUpload,
},
{
label: '移动',
icon: 'el-icon-sort',
type: 'warning',
click: this.handleMove,
},
{
label: '删除',
icon: 'el-icon-delete',
type: 'danger',
click: this.handleDelete,
},
{
label: '批量下载',
icon: 'el-icon-download',
type: 'info',
click: this.handleBatchDownload,
},
{
label: '共享',
icon: 'el-icon-share',
type: 'primary',
click: this.handleShare,
},
{
label: '添加副本',
icon: 'el-icon-copy-document',
type: 'success',
click: this.handleAddCopy,
},
],
dialogConfig: {
outerTitle: '批量下载',
outerVisible: false,
outerWidth: '50%',
},
//
selectedFilesForDownload: [],
//
selectedFilesForShare: [],
}
},
mounted() {
this.getList()
},
methods: {
//
getFileIcon(type) {
if (type === '文件夹') {
return 'el-icon-folder'
} else if (type === 'docx') {
return 'el-icon-document'
} else if (type === 'pdf') {
return 'el-icon-document'
}
return 'el-icon-document'
},
//
getTypeTagType(type) {
if (type === '文件夹') {
return 'warning'
} else if (type === 'docx') {
return 'primary'
} else if (type === 'pdf') {
return 'danger'
}
return 'info'
},
//
getList() {
this.loading = true
// API
setTimeout(() => {
this.total = 50 //
this.loading = false
}, 500)
},
//
handleSelectionChange(selection) {
this.selectedRows = selection
},
//
//
handleNew() {
// this.$emit('new')
this.dialogConfig.outerTitle = '新建文档夹'
this.dialogConfig.outerVisible = true
},
//
handleUpload() {
// this.$emit('upload')
this.dialogConfig.outerTitle = '上传文件'
this.dialogConfig.outerVisible = true
},
//
handleMove() {
// this.$emit('move', this.selectedRows)
this.dialogConfig.outerTitle = '移动'
this.dialogConfig.outerVisible = true
},
//
handleDelete() {
if (this.selectedRows.length === 0) {
this.$modal.msgWarning('请选择要删除的文件')
return
}
// this.$emit('delete', this.selectedRows)
this.$confirm(
'所选中文档及对应的映射文档将被删除, 且该操作不可恢复, 确认吗?\n该操作会重新配置文档或文档夹的权限, 确认继续吗?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
)
.then(() => {
this.$modal.msgSuccess('删除功能待实现')
})
.catch(() => {
this.$modal.msgInfo('已取消删除')
})
},
//
handleBatchDownload() {
if (this.selectedRows.length === 0) {
this.$modal.msgWarning('请选择要下载的文件')
return
}
//
this.selectedFilesForDownload = this.selectedRows.map((row) => ({
id: row.id,
name: row.name,
}))
this.dialogConfig.outerTitle = '批量下载'
this.dialogConfig.outerVisible = true
},
//
handleShare() {
if (this.selectedRows.length === 0) {
this.$modal.msgWarning('请选择要共享的文件')
return
}
//
this.selectedFilesForShare = this.selectedRows.map((row) => ({
id: row.id,
name: row.name,
}))
this.dialogConfig.outerTitle = '共享'
this.dialogConfig.outerVisible = true
},
//
handleAddCopy() {
// this.$emit('add-copy', this.selectedRows)
this.dialogConfig.outerTitle = '添加副本'
this.dialogConfig.outerVisible = true
},
//
handleView(row) {
this.$emit('view', row)
},
//
handleEdit(row) {
this.$emit('edit', row)
},
//
handleCloseDialogOuter() {
this.dialogConfig.outerVisible = false
},
//
handleRemoveFile(index) {
this.$refs.tableRef.toggleRowSelection(this.selectedRows[index])
//
if (this.selectedFilesForDownload.length === 0) {
this.dialogConfig.outerVisible = false
} else {
this.selectedFilesForDownload = this.selectedRows.map(
(row) => ({
id: row.id,
name: row.name,
}),
)
}
},
//
onHandleCancel() {
this.dialogConfig.outerVisible = false
},
//
onHandleConfirm() {
this.dialogConfig.outerVisible = false
},
//
handleCloseShareDialog() {
this.shareDialogConfig.outerVisible = false
},
//
handleShareConfirm(data) {
console.log('共享权限设置:', data)
this.shareDialogConfig.outerVisible = false
this.$modal.msgSuccess('权限设置成功')
},
},
}
</script>
<style scoped lang="scss">
.right-table-container {
width: 100%;
height: 100%;
padding: 14px;
box-sizing: border-box;
background: #fff;
// background-color: pink;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
overflow: hidden;
overflow-y: auto;
}
.action-bar {
display: flex;
justify-content: space-between;
align-items: center;
background: #f0f7ff;
padding: 12px 16px;
border-bottom: 1px solid #e6f7ff;
.action-buttons {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.search-container {
display: flex;
align-items: center;
gap: 12px;
justify-content: flex-end;
.search-input {
width: 200px;
}
.tag-filter-btn {
display: flex;
align-items: center;
gap: 4px;
}
}
}
.breadcrumb-container {
padding: 12px 16px;
border-bottom: 1px solid #f0f0f0;
background: #fafafa;
}
.table-container {
flex: 1;
overflow: auto;
.name-cell {
display: flex;
align-items: center;
.file-icon {
margin-right: 8px;
color: #409eff;
font-size: 16px;
}
.file-name {
font-size: 14px;
color: #333;
}
}
.tags-cell {
display: flex;
flex-wrap: wrap;
gap: 4px;
.tag-item {
margin: 0;
}
}
.count-text {
color: #666;
font-size: 14px;
}
}
.pagination-container {
// padding: 16px;
display: flex;
align-items: center;
justify-content: flex-end;
}
//
:deep(.el-table) {
.el-table__header {
th {
background-color: #fafafa;
color: #333;
font-weight: 600;
}
}
.el-table__body {
tr:hover {
background-color: #f5f7fa;
}
}
}
:deep(.el-button--text) {
padding: 4px 8px;
font-size: 12px;
}
.button-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
border-top: 1px solid #e0e0e0;
padding-top: 10px;
}
</style>

View File

@ -0,0 +1,9 @@
<template>
<div> 添加副本 </div>
</template>
<script>
export default {}
</script>
<style></style>

View File

@ -0,0 +1,35 @@
<template>
<div>
<el-form
:model="addWordForm"
:rules="addWordFormRules"
label-width="100px"
>
<el-form-item label="文档夹名称" prop="name">
<el-input v-model="addWordForm.name" />
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: 'AddWord',
data() {
return {
addWordForm: {
name: '',
},
addWordFormRules: {
name: [
{
required: true,
message: '请输入文档夹名称',
trigger: 'blur',
},
],
},
}
},
}
</script>

View File

@ -0,0 +1,151 @@
<template>
<div class="download-tags-container">
<!-- 标题 -->
<div class="title">您勾选下载了以下文件:</div>
<!-- 标签列表 -->
<div class="tags-wrapper">
<div
v-for="(file, index) in displayFiles"
:key="index"
class="tag-item"
>
<span class="tag-text">{{ file.name }}</span>
<i
class="el-icon-close tag-close"
@click="removeFile(index, file)"
></i>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DownloadTags',
props: {
//
selectedFiles: {
type: Array,
default: () => [],
},
},
data() {
return {
// 使props
defaultFiles: [
{ name: '可行方案.docx' },
{ name: '可行方案.docx' },
{ name: '可行方案.docx' },
{ name: '可行方案.docx' },
{ name: '资质文件' },
{ name: '可行方案.docx' },
{ name: '可行方案.docx' },
{ name: '可行方案.docx' },
],
}
},
computed: {
// 使props
displayFiles() {
return this.selectedFiles.length > 0
? this.selectedFiles
: this.defaultFiles
},
},
methods: {
//
removeFile(index, row) {
// 使props
if (this.selectedFiles.length > 0) {
this.$emit('remove-file', index)
} else {
// 使
this.defaultFiles.splice(index, 1)
}
},
},
}
</script>
<style scoped lang="scss">
.download-tags-container {
padding: 20px;
background: #fff;
border-radius: 8px;
.title {
font-size: 16px;
font-weight: 600;
color: #333;
margin-bottom: 16px;
line-height: 1.5;
}
.tags-wrapper {
// display: flex;
// flex-wrap: wrap;
// gap: 8px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 10px;
.tag-item {
display: flex;
align-items: center;
justify-content: center;
padding: 6px 12px;
background: #f5f5f5;
border: 1px solid #e0e0e0;
border-radius: 4px;
font-size: 14px;
color: #666;
transition: all 0.3s ease;
&:hover {
background: #e8e8e8;
border-color: #d0d0d0;
}
.tag-text {
margin-right: 6px;
// white-space: nowrap;
}
.tag-close {
font-size: 14px;
color: #999;
cursor: pointer;
transition: color 0.3s ease;
text-decoration: none;
font-style: normal;
&:hover {
color: #666;
}
}
}
}
}
//
@media (max-width: 768px) {
.download-tags-container {
padding: 16px;
.title {
font-size: 14px;
}
.tags-wrapper {
gap: 6px;
.tag-item {
padding: 4px 8px;
font-size: 12px;
}
}
}
}
</style>

View File

@ -0,0 +1,9 @@
<template>
<div> 移动 </div>
</template>
<script>
export default {}
</script>
<style></style>

View File

@ -0,0 +1,227 @@
<template>
<div class="permission-form">
<el-form
ref="permissionForm"
:model="form"
:rules="rules"
label-width="100px"
class="permission-form-content"
>
<!-- 授权对象 -->
<el-form-item
label="授权对象"
prop="authorizedObject"
class="form-item"
>
<el-select
v-model="form.authorizedObject"
placeholder="请选择"
clearable
filterable
style="width: 100%"
@change="handleAuthorizedObjectChange"
>
<el-option
v-for="item in authorizedObjectOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<!-- 权限设置 -->
<el-form-item label="权限" prop="permission" class="form-item">
<el-radio-group
v-model="form.permission"
@change="handlePermissionChange"
>
<div class="permission-options">
<el-radio label="view" class="permission-radio">
仅可查看
</el-radio>
<el-radio
label="view_download"
class="permission-radio"
>
可查看/下载
</el-radio>
<el-radio label="edit" class="permission-radio">
可编辑
</el-radio>
<el-radio label="manage" class="permission-radio">
可管理
</el-radio>
</div>
</el-radio-group>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: 'SharePermissionForm',
props: {
//
visible: {
type: Boolean,
default: false,
},
//
selectedFiles: {
type: Array,
default: () => [],
},
},
data() {
return {
loading: false,
form: {
authorizedObject: '', //
permission: 'view', //
},
rules: {
authorizedObject: [
{
required: true,
message: '请选择授权对象',
trigger: 'change',
},
],
permission: [
{
required: true,
message: '请选择权限',
trigger: 'change',
},
],
},
//
authorizedObjectOptions: [
{ value: 'user_001', label: '张三' },
{ value: 'user_002', label: '李四' },
{ value: 'user_003', label: '王五' },
{ value: 'dept_001', label: '技术部' },
{ value: 'dept_002', label: '产品部' },
{ value: 'role_001', label: '管理员' },
{ value: 'role_002', label: '编辑者' },
],
}
},
watch: {
visible(newVal) {
if (newVal) {
this.resetForm()
}
},
},
methods: {
//
resetForm() {
this.form = {
authorizedObject: '',
permission: 'view',
}
this.$nextTick(() => {
this.$refs.permissionForm &&
this.$refs.permissionForm.clearValidate()
})
},
//
handleAuthorizedObjectChange(value) {
console.log('授权对象变化:', value)
},
//
handlePermissionChange(value) {
console.log('权限变化:', value)
},
},
}
</script>
<style scoped lang="scss">
.permission-form {
padding: 20px;
background: #fff;
border-radius: 8px;
.permission-form-content {
.form-item {
margin-bottom: 24px;
:deep(.el-form-item__label) {
font-weight: 600;
color: #333;
font-size: 14px;
}
:deep(.el-form-item__content) {
line-height: normal;
}
}
.permission-options {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
width: 100%;
.permission-radio {
margin: 0;
padding: 12px 16px;
border: 1px solid #e0e0e0;
border-radius: 6px;
background: #fafafa;
transition: all 0.3s ease;
&:hover {
border-color: #409eff;
background: #f0f7ff;
}
:deep(.el-radio__input.is-checked + .el-radio__label) {
color: #409eff;
font-weight: 600;
}
:deep(.el-radio__input.is-checked .el-radio__inner) {
background-color: #409eff;
border-color: #409eff;
}
:deep(.el-radio__label) {
font-size: 14px;
color: #333;
padding-left: 8px;
}
}
}
}
.form-actions {
display: flex;
justify-content: flex-end;
gap: 12px;
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #e0e0e0;
.el-button {
min-width: 80px;
}
}
}
//
@media (max-width: 768px) {
.permission-form {
.permission-options {
grid-template-columns: 1fr;
gap: 12px;
}
}
}
</style>

View File

@ -0,0 +1,353 @@
<template>
<div class="upload-dialog">
<div class="upload-form">
<!-- 导入重复时处理方式 -->
<div class="form-item">
<label class="form-label">导入重复时:</label>
<div class="radio-group">
<el-radio v-model="duplicateHandle" label="skip"
>跳过</el-radio
>
<el-radio v-model="duplicateHandle" label="overwrite"
>覆盖</el-radio
>
</div>
</div>
<!-- 文件标签选择 -->
<div class="form-item">
<label class="form-label">文件标签:</label>
<el-select
v-model="selectedTag"
placeholder="请选择"
clearable
class="tag-select"
>
<el-option
v-for="tag in tagOptions"
:key="tag.value"
:label="tag.label"
:value="tag.value"
/>
</el-select>
</div>
<!-- 文件上传区域 -->
<div class="form-item upload-item">
<label class="form-label">上传:</label>
<div class="upload-container">
<el-upload
ref="upload"
:action="uploadUrl"
:headers="headers"
:data="uploadData"
:file-list="fileList"
:before-upload="handleBeforeUpload"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:limit="10"
:auto-upload="false"
multiple
drag
class="upload-dragger"
>
<div class="upload-content">
<i class="el-icon-upload upload-icon"></i>
<div class="upload-text">
将文件拖到此处或
<em class="upload-link">点击上传</em>
</div>
<div class="upload-tip">
按住Ctrl可同时多选,支持上传rar/zip格式文件,单个文件不能超过500kb
</div>
<div class="upload-warning">
严禁上传包含色情暴力反动等相关违法信息的文件
</div>
</div>
</el-upload>
</div>
</div>
</div>
</div>
</template>
<script>
import { getToken } from '@/utils/auth'
export default {
name: 'UploadDialog',
props: {
visible: {
type: Boolean,
default: false,
},
},
data() {
return {
dialogVisible: false,
duplicateHandle: 'skip', // skip-overwrite-
selectedTag: '', //
fileList: [], //
uploading: false, //
uploadUrl: process.env.VUE_APP_BASE_API + '/common/upload', //
headers: {
Authorization: 'Bearer ' + getToken(),
},
//
tagOptions: [
{ label: '技术文档', value: 'tech' },
{ label: '产品文档', value: 'product' },
{ label: '设计文档', value: 'design' },
{ label: '测试文档', value: 'test' },
{ label: '其他', value: 'other' },
],
}
},
watch: {
visible: {
handler(val) {
this.dialogVisible = val
},
immediate: true,
},
},
computed: {
//
uploadData() {
return {
duplicateHandle: this.duplicateHandle,
fileTag: this.selectedTag,
}
},
},
methods: {
//
handleClose() {
this.dialogVisible = false
this.$emit('update:visible', false)
this.resetForm()
},
//
resetForm() {
this.duplicateHandle = 'skip'
this.selectedTag = ''
this.fileList = []
this.uploading = false
this.$refs.upload && this.$refs.upload.clearFiles()
},
//
handleBeforeUpload(file) {
//
const allowedTypes = ['rar', 'zip']
const fileExtension = file.name.split('.').pop().toLowerCase()
if (!allowedTypes.includes(fileExtension)) {
this.$modal.msgError('只支持上传rar/zip格式文件!')
return false
}
// (500kb = 0.5MB)
const maxSize = 0.5
const isLtMaxSize = file.size / 1024 / 1024 < maxSize
if (!isLtMaxSize) {
this.$modal.msgError(`文件大小不能超过 ${maxSize}MB!`)
return false
}
//
if (file.name.includes(',')) {
this.$modal.msgError('文件名不能包含英文逗号!')
return false
}
return true
},
//
handleUploadSuccess(response, file, fileList) {
if (response.code === 200) {
this.$modal.msgSuccess('文件上传成功!')
this.$emit('upload-success', {
file: file,
response: response,
duplicateHandle: this.duplicateHandle,
fileTag: this.selectedTag,
})
} else {
this.$modal.msgError(response.msg || '上传失败!')
}
},
//
handleUploadError(err, file, fileList) {
this.$modal.msgError('文件上传失败,请重试!')
console.error('上传失败:', err)
},
//
handleRemove(file, fileList) {
this.fileList = fileList
},
//
handleExceed(files, fileList) {
this.$modal.msgError('最多只能上传10个文件!')
},
//
handleConfirm() {
if (this.fileList.length === 0) {
this.$modal.msgWarning('请选择要上传的文件!')
return
}
if (!this.selectedTag) {
this.$modal.msgWarning('请选择文件标签!')
return
}
this.uploading = true
this.$refs.upload.submit()
//
setTimeout(() => {
this.uploading = false
this.handleClose()
}, 2000)
},
},
}
</script>
<style scoped lang="scss">
.upload-form {
.form-item {
display: flex;
align-items: center;
margin-bottom: 20px;
.form-label {
width: 100px;
text-align: right;
margin-right: 16px;
font-size: 14px;
color: #606266;
flex-shrink: 0;
}
.radio-group {
display: flex;
gap: 20px;
}
.tag-select {
width: 200px;
}
&.upload-item {
align-items: flex-start;
.form-label {
margin-top: 8px;
}
}
}
.upload-container {
flex: 1;
.upload-dragger {
width: 100%;
::v-deep .el-upload-dragger {
width: 100%;
height: 200px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
background-color: #fafafa;
transition: border-color 0.3s;
&:hover {
border-color: #409eff;
}
}
.upload-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
padding: 20px;
.upload-icon {
font-size: 48px;
color: #c0c4cc;
margin-bottom: 16px;
}
.upload-text {
font-size: 14px;
color: #606266;
margin-bottom: 8px;
.upload-link {
color: #409eff;
font-style: normal;
cursor: pointer;
}
}
.upload-tip {
font-size: 12px;
color: #909399;
margin-bottom: 8px;
text-align: center;
line-height: 1.4;
}
.upload-warning {
font-size: 12px;
color: #f56c6c;
text-align: center;
line-height: 1.4;
}
}
}
}
}
.dialog-footer {
text-align: right;
padding-top: 20px;
border-top: 1px solid #e4e7ed;
}
//
@media (max-width: 768px) {
.upload-dialog {
.upload-form {
.form-item {
flex-direction: column;
align-items: flex-start;
.form-label {
width: auto;
text-align: left;
margin-right: 0;
margin-bottom: 8px;
}
.tag-select {
width: 100%;
}
}
}
}
}
</style>

View File

@ -1,25 +1,183 @@
<template>
<!-- 文档中心 -->
<div class="doc-center"> 文档中心正在开发中敬请期待... </div>
<div class="doc-center">
<!-- 顶部搜索栏 -->
<!-- 主要内容区域 -->
<div class="main-content">
<!-- 左侧树形导航 -->
<div class="left-sidebar">
<LeftTree @node-click="handleNodeClick" />
</div>
<!-- 右侧表格内容 -->
<div class="right-content">
<RightTable
@new="handleNew"
@upload="handleUpload"
@move="handleMove"
@delete="handleDelete"
@batch-download="handleBatchDownload"
@share="handleShare"
@add-copy="handleAddCopy"
@view="handleView"
@edit="handleEdit"
/>
</div>
</div>
</div>
</template>
<script>
import LeftTree from './components/leftTree.vue'
import RightTable from './components/rightTable.vue'
export default {
name: 'DocCenter',
components: {
LeftTree,
RightTable,
},
data() {
return {
searchKeyword: '',
selectedNode: null,
}
},
methods: {
//
handleNodeClick(data, node) {
this.selectedNode = data
console.log('选中节点:', data)
},
//
handleNew() {
this.$modal.msgSuccess('新建功能待实现')
},
//
handleUpload() {
this.$modal.msgSuccess('上传功能待实现')
},
//
handleMove(selectedRows) {
this.$modal.msgSuccess('移动功能待实现')
},
//
handleDelete(selectedRows) {
this.$confirm('确定要删除选中的文档吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.$modal.msgSuccess('删除功能待实现')
})
.catch(() => {
this.$modal.msgInfo('已取消删除')
})
},
//
handleBatchDownload(selectedRows) {
this.$modal.msgSuccess('批量下载功能待实现')
},
//
handleShare(selectedRows) {
this.$modal.msgSuccess('共享功能待实现')
},
//
handleAddCopy(selectedRows) {
this.$modal.msgSuccess('添加副本功能待实现')
},
//
handleView(row) {
this.$modal.msgSuccess('查看功能待实现')
},
//
handleEdit(row) {
this.$modal.msgSuccess('编辑功能待实现')
},
},
}
</script>
<style scoped>
<style scoped lang="scss">
.doc-center {
width: 100%;
height: 100%;
background-color: #f0f2f5;
font-size: 16px;
color: #333;
text-align: center;
line-height: 1.5;
letter-spacing: 1px;
font-weight: 600;
font-family: 'Arial', sans-serif;
}
// .search-header {
// background: #e6f7ff;
// padding: 16px 20px;
// border-bottom: 1px solid #d9d9d9;
// .search-container {
// display: flex;
// align-items: center;
// gap: 12px;
// justify-content: flex-end;
// .search-input {
// width: 200px;
// }
// .tag-filter-btn {
// display: flex;
// align-items: center;
// gap: 4px;
// }
// }
// }
.main-content {
height: 100%;
flex: 1;
display: flex;
gap: 16px;
padding: 16px 20px;
overflow: hidden;
.left-sidebar {
width: 280px;
flex-shrink: 0;
height: 100%;
}
.right-content {
flex: 1;
height: 100%;
// background-color: skyblue;
// overflow: hidden;
}
}
//
@media (max-width: 1200px) {
.main-content {
.left-sidebar {
width: 240px;
}
}
}
@media (max-width: 768px) {
.main-content {
flex-direction: column;
.left-sidebar {
width: 100%;
height: 200px;
}
}
}
</style>