|
|
<template> <div class="app-container row-container"> <!--工具栏--> <div class="head-container"> <div v-if="crud.props.searchToggle" class="head-search"> <!-- 搜索 --> <el-input v-model="query.search" size="small" clearable placeholder="输入资产名称/编码搜索" prefix-icon="el-icon-search" style="width: 220px;" class="filter-item" @keyup.enter.native="crud.toQuery" /> <rrOperation /> </div> <crudOperation :permission="permission"> <template v-slot:left> <el-button size="mini" @click="toAdd()"> <i class="iconfont icon-xinzeng" /> 新增 </el-button> <el-button slot="reference" size="mini" :loading="crud.delAllLoading" :disabled="crud.selections.length === 0" @click="toDelete(crud.selections)"> <i class="iconfont icon-shanchu" /> 删除 </el-button> </template> </crudOperation> </div> <div class="container-wrap"> <span class="right-top-line" /> <span class="left-bottom-line" /> <el-table ref="table" v-loading="crud.loading" :header-cell-class-name="headerCellClassName" :cell-class-name="cellClassName" highlight-current-row style="width: 100%;" height="calc(100vh - 330px)" :data="crud.data" @row-dblclick="handleRowDblClick" @selection-change="crud.selectionChangeHandler"> <el-table-column type="selection" width="55" align="center" /> <el-table-column prop="mark" label="资产编号" min-width="180px" :show-overflow-tooltip="true" /> <el-table-column prop="name" label="资产名称" min-width="180px" :show-overflow-tooltip="true" /> <el-table-column prop="capitaltyepname" label="资产类型" width="80px" :show-overflow-tooltip="true" /> <el-table-column prop="startprice" label="价值" width="80px" align="right" :show-overflow-tooltip="true" :formatter="(row) => formatMoney(row.startprice)" /> <el-table-column prop="unitname" label="计量单位" width="80px" align="center" :show-overflow-tooltip="true" /> <el-table-column prop="departmentname" label="使用部门" :show-overflow-tooltip="true" /> <el-table-column prop="resourcename" label="使用人" :show-overflow-tooltip="true" /> <el-table-column prop="blongdepartmentname" label="所属部门" min-width="140px" :show-overflow-tooltip="true" /> <el-table-column prop="glrname" label="管理人" :show-overflow-tooltip="true" /> <el-table-column prop="cfdname" label="存放地" min-width="140px" :show-overflow-tooltip="true" /> <el-table-column prop="whiteCreateTime" label="加入时间" width="180px"> <template slot-scope="scope"> <div>{{ scope.row.whiteCreateTime | parseTime }}</div> </template> </el-table-column> <el-table-column prop="whiteLastname" label="操作人"> <template slot-scope="scope"> <div>{{ scope.row.whiteLastname || '——' }}</div> </template> </el-table-column> <el-table-column prop="whiteRemark" label="备注" :show-overflow-tooltip="true"> <template slot-scope="scope"> <div>{{ scope.row.whiteRemark || '——' }}</div> </template> </el-table-column> </el-table> <!--分页组件--> <pagination v-if="crud.data.length!==0" /> </div>
<!-- 资产详情弹窗 --> <el-dialog class="detailBook" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :before-close="handleCloseDialog" :visible="detailDialogVisible" title="资产详情"> <span class="dialog-right-top" /> <span class="dialog-left-bottom" /> <div class="setting-dialog"> <div class="detail-tab tab-content"> <div class="detail-check"> <div style="flex: 1;"> <ul class="book-detail asset-detail" style="max-height: 680px; overflow: auto;"> <li><span>资产编号:</span>{{ selectedAsset && selectedAsset.mark }}</li> <li><span>资产名称:</span>{{ selectedAsset && selectedAsset.name }}</li> <li><span>资产类型:</span>{{ selectedAsset && selectedAsset.capitaltyepname || '——' }}</li> <li><span>规格型号:</span>{{ selectedAsset && selectedAsset.capitalspec || '——' }}</li> <!-- <li><span>设备用途:</span>{{ selectedAsset && selectedAsset.sbyt || '——' }}</li> --> <li><span>价值类型:</span>{{ selectedAsset && selectedAsset.jzlx || '——' }}</li> <li><span>价值:</span>{{ selectedAsset ? formatMoney(selectedAsset?.startprice) : '——' }}</li> <li><span>数量:</span>{{ selectedAsset && selectedAsset.capitalnum }}</li> <li><span>实际数量:</span>{{ selectedAsset && selectedAsset.sjsl }}</li> <li><span>计量单位:</span>{{ selectedAsset && selectedAsset.unitname }}</li> <li><span>使用部门:</span>{{ selectedAsset && selectedAsset.departmentname }}</li> <li><span>使用人:</span>{{ selectedAsset && selectedAsset.resourcename }}</li> <li><span>所属部门:</span>{{ selectedAsset && selectedAsset.blongdepartmentname }}</li> <li><span>管理人:</span>{{ selectedAsset && selectedAsset.glrname }}</li> <li><span>存放地:</span>{{ selectedAsset && selectedAsset.cfdname }}</li> <li><span>供应商:</span>{{ selectedAsset && selectedAsset.gys }}</li> <li><span>项目名称:</span>{{ selectedAsset && selectedAsset.xmmc }}</li> <!-- <li><span>无线电设备用途:</span>{{ selectedAsset && selectedAsset.wxdsbyt }}</li> --> <li><span>领用日期:</span>{{ selectedAsset && selectedAsset.deprestartdate | parseTime }}</li> <li><span>投入使用日期:</span>{{ selectedAsset && selectedAsset.trsyrq | parseTime }}</li> <li><span>入账日期:</span>{{ selectedAsset && selectedAsset.rzrq | parseTime }}</li> <li><span>保修截至日期:</span>{{ selectedAsset && selectedAsset.bxjzrq | parseTime }}</li> </ul> <div class="book-detail white-detail"> <div class="white-title"> <span class="small-line" /> <p>已加入白名单</p> <span class="big-line" /> </div> <ul> <li class="white-item"><span>加入时间:</span>{{ selectedAsset && selectedAsset.whiteCreateTime | parseTime }}</li> <li class="white-item"><span>操作人:</span>{{ selectedAsset && selectedAsset.whiteLastname || '——' }}</li> <li class="white-item"><span>备注:</span>{{ selectedAsset && selectedAsset.whiteRemark || '——' }}</li> </ul> </div> </div> <!-- 资产图片列表(竖向滚动 + 删除按钮) --> <div class="asset-image-wrapper"> <div v-if="assetImageList.length > 0" class="asset-image-scroll"> <div v-for="(item, index) in assetImageList" :key="item.id || index" class="image-item"> <el-image class="preview-img" :src="item.imgUrl" fit="contain" :preview-src-list="assetImageList.map(img => img.imgUrl)" :preview-initial-index="index" /> </div> </div> <div v-else class="default-img"> <img :src="require('@/assets/images/system/default-img2.png')" alt="默认图片"> </div> </div> </div> </div> </div> </el-dialog>
<el-dialog title="新增资产白名单" :visible.sync="addDialogVisible" width="1000px" append-to-body :close-on-click-modal="false" @close="resetAddDialog" > <div style="display: flex; justify-content: space-between; align-items: center; padding-bottom: 20px;"> <div> <el-input v-model="addSearch" size="small" clearable placeholder="输入资产名称/编码搜索" prefix-icon="el-icon-search" style="width: 220px;" class="filter-item" @keyup.enter.native="toQuery" @clear="toQuery" /> <el-button class="filter-item filter-search" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button> </div> <div style="color:#606266;"> 已选择资产:<span style="color:#409EFF">{{ selectedMarkSet.size }}</span> 条 </div> </div> <div v-loading="addDialogLoading"> <el-table ref="addTable" :row-key="row => row.mark" :data="initAssetList" height="446px" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" :reserve-selection="true" />
<el-table-column prop="mark" label="资产编号" min-width="200px" :show-overflow-tooltip="true" /> <el-table-column prop="name" label="资产名称" min-width="200px" :show-overflow-tooltip="true" /> <el-table-column prop="capitaltyepname" label="资产类型" width="80px" :show-overflow-tooltip="true" /> <el-table-column prop="startprice" label="价值" width="80px" align="right" :show-overflow-tooltip="true" :formatter="(row) => formatMoney(row.startprice)" /> <el-table-column prop="unitname" label="计量单位" width="80px" align="center" :show-overflow-tooltip="true" /> <el-table-column prop="departmentname" label="使用部门" :show-overflow-tooltip="true" /> <el-table-column prop="resourcename" label="使用人" :show-overflow-tooltip="true" /> <el-table-column prop="blongdepartmentname" label="所属部门" min-width="140px" :show-overflow-tooltip="true" /> <el-table-column prop="glrname" label="管理人" :show-overflow-tooltip="true" /> <el-table-column prop="cfdname" label="存放地" min-width="140px" :show-overflow-tooltip="true" /> <el-table-column prop="is_whitelist" label="是否白名单" width="90px" align="center" fixed="right"> <template slot-scope="scope"> <el-tag v-if="scope.row.is_whitelist" type="success">白名单</el-tag> <span v-else>-</span> </template> </el-table-column> </el-table>
<!-- 弹窗内分页 --> <el-pagination :current-page="addPage.pageNo" :page-sizes="[10, 20, 50, 100]" :page-size="addPage.pageSize" layout="total, sizes, prev, pager, next" :total="addPage.total" style="margin: 20px 0 !important;" @size-change="onAddSizeChange" @current-change="onAddPageChange" /> <div style="padding: 20px 20px 0 20px;"> <el-form ref="form" inline :model="addForm" size="small" label-width="40px"> <el-form-item label="备注" prop="remark" style="margin-bottom: 0 !important;"> <el-input v-model="addForm.remark" type="textarea" rows="3" placeholder="请输入备注" style="width: 880px;" /> </el-form-item> </el-form> </div> </div>
<span slot="footer" class="dialog-footer"> <el-button @click="addDialogVisible = false">取消</el-button> <el-button type="primary" :loading="submitLoading" @click="submitAdd">确定</el-button> </span> </el-dialog> </div></template>
<script>import crudAsset, { FetchAssetInfoDetailsByMark, FetchInitAssetInfo, FetchAddAssetWhiteList, FetchDeleteAssetWhiteList } from '@/api/asset/index'import CRUD, { presenter, header, crud } from '@crud/crud'import rrOperation from '@crud/RR.operation'import crudOperation from '@crud/CRUD.operation'import pagination from '@crud/Pagination'import { mapGetters } from 'vuex'// import { addAssetWhitelist } from '@/api/asset/index' // 真实新增接口
export default { name: 'AssetWhitelist', components: { pagination, crudOperation, rrOperation }, cruds() { return CRUD({ title: '资产白名单', idField: 'mark', url: 'api/asset/initAssetInfo', crudMethod: { ...crudAsset }, optShow: { add: false, edit: false, del: false, reset: true, download: false, group: false }}) }, mixins: [presenter(), header(), crud()], data() { return { permission: { add: [], edit: [], del: [] }, selectedFile: null, detailDialogVisible: false, selectedAsset: null, assetImageList: [],
addDialogVisible: false, addDialogLoading: false, submitLoading: false, initAssetList: [], // 弹窗内待选资产列表
selectedMarkSet: new Map(), // 跨页保存勾选行:mark -> row(由 reserve-selection 自动维护)
addForm: { remark: '' }, // 弹窗内部分页
addPage: { pageNo: 1, pageSize: 10, total: 0 }, addSearch: '' } }, computed: { ...mapGetters([ 'baseApi', 'user' ]) }, created() { }, mounted() { }, methods: { // 数据单元格样式
cellClassName({ row, column, rowIndex, columnIndex }) { const whiteFields = ['whiteCreateTime', 'whiteLastname', 'whiteRemark'] if (whiteFields.includes(column.property)) { return 'white-list-cell' } return '' }, // 表头单元格样式
headerCellClassName({ row, column, rowIndex, columnIndex }) { const whiteFields = ['whiteCreateTime', 'whiteLastname', 'whiteRemark'] if (whiteFields.includes(column.property)) { return 'white-list-header-cell' } return '' },
[CRUD.HOOK.beforeRefresh]() { if (this.crud.query.search) { this.crud.query.search = this.crud.query.search.trim() } this.crud.params.isWhite = true // 保存原始参数
this.originalPage = this.crud.page.page this.originalSize = this.crud.page.size // 添加pageNo和pageSize参数
this.crud.params.pageNo = this.crud.page.page this.crud.params.pageSize = this.crud.page.size // 清空page和size参数
this.crud.params.page = undefined this.crud.params.size = undefined }, [CRUD.HOOK.afterRefresh](crud) { // 恢复原始参数
if (this.originalPage !== undefined) { this.crud.page.page = this.originalPage this.crud.page.size = this.originalSize // 移除pageNo和pageSize参数
delete this.crud.params.pageNo delete this.crud.params.pageSize delete this.crud.params.page delete this.crud.params.size } console.log(crud.data) }, // 新增前
[CRUD.HOOK.beforeToAdd](crud, form) { }, // 编辑前
[CRUD.HOOK.beforeToEdit](crud, form) { }, // 提交前做的操作
[CRUD.HOOK.afterValidateCU](crud) { return true }, formatMoney(money) { if (!money && money !== 0) return '——' return Number(money).toLocaleString('en-US') }, // 处理行双击事件
// 处理行双击事件
handleRowDblClick(row) { this.detailDialogVisible = true this.selectedAsset = {} this.assetImageList = [] const params = { mark: row.mark } FetchAssetInfoDetailsByMark(params).then(res => { // 合并详情接口数据 + 列表行的白名单字段
this.selectedAsset = { ...(res || {}), capitaltyepname: row.capitaltyepname, resourcename: row.resourcename, whiteCreateTime: row.whiteCreateTime, whiteLastname: row.whiteLastname, whiteRemark: row.whiteRemark } const photoList = res?.assetInfoPhoto || [] this.assetImageList = photoList.map(item => ({ id: item.id, photoUrl: item.photoUrl, imgUrl: this.baseApi + '/api/minio/getImg?bucket=2&fileName=' + item.photoUrl })) }) }, handleCloseDialog() { this.detailDialogVisible = false this.selectedAsset = null this.assetImageList = [] },
toAdd() { this.addDialogVisible = true this.addPage.pageNo = 1 this.addPage.pageSize = 10 this.addPage.total = 0 this.selectedMarkSet.clear() // 清空表格保留的跨页选中状态
this.$nextTick(() => { this.$refs.addTable && this.$refs.addTable.clearSelection() }) this.addForm.remark = '' this.loadInitAssetList() }, toQuery() { this.addPage.pageNo = 1 this.addPage.pageSize = 10 this.addPage.total = 0 this.loadInitAssetList() }, // 加载弹窗表格
async loadInitAssetList() { this.addDialogLoading = true try { const res = await FetchInitAssetInfo({ search: this.addSearch.trim(), pageNo: this.addPage.pageNo, pageSize: this.addPage.pageSize }) this.initAssetList = res.records || [] this.addPage.total = res.total || 0 // reserve-selection 会自动回显已勾选行,无需手动处理
} catch (e) { this.$message.error('加载失败') } finally { this.addDialogLoading = false } },
handleSelectionChange(rows) { // rows 为当前所有跨页选中行
this.selectedMarkSet = new Map(rows.map(row => [row.mark, row])) console.log('当前全部选中mark集合:', Array.from(this.selectedMarkSet.keys())) },
// 分页切换
onAddPageChange(val) { this.addPage.pageNo = val this.loadInitAssetList() }, onAddSizeChange(val) { this.addPage.pageSize = val this.addPage.pageNo = 1 this.loadInitAssetList() },
// 提交新增白名单
async submitAdd() { const selectedRows = Array.from(this.selectedMarkSet.values()) console.log('最终选中的全部行:', selectedRows) if (selectedRows.length === 0) { return this.$message.warning('请至少选择一条资产') } this.submitLoading = true try { const params = { assetInfos: selectedRows.map(row => ({ mark: row.mark, epc: row.epc })), createBy: this.user.id, remark: this.addForm.remark } console.log('params', params) await FetchAddAssetWhiteList(params).then(res => { console.log('FetchAddAssetWhiteList', res) if (res.code !== null) { this.$message.success(res || '加入白名单成功') this.addDialogVisible = false this.crud.refresh() } else { this.$message.error(res.message || '加入白名单失败') } }).catch(err => { this.$message.error(err.message || '加入白名单失败') }) } catch (err) { this.$message.error(err.message || '加入白名单失败') } finally { this.submitLoading = false } },
// 关闭弹窗重置状态
resetAddDialog() { this.initAssetList = [] this.selectedMarkSet.clear() this.addForm.remark = '' this.addPage.pageNo = 1 this.addPage.total = 0 this.addSearch = '' this.$nextTick(() => { this.$refs.addTable && this.$refs.addTable.clearSelection() }) }, toDelete(datas) { console.log('toDelete', datas) this.$confirm('此操作将删除当前所选' + this.crud.title + '<span>你是否还要继续?</span>', '提示', { confirmButtonText: '继续', cancelButtonText: '取消', type: 'warning', dangerouslyUseHTMLString: true }).then(() => { this.crud.delAllLoading = true const marks = datas.map(val => val.mark) console.log('marks', marks) FetchDeleteAssetWhiteList(marks).then(res => { console.log('FetchDeleteAssetWhiteList', res) if (res.code !== null) { this.$message({ message: res, type: 'success', offset: 8 }) this.crud.delAllLoading = false this.crud.refresh() } else { this.$message.error(res.message || '删除失败') } }).catch(err => { this.crud.delAllLoading = false console.log(err) }) }).catch(() => { }) } }}</script>
<style lang="scss" scoped>.sync-loading { display: flex; justify-content: center; align-items: center; min-height: 200px;}.sync-loading-content { text-align: center;}.sync-loading-icon { font-size: 48px; color: #409EFF;}.sync-status { margin-top: 15px; text-align: center; color: #606266; font-size: 14px;}.file-tip { margin-left: 10px; font-size: 12px; color: #606266;}.sync-result{ display: flex; justify-content: center; align-items: center; margin-top: 40px; font-size: 22px; text-align: center; .sync-text{ margin-left: 10px; p{ display: inline-block; span{ display: inline-block; padding: 0 4px; } } }}::v-deep .el-dialog__footer{ padding: 0 0 20px 0 !important;}.asset-detail-content { display: flex; gap: 20px;}.asset-info { flex: 1;}// 资产图片列表样式(竖向滚动)
.asset-image-wrapper { width: 400px; height: 660px; /* 固定高度 */ overflow: hidden;}.asset-image-scroll { width: 100%; height: 100%; overflow-y: auto; /* 竖向滚动条 */ padding-right: 5px; display: flex; flex-direction: column; gap: 10px;}.image-item { position: relative; width: 100%; height: 150px; background: #f5f7fa; border-radius: 4px; overflow: hidden; flex-shrink: 0;}.preview-img { width: 100%; height: 100%; object-fit: contain; background: #fff;}// 删除按钮
.delete-btn { position: absolute; top: 5px; right: 5px; width: 22px; height: 22px; background: rgba(0, 0, 0, 0.6); color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 10; transition: 0.2s; &:hover { background: #f56c6c; } i { font-size: 14px; }}// 默认图片
.default-img { width: 100%; height: 200px; display: flex; align-items: center; justify-content: center; background-color: #f5f7fa; border: 2px solid #dcdfe6; border-radius: 4px; img { width: 180px; height: 180px; object-fit: cover; }}.detailBook { ::v-deep .el-dialog { width: 1000px !important; .el-dialog__body{ padding: 0 0 30px 0; ::-webkit-scrollbar{ width: 5px !important; height: 5px !important;
} ::-webkit-scrollbar-thumb{ background-color: #f5f7fa !important; } } } .detail-check{ display: flex; justify-content: space-between; align-items: flex-start; padding: 12px 30px; background-color: #F6F8FC; overflow: hidden; } .book-detail{ display: flex; flex-direction: column; justify-content: flex-start;
li{ line-height: 30px; span{ display: inline-block; width: 120px; text-align: right; margin-right: 10px; color: #0C0E1E; } i{ font-style: normal; padding: 0 8px; } &.row-li{ width: 100% } &.white-item { color: #606266; span { color: #0348F3 !important; } } } &.white-detail{ border-radius: 4px; background-color: #EEF5FE; margin-top: 4px; & .white-title{ display: flex; justify-content: flex-start; align-items: center; font-size: 12px; color: #606266; padding: 6px; p{ padding: 0 10px; } .small-line{ display: inline-block; width: 40px; border-bottom: 1px solid #a9aeb8; } .big-line{ display: inline-block; flex: 1; // height: 1px;
border-bottom: 1px solid #a9aeb8; // background-color: #a9aeb8;
} } } } ::v-deep .dialog-footer{ margin-top: 30px; }}.dialog-footer{ margin: 20px auto 0 auto;}::v-deep .el-table__fixed-right{ background-color: #fff !important;}// 数据行单元格
::v-deep .white-list-cell { // background-color: #EAF3FB !important;
color: #0348F3 !important;}// 表头单元格
::v-deep .white-list-header-cell { background-color: #EAF3FB !important;}</style>
|