交通管理局公文项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

734 lines
27 KiB

<template>
<div class="app-container row-container">
<div class="filing-cabinet-wrapper">
<div class="file-cabinet">
<div class="cabinet-grid">
<div class="cabinet-column">
<div
v-for="(item, index) in cabinetColumns[0]"
:key="'col1-' + index"
:class="['cabinet-cell', { 'cabinet-cell-ld': item.type === 'ld', 'cabinet-cell-department': item.type === 'department', 'cabinet-cell-big': item.type === 'big', 'cabinet-cell-selected': selectedCell === item.id, 'cabinet-cell-unbound': !item.bound }]"
@click="selectCell(item)"
>
<span class="cell-id">{{ item.id }}</span>
<!-- <span v-if="item.type === 'ld'" class="cell-label">{{ item.bound ? item.borrowName : '' }}</span> -->
<span class="cell-label">{{ item.bound ? item.borrowName : '' }}</span>
<span v-if="item.documentCount > 0" class="cell-file-count">{{ item.documentCount }}</span>
</div>
</div>
<div class="cabinet-column">
<div
v-for="(item, index) in cabinetColumns[1]"
:key="'col2-' + index"
:class="['cabinet-cell', { 'cabinet-cell-ld': item.type === 'ld', 'cabinet-cell-department': item.type === 'department', 'cabinet-cell-big': item.type === 'big', 'cabinet-cell-selected': selectedCell === item.id, 'cabinet-cell-unbound': !item.bound }]"
@click="selectCell(item)"
>
<span class="cell-id">{{ item.id }}</span>
<span class="cell-label">{{ item.bound ? item.borrowName : '' }}</span>
<span v-if="item.documentCount > 0" class="cell-file-count">{{ item.documentCount }}</span>
</div>
</div>
<div class="cabinet-column">
<div
v-for="(item, index) in cabinetColumns[2]"
:key="'col3-' + index"
:class="['cabinet-cell', { 'cabinet-cell-ld': item.type === 'ld', 'cabinet-cell-department': item.type === 'department', 'cabinet-cell-big': item.type === 'big', 'cabinet-cell-selected': selectedCell === item.id, 'cabinet-cell-unbound': !item.bound }]"
@click="selectCell(item)"
>
<span class="cell-id">{{ item.id }}</span>
<span class="cell-label">{{ item.bound ? item.borrowName : '' }}</span>
<span v-if="item.documentCount > 0" class="cell-file-count">{{ item.documentCount }}</span>
</div>
</div>
<div class="cabinet-column">
<div
v-for="(item, index) in cabinetColumns[3]"
:key="'col4-' + index"
:class="['cabinet-cell', { 'cabinet-cell-ld': item.type === 'ld', 'cabinet-cell-department': item.type === 'department', 'cabinet-cell-big': item.type === 'big', 'cabinet-cell-selected': selectedCell === item.id, 'cabinet-cell-unbound': !item.bound }]"
@click="selectCell(item)"
>
<span class="cell-id">{{ item.id }}</span>
<span class="cell-label">{{ item.bound ? item.borrowName : '' }}</span>
<span v-if="item.documentCount > 0" class="cell-file-count">{{ item.documentCount }}</span>
</div>
</div>
</div>
</div>
<div class="content-wrap">
<div v-if="selectedCellInfo" class="cabinet-info">
<div class="cabinet-info-title">
<p class="title-left">层位信息</p>
</div>
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="display: flex; justify-content: flex-start;">
<div class="info-row">
<span class="info-label">编号:</span>
<span class="info-value">{{ selectedCellInfo.id }}</span>
</div>
<div class="info-row">
<span class="info-label">绑定状态:</span>
<span :class="['info-value', !selectedCellInfo.bound ? 'unbound' : '']">
{{ selectedCellInfo.bound ? '已绑定' : '未绑定' }}
</span>
</div>
<div class="info-row">
<span class="info-label">绑定目标:</span>
<span class="info-value">
{{ selectedCellInfo.bound ? selectedCellInfo.borrowName : '-' }}
</span>
</div>
</div>
<div>
<el-button v-if="!selectedCellInfo.bound" size="mini" @click="borrowerListVisible = true">
<i class="iconfont icon-bendiguajie" />
绑定
</el-button>
<el-button v-else :loading="unbindLoading" class="unbind-btn" size="mini" @click="unbindCell">
<i class="iconfont icon-jiebang" />
解绑
</el-button>
</div>
</div>
</div>
<div class="container-wrap">
<span class="right-top-line" />
<span class="left-bottom-line" />
<div class="cabinet-table-title">
<p class="title-left">在架信息</p>
<span>共 <i style="color: #1890ff; font-weight: bold;">{{ miodData.length }}</i> 件</span>
</div>
<el-table
ref="table"
v-loading="tableLoading"
class="archives-table"
:data="miodData"
style="width: 100%;"
height="calc(100vh - 334px)"
@cell-dblclick="tableDoubleClick"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="regNo" label="收文号" width="120" />
<el-table-column prop="detailsType" label="文件类型" width="100">
<template slot-scope="scope">
<el-tag v-if="scope.row.detailsType === 1">原件</el-tag>
<el-tag v-else>复印件</el-tag>
</template>
</el-table-column>
<el-table-column prop="maintitle" label="公文题名" min-width="140" show-overflow-tooltip />
<el-table-column prop="docNo" label="来文字号" min-width="120" />
<el-table-column prop="docDepartment" label="所属文件" width="120" />
<el-table-column prop="actual_return_time" label="操作" align="center" width="140">
<template slot-scope="scope">
<el-button size="mini" style="padding: 5px;" :loading="removalLoaing[scope.$index]" @click="handleBatchDel(scope.$index, scope.row)">
<i class="iconfont icon-xiajia" />
手动下架
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
<el-dialog :close-on-click-modal="false" :modal-append-to-body="false" append-to-body title="绑定借阅者" :visible.sync="borrowerListVisible">
<div class="setting-dialog">
<div style="display: flex; justify-content: flex-start; margin-bottom: 15px;">
<el-input v-model="query.search" clearable size="small" placeholder="输入借阅者名称搜索" prefix-icon="el-icon-search" style="width: 200px;" class="filter-item" @keyup.enter.native="handleSearch" />
<el-button class="filter-item filter-search" size="mini" type="success" icon="el-icon-search" style="margin-left: 10px;" @click="handleSearch">搜索</el-button>
<el-button class="filter-item filter-refresh" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetSearch">重置</el-button>
</div>
<el-table
ref="borrowerTable"
v-loading="borrowerListLoading"
:data="borrowerList"
row-key="id"
height="440px"
>
<el-table-column prop="borrowName" label="借阅者名称" />
<el-table-column prop="borrowType" label="借阅者类型">
<template slot-scope="scope">
<div>
<span v-if="scope.row.borrowType === 1">部门</span>
<span v-if="scope.row.borrowType === 2">个人</span>
</div>
</template>
</el-table-column>
<el-table-column prop="borrowNo" label="借阅证号">
<template slot-scope="scope">
{{ scope.row.borrowNo || '-' }}
</template>
</el-table-column>
<el-table-column prop="cabinetId" label="已绑定位置">
<template slot-scope="scope">
{{ scope.row.cabinetId ? String(scope.row.cabinetId).padStart(2, '0') : '-' }}
</template>
</el-table-column>
<el-table-column prop="create_time" label="操作" width="80">
<template slot-scope="scope">
<el-button :disabled="scope.row.cabinetId !== null" :loading="bindLoading[scope.$index]" size="mini" style="padding: 5px;" @click="handleBindCell(scope.$index, scope.row)"> {{ scope.row.cabinetId ? '已绑定' : '绑定' }}</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="borrowerPage.current+1"
:page-size="borrowerPage.size"
:total="borrowerPage.total"
:page-sizes="[10, 20, 50, 100]"
layout="total, prev, pager, next, sizes"
@size-change="handleBorrowerSizeChange"
@current-change="handleBorrowerPageChange"
/>
</div>
</el-dialog>
<MidoArchivesInfo ref="archivesInfo" :is-mido-record="true" :parent-info="parentInfo" :page-type="pageType" />
</div>
</template>
<script>
import CRUD, { presenter, crud } from '@crud/crud'
import { FetchInitBorrowerList } from '@/api/system/borrower'
import { FetchCabinetBingBorrower, FetchCabinetUnbingBorrower, FetchDocumentCirculationCabinetById, FetchUnpublish } from '@/api/system/documentArchives'
import MidoArchivesInfo from '@/views/archivesMIOD/miodLibrary/module/detail'
import { mapGetters } from 'vuex'
export default {
name: 'FilingCabinet',
components: { MidoArchivesInfo },
mixins: [presenter(), crud()],
cruds() {
return CRUD({
url: 'api/documentCirculationCabinet/initDocumentCirculationCabinet',
title: '文件流转柜管理',
optShow: {
add: false,
edit: false,
del: false,
download: false,
reset: false,
group: false
}
})
},
data() {
return {
tableLoading: false,
categoryId: null,
parentInfo: null,
pageType: 'miodRecord',
removalLoaing: [],
selectedCell: null,
selectedCellInfo: null,
unbindLoading: false,
cabinetColumns: [
[
{ id: '01', borrowName: '', type: 'ld', bound: false, documentCount: 0 },
{ id: '02', borrowName: '', type: 'ld', bound: false, documentCount: 0 },
{ id: '03', borrowName: '', type: 'ld', bound: false, documentCount: 0 },
{ id: '04', borrowName: '', type: 'ld', bound: false, documentCount: 0 },
{ id: '05', borrowName: '', type: 'ld', bound: false, documentCount: 0 },
{ id: '06', borrowName: '', type: 'ld', bound: false, documentCount: 0 },
{ id: '07', borrowName: '', type: 'ld', bound: false, documentCount: 0 },
{ id: '08', borrowName: '', type: 'big', bound: false, documentCount: 0 }
],
[
{ id: '09', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '10', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '11', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '12', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '13', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '14', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '15', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '16', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '17', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '18', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '19', borrowName: '', type: 'big', bound: false, documentCount: 0 }
],
[
{ id: '20', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '21', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '22', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '23', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '24', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '25', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '26', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '27', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '28', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '29', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '30', borrowName: '', type: 'big', bound: false, documentCount: 0 }
],
[
{ id: '31', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '32', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '33', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '34', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '35', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '36', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '37', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '38', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '39', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '40', borrowName: '', type: 'department', bound: false, documentCount: 0 },
{ id: '41', borrowName: '', type: 'big', bound: false, documentCount: 0 }
]
],
borrowerListVisible: false,
borrowerList: [],
borrowerListLoading: false,
borrowerPage: {
current: 0,
size: 10,
total: 0
},
query: {
search: ''
},
bindLoading: [],
lastSelectedCellId: null,
miodData: []
}
},
computed: {
...mapGetters([
'baseApi'
])
},
watch: {
},
created() {
},
mounted() {
this.getBorrowerList()
},
methods: {
selectCell(item) {
if (item.type === 'empty') return
this.selectedCell = item.id
this.selectedCellInfo = item
this.getDocumentCirculationCabinetById()
},
[CRUD.HOOK.beforeRefresh]() {
this.crud.params.page = undefined
this.crud.params.size = undefined
},
[CRUD.HOOK.afterRefresh](crud) {
if (crud.data && Array.isArray(crud.data)) {
this.transformCabinetData(crud.data)
}
},
transformCabinetData(data) {
const ldCells = []
const departmentCells = []
const bigCells = []
data.forEach(item => {
const cell = {
id: String(item.id).padStart(2, '0'),
type: item.cabinetType === 1 ? 'ld' : (item.cabinetType === 3 ? 'big' : 'department'),
documentCount: item.documentCount || 0,
bound: !!item.bindBorrower,
borrowName: item.borrowName || '',
borrowerType: item.borrowerType,
originalData: item
}
if (item.cabinetType === 1) {
ldCells.push(cell)
} else if (item.cabinetType === 3) {
bigCells.push(cell)
} else {
departmentCells.push(cell)
}
})
ldCells.sort((a, b) => parseInt(a.id) - parseInt(b.id))
departmentCells.sort((a, b) => parseInt(a.id) - parseInt(b.id))
bigCells.sort((a, b) => parseInt(a.id) - parseInt(b.id))
this.cabinetColumns = [
[...ldCells, bigCells[0]],
[...departmentCells.slice(0, 10), bigCells[1]],
[...departmentCells.slice(10, 20), bigCells[2]],
[...departmentCells.slice(20, 30), bigCells[3]]
]
this.$nextTick(() => {
// 优先选中上次操作的格子,否则选中第一个
if (this.lastSelectedCellId) {
let targetCell = null
for (const column of this.cabinetColumns) {
targetCell = column.find(cell => cell.id === this.lastSelectedCellId)
if (targetCell) break
}
if (targetCell) {
this.selectCell(targetCell)
return
}
}
if (this.cabinetColumns[0] && this.cabinetColumns[0][0]) {
this.selectCell(this.cabinetColumns[0][0])
}
})
},
getDocumentCirculationCabinetById() {
this.tableLoading = true
this.miodData = []
const params = {
id: this.selectedCellInfo.originalData.id
}
FetchDocumentCirculationCabinetById(params).then((res) => {
if (res.code !== 500) {
this.miodData = res.detailsList || []
} else {
this.$message({ message: '获取文件流转柜详情失败', type: 'error', offset: 8 })
}
this.tableLoading = false
}).catch(err => {
console.log(err)
this.$message({ message: '获取文件流转柜详情失败', type: 'error', offset: 8 })
this.tableLoading = false
})
},
handleBindCell(index, item) {
this.$set(this.bindLoading, index, true)
this.$confirm('此操作将绑定当前借阅者' + '<span>你是否还要继续?</span>', '提示', {
confirmButtonText: '继续',
cancelButtonText: '取消',
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
const params = {
bindBorrower: item.id,
borrowType: null,
id: this.selectedCellInfo.originalData.id
}
FetchCabinetBingBorrower(params).then((res) => {
if (res.code !== 500) {
this.$message({ message: '绑定成功', type: 'success', offset: 8 })
this.lastSelectedCellId = this.selectedCellInfo.id
this.crud.refresh()
} else {
this.$message({ message: '绑定失败', type: 'error', offset: 8 })
}
this.borrowerListVisible = false
this.getBorrowerList()
}).catch(err => {
console.log(err)
this.borrowerListVisible = false
})
this.$set(this.bindLoading, index, false)
}).catch(() => {
this.$set(this.bindLoading, index, false)
})
},
unbindCell() {
this.unbindLoading = true
this.$confirm('此操作将解绑当前绑定的目标' + '<span>你是否还要继续?</span>', '提示', {
confirmButtonText: '继续',
cancelButtonText: '取消',
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
const ids = [this.selectedCellInfo.originalData.id]
FetchCabinetUnbingBorrower(ids).then((res) => {
if (res.code !== 500) {
this.$message({ message: '解绑成功', type: 'success', offset: 8 })
this.lastSelectedCellId = this.selectedCellInfo.id
this.crud.refresh()
} else {
this.$message({ message: '解绑失败', type: 'error', offset: 8 })
}
this.getBorrowerList()
}).catch(err => {
console.log(err)
})
this.unbindLoading = false
}).catch(() => {
this.unbindLoading = false
})
},
tableDoubleClick(row) {
this.parentInfo = row
this.$nextTick(() => {
this.$refs.archivesInfo.archivesInfoVisible = true
this.$refs.archivesInfo.archivesTabIndex = 0
this.$refs.archivesInfo.getDetial()
})
},
handleSearch() {
this.borrowerPage.current = 0
this.getBorrowerList()
},
resetSearch() {
this.query.search = ''
this.borrowerPage.current = 0
this.getBorrowerList()
},
getBorrowerList() {
this.borrowerListLoading = true
const params = {
page: this.borrowerPage.current,
size: this.borrowerPage.size,
search: this.query.search
}
FetchInitBorrowerList(params).then(res => {
if (res && res.content) {
this.borrowerList = res.content || []
this.borrowerPage.total = res.totalElements || 0
} else {
this.borrowerList = []
this.borrowerPage.total = 0
}
this.borrowerListLoading = false
}).catch(err => {
console.error('获取借阅者列表失败:', err)
this.borrowerList = []
this.borrowerPage.total = 0
this.borrowerListLoading = false
})
},
handleBorrowerPageChange(page) {
this.borrowerPage.current = page - 1
this.getBorrowerList()
},
handleBorrowerSizeChange(size) {
this.borrowerPage.size = size
this.borrowerPage.current = 0
this.getBorrowerList()
},
handleBatchDel(index, data) {
this.$set(this.removalLoaing, index, true)
this.$confirm('此操作将下架当前公文' + '<span>你是否还要继续?</span>', '提示', {
confirmButtonText: '继续',
cancelButtonText: '取消',
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
const params = {
'documentTid': data.regNo
}
FetchUnpublish(params).then((res) => {
if (res.code !== 500) {
this.$message({ message: '手动下架成功', type: 'success', offset: 8 })
this.crud.refresh()
} else {
this.$message({ message: '手动下架失败', type: 'error', offset: 8 })
}
}).catch(err => {
console.log(err)
})
this.$set(this.removalLoaing, index, false)
}).catch(() => {
this.$set(this.removalLoaing, index, false)
})
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/assets/styles/collect-reorganizi.scss";
::v-deep .el-pagination{
margin: 24px 0 10px 0 !important
}
.filing-cabinet-wrapper {
display: flex;
justify-content: flex-start;
}
.file-cabinet {
border-radius: 8px;
padding: 15px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
margin-right: 20px;
height: calc(100vh - 180px);
}
.cabinet-grid {
display: flex;
gap: 8px;
height: 100%;
}
.cabinet-column {
display: flex;
flex-direction: column;
gap: 8px;
flex: 1;
}
.cabinet-column:nth-child(1) .cabinet-cell:not(.cabinet-cell-big) {
flex: 1;
min-height: 0;
width: 100px;
}
.cabinet-column:nth-child(2) .cabinet-cell:not(.cabinet-cell-big),
.cabinet-column:nth-child(3) .cabinet-cell:not(.cabinet-cell-big),
.cabinet-column:nth-child(4) .cabinet-cell:not(.cabinet-cell-big) {
flex: 1;
min-height: 0;
width: 100px;
}
.cabinet-column .cabinet-cell-big {
height: 140px;
width: 100px;
}
.cabinet-cell {
border-radius: 4px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
cursor: pointer;
transition: all 0.3s ease;
border: 1px solid #d9d9d9;
position: relative;
overflow: hidden;
}
.cabinet-cell-empty {
background: #fff;
border: 1px dashed #d9d9d9;
cursor: default;
}
.cabinet-cell-ld {
background: linear-gradient(145deg, #fff 0%, #f0f0f0 100%);
}
.cabinet-cell-department {
background: linear-gradient(145deg, #f5f7fa 0%, #e4e8ec 100%);
}
.cabinet-cell-unbound {
background: linear-gradient(145deg, #fafafa 0%, #e8e8e8 100%);
opacity: 0.6;
}
.cabinet-cell-unbound .cell-label {
color: #999;
}
.cabinet-cell:hover:not(.cabinet-cell-empty) {
border-color: #1890ff;
box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3);
}
.cabinet-cell-selected {
border-color: #1890ff;
background: linear-gradient(145deg, #e6f7ff 0%, #b3d9ff 100%);
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
.cell-label {
font-size: 12px;
color: #333;
font-weight: 500;
text-align: center;
padding: 0 4px;
}
.cell-id {
position: absolute;
top: 2px;
left: 4px;
font-size: 10px;
color: #333;
}
.cell-file-count {
position: absolute;
bottom: 2px;
right: 4px;
font-size: 11px;
color: #1890ff;
font-weight: bold;
// background: rgba(24, 144, 255, 0.1);
padding: 1px 4px;
border-radius: 4px;
}
.cabinet-info {
// display: flex;
// justify-content: space-between;
// align-items: center;
// margin-top: 15px;
padding: 12px;
background: #fff;
border-radius: 6px;
border: 1px solid #e8e8e8;
}
.info-row {
display: flex;
margin-right: 20px;
font-size: 14px;
&:last-child {
margin-right: 0;
}
}
.info-label {
color: #999;
}
.info-value {
color: #333;
font-weight: 500;
}
.info-value.unbound {
color: #ED4A41;
}
.content-wrap {
width: calc(100% - 454px);
}
[data-theme=light] .el-button.unbind-btn,
[data-theme=light] .el-button.unbind-btn:hover,
[data-theme=light] .el-button.unbind-btn:focus{
color: #ED4A41;
border-color: #ED4A41;
background: transparent;
}
[data-theme=light] .el-button.unbind-btn.is-disabled,
[data-theme=light] .el-button.unbind-btn.is-disabled:hover,
[data-theme=light] .el-button.unbind-btn.is-disabled:focus{
color:#F6A5A0;
border-color:#F6A5A0;
background: rgba(252,49,49,0.2);
}
.cabinet-info-title{
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 6px;
font-size: 14px;
}
.cabinet-table-title{
font-size: 14px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px;
background: #fff;
border-radius: 6px;
border: 1px solid #e8e8e8;
margin-bottom: 12px;
}
.title-left{
display: flex;
justify-content: flex-start;
align-items: center;
color: #000;
&::before{
content: '';
display: inline-block;
width: 4px;
height: 16px;
background: #1890ff;
margin-right: 6px;
}
}
</style>