|
|
<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>
|