bonus-ui/src/views/business/businessHandling/directApply.vue

1499 lines
61 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-form :model="maForm" ref="maForm" size="small" :rules="rules" label-width="80px" :disabled="isDetail">
<el-row :gutter="20" class="cont-center" style="margin-bottom: 20px">
<el-col :span="8" :offset="0">
<el-card shadow="always" :body-style="{ padding: '20px' }" style="min-width: 400px; overflow-y: auto">
<!-- card body -->
<el-form-item label="转出单位" prop="backUnitId">
<treeselect
v-model="maForm.backUnitId"
:disabled="isEdit || isDetail"
:options="uniteList"
:normalizer="normalizer"
:show-count="true"
style="width: 100%"
:disable-branch-nodes="true"
noChildrenText="没有数据了"
noOptionsText="没有数据"
noResultsText="没有搜索结果"
placeholder="请选择转出单位"
@select="uniteChange"
/>
</el-form-item>
<el-form-item label="转出工程" prop="backProId">
<treeselect
v-model="maForm.backProId"
:disabled="isEdit || isDetail"
:options="projectList"
:normalizer="normalizer"
:show-count="true"
style="width: 100%"
:disable-branch-nodes="true"
noChildrenText="没有数据了"
noOptionsText="没有数据"
noResultsText="没有搜索结果"
placeholder="请选择转出工程"
@select="projectChange"
/>
</el-form-item>
<el-form-item label="转出人" prop="backMan">
<el-input
v-model="maForm.backMan"
placeholder="请输入转出人"
clearable
maxlength="50"
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="联系电话" prop="backPhone">
<el-input
v-model="maForm.backPhone"
placeholder="请输入联系电话"
clearable
maxlength="11"
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</el-card>
</el-col>
<el-col :span="2" :offset="0">
<div class="cont-center">
<el-image
style="width: 100px; height: 100px"
:src="require('@/assets/img/transform.png')"
fit="fit"
></el-image>
</div>
</el-col>
<el-col :span="8" :offset="0">
<el-card shadow="always" :body-style="{ padding: '20px' }" style="min-width: 400px; overflow-y: auto">
<!-- card body -->
<el-form-item label="转入单位" prop="leaseUnitId">
<treeselect
v-model="maForm.leaseUnitId"
:disabled="isDetail"
:options="lessUniteList"
:normalizer="normalizer"
:show-count="true"
style="width: 100%"
:disable-branch-nodes="true"
noChildrenText="没有数据了"
noOptionsText="没有数据"
noResultsText="没有搜索结果"
placeholder="请选择转入单位"
@select="leaseUniteChange"
/>
</el-form-item>
<el-form-item label="转入工程" prop="leaseProId">
<treeselect
v-model="maForm.leaseProId"
:disabled="isDetail"
:options="leaseProjectList"
:normalizer="normalizer"
:show-count="true"
style="width: 100%"
:disable-branch-nodes="true"
noChildrenText="没有数据了"
noOptionsText="没有数据"
noResultsText="没有搜索结果"
placeholder="请选择转入工程"
@select="leaseProjectChange"
/>
</el-form-item>
<el-form-item label="转入人" prop="leaseMan">
<el-input
v-model="maForm.leaseMan"
placeholder="请输入转入人"
clearable
maxlength="50"
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="联系电话" prop="leasePhone">
<el-input
v-model="maForm.leasePhone"
placeholder="请输入联系电话"
clearable
maxlength="11"
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</el-card>
</el-col>
<el-col :span="6" :offset="0">
<el-form-item label="" prop="dirUrls">
<el-upload
:action="uploadUrl"
:file-list="maForm.dirUrls"
:show-file-list="true"
:auto-upload="true"
:headers="headers"
:key="uploadKey"
:limit="3"
list-type="picture-card"
accept=".png, .jpg, .jpeg, .pdf"
:before-upload="beforeUpload"
:on-change="handleChangeBusinessList"
:class="{ disabledFbs: uploadDisabled }"
:on-preview="picturePreviewFbs"
:on-remove="handleRemoveElectricianImgList"
:disabled="isDetail"
>
<!-- 文件格式下载图片格式预览 -->
<div slot="file" slot-scope="{ file }">
<img
class="el-upload-list__item-thumbnail"
:src="file.url"
alt=""
/>
<!-- <div v-else class="picture-card-container">
<img class="picture-card" :src="urlTemp" alt="" />
<p class="file-name">{{ file.name }}</p>
</div> -->
<span class="el-upload-list__item-actions">
<!-- <span
v-if="updataIf(file)"
class="el-upload-list__item-delete"
@click="handleDownload(file)"
>
<i class="el-icon-download" />
</span> -->
<span class="el-upload-list__item-preview" @click="picturePreviewFbs(file)">
<i class="el-icon-zoom-in" />
</span>
<span
v-if="!isDetail"
class="el-upload-list__item-delete"
@click="handleRemoveElectricianImgList(file)"
>
<i class="el-icon-delete" />
</span>
</span>
</div>
<i class="el-icon-plus avatar-uploader-icon">
<div style="font-size: 14px; margin-top: 10px">上传图片</div>
</i>
</el-upload>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10" class="mb8">
<el-form v-show="showSearch" :model="queryParams" ref="queryForm" size="small" inline>
<el-form-item label="物资类型" prop="maId">
<treeselect
v-model="queryParams.maId"
:options="materialTypeOpts"
:normalizer="normalizer2"
:show-count="true"
style="width: 100%"
:disable-branch-nodes="true"
noChildrenText="没有数据了"
noOptionsText="没有数据"
noResultsText="没有搜索结果"
placeholder="请选择物资类型"
@select="selectMaType"
/>
</el-form-item>
<el-form-item label="规格型号" prop="typeId">
<el-select v-model="queryParams.typeId" placeholder="请选择规格型号" clearable filterable>
<el-option
v-for="item in typeModelNameOpts"
:key="item.typeId"
:label="item.name"
:value="item.typeId"
/>
</el-select>
</el-form-item>
<el-form-item label="关键字" prop="keyWord">
<el-input
v-model="queryParams.keyWord"
placeholder="请输入关键字"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- 表单按钮 -->
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleSave"
v-if="!isDetail"
>
{{ isEdit ? '保存' : '发起提交' }}
</el-button>
<el-button
type="primary"
plain
icon="el-icon-arrow-left"
size="mini"
@click="handleApplyRecord"
>
直转记录查看
</el-button>
</el-form-item>
</el-form>
</el-row>
</el-form>
<!-- 数据状态提示 -->
<div class="data-status-info" style="margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center;">
<!-- 分页状态 -->
<div style="padding: 8px 12px; background-color: #f8fafc; border: 1px solid #e2e8f0; border-radius: 4px; color: #475569; font-size: 14px;">
<i class="el-icon-info"></i>
总共 <strong>{{ total }}</strong> 条数据,当前显示第 <strong>{{ queryParams.pageNum }}</strong> 页,每页 <strong>{{ queryParams.pageSize }}</strong> 条
</div>
<!-- 选中数量提示 -->
<div v-if="multipleSelection.length > 0" style="padding: 8px 12px; background-color: #f0f9ff; border: 1px solid #bfdbfe; border-radius: 4px; color: #1e40af;">
<i class="el-icon-info"></i>
已选中 <strong>{{ multipleSelection.length }}</strong> 条数据
<span style="margin-left: 10px; font-size: 12px; color: #64748b;">
<!-- (当前页: {{ equipmentList.filter(row => row.isActive).length }} 条, 全部: {{ selectedDataArray.length }} 条)-->
</span>
<el-button type="text" size="mini" style="margin-left: 10px; color: #ef4444;" @click="clearCrossPageSelection">
清空选择
</el-button>
</div>
</div>
<el-table
v-loading="loading"
ref="equipmentList"
:data="equipmentList"
:row-key="getRowKey"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" :selectable="checkSelectable" />
<el-table-column align="center" label="序号" width="55">
<template slot-scope="scope">
{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column
v-for="(column, index) in tableColumns"
:key="column.prop"
:label="column.label"
:prop="column.prop"
align="center"
show-overflow-tooltip
>
<template v-slot="scope" v-if="column.prop == 'directNum'">
<el-input-number
v-model="scope.row.directNum"
:value="scope.row.directNum || ''"
controls-position="right"
:precision="scope.row.unitValue == 1 ? 3 : 0"
style="width: 100%"
:disabled="isDetail || !scope.row.isActive"
:min="scope.row.unitValue == 1 ? 0.001 : 1"
@change="directNumChange(scope.row)"
></el-input-number>
</template>
<template v-slot="{ row }" v-else-if="column.prop == 'remark'">
<span style="color: #ef4444;">{{ checkSelectable(row) ? '' : '超检验周期' }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="操作" align="center" v-if="!isDetail">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-delete" style="color: red" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column> -->
</el-table>
<!-- 分页组件 -->
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 图片查看弹窗 -->
<el-dialog :visible.sync="dialogVisible" width="600px" height="600px">
<img width="100%" height="500px" :src="dialogImageUrl" />
</el-dialog>
</div>
</template>
<script>
import { getMaTypeOpt } from '@/api/ma/base'
import {getListProject, getListUnite, getAgreement, getUnitProDepList} from '@/api/lease/apply'
import { downloadFile, downloadFileData } from '@/utils/download'
import { getUseringData, receiveSubmitTwo, receiveEdit, receiveDetail, getEquipmentThreeTypes } from '@/api/business/index'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { getToken } from '@/utils/auth'
import Pagination from '@/components/Pagination'
export default {
name: 'DirectApply',
dicts: ['purchase_task_status'],
components: { Treeselect, Pagination },
data() {
return {
id: '',
isEdit: false, // 是否编辑
isDetail: false, // 是否查看
// 遮罩层
loading: false,
loadingTwo: false,
// 选中数组
multipleSelection: [],
// 回显选中数据
multipleSelectionTemp: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
selectTreeProps: {
children: 'children',
label: 'name',
// multiple: false,
value: 'id'
// multiple: true,
},
//租赁单位
uniteList: [],
lessUniteList: [],
//租赁工程
projectList: [],
leaseProjectList: [],
// 物资类型
materialTypeOpts: [],
// 类型规格
typeModelNameOpts: [],
// 表格数据
equipmentList: [],
// 表头
tableColumns: [
{ label: '直转数量', prop: 'directNum' },
{ label: '类型名称', prop: 'typeName' },
{ label: '规格型号', prop: 'typeModelName' },
{ label: '设备编码', prop: 'maCode' },
{ label: '计量单位', prop: 'unitName' },
{ label: '在用数量', prop: 'useNum' },
{ label: '待转数量', prop: 'waitTransNum' },
{ label: '可转数量', prop:'transNum' },
{ label: '领料人', prop: 'leasePerson' },
{ label: '领料日期', prop: 'startTime' },
{ label: '备注', prop: 'remark' },
],
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
rowData: {},
unitId: null,
projectId: null,
// 查询参数
queryParams: {
pageNum: 1, // 当前页码
pageSize: 20, // 每页显示数量
maId: undefined, // 物资类型
typeId: '', // 类型规格
keyWord: ''
},
// 前端分页数据
allData: [], // 存储所有数据
// 跨页勾选数据专用数组
selectedDataArray: [], // 专门存储所有选中的完整数据
// 防止事件循环的标志位
isRestoringSelection: false, // 正在恢复选中状态时为true
maForm: {
backUnitId: undefined,
backProId: undefined,
backMan: '', // 转出人
backPhone: '', // 联系电话
backAgreementId: '', // 转出协议id
backAgreementCode: '', // 转出协议编号
leaseUnitId: undefined, // 转入单位
leaseProId: undefined, // 转入工程
leaseMan: '', // 转入人
leasePhone: '', // 联系电话
leaseAgreementId: '', // 转入协议id
leaseAgreementCode: '', // 转入协议编号
dirUrls: [] // 附件
},
// 表单参数
form: {},
defaultProps: {
children: 'children',
label: 'label'
},
// 表单校验
rules: {
backUnitId: [
{
required: true,
message: '请选择转出单位',
trigger: 'blur'
}
],
backProId: [
{
required: true,
message: '请选择转出工程',
trigger: 'blur'
}
],
backMan: [
{
required: true,
message: '请输入转出人',
trigger: 'blur'
}
],
backPhone: [
{ required: true, message: '联系电话不能为空', trigger: 'blur' },
{
pattern: /^(?:(?:\+|00)86)?1[3-9]\d{9}$/,
message: '请输入正确的手机号码',
trigger: 'blur'
}
],
leaseUnitId: [
{
required: true,
message: '请选择转入单位',
trigger: 'blur'
}
],
leaseProId: [
{
required: true,
message: '请选择转入工程',
trigger: 'blur'
}
],
leaseMan: [
{
required: true,
message: '请输入转入人',
trigger: 'blur'
}
],
leasePhone: [
{ required: true, message: '联系电话不能为空', trigger: 'blur' },
{
pattern: /^(?:(?:\+|00)86)?1[3-9]\d{9}$/,
message: '请输入正确的手机号码',
trigger: 'blur'
}
],
dirUrls: [
{
required: true, // 是否分包商(是:合同编号必填)
message: '请上传图片',
trigger: 'change'
}
]
},
urlTemp: '',
delBusinessFileIdList: [],
//图片查看弹窗
dialogImageUrl: '',
dialogVisible: false,
uploadKey: Date.now(),
uploadUrl: process.env.VUE_APP_BASE_API + '/file/upload', // 上传的图片服务器地址
headers: { Authorization: 'Bearer ' + getToken() }
}
},
computed: {
//图片上传1张后隐藏上传框
uploadDisabled() {
return this.maForm.dirUrls && this.maForm.dirUrls.length == 3
}
},
created() {
// 初始化标志位
this.isRestoringSelection = false
if (this.$route.query.type == 'edit') {
this.isEdit = true
this.isDetail = false
this.id = this.$route.query.id
const obj = Object.assign({}, this.$route, { title: '直转申请编辑' })
this.$tab.updatePage(obj)
} else if (this.$route.query.type == 'detail') {
this.isEdit = false
this.isDetail = true
this.id = this.$route.query.id
const obj = Object.assign({}, this.$route, { title: '直转申请详情' })
this.$tab.updatePage(obj)
} else {
this.isEdit = false
this.isDetail = false
this.id = ''
const obj = Object.assign({}, this.$route, { title: '直转申请' })
this.$tab.updatePage(obj)
}
this.projectInfoList() // 单位工程下拉选
if (this.isEdit || this.isDetail) {
console.log('isEdit', this.isEdit)
this.getTaskInfo()
}
console.log(this.$store, 'this.$store.getters')
console.log(this.$route.query, 'this.$route.query')
},
watch: {
// this.maForm.backAgreementId 变化时执行
'maForm.backAgreementId': {
handler: function (val, oldVal) {
if (val && val !== oldVal) {
this.getMaTypeOpt()
// 协议变化时清空数据
this.allData = []
this.clearCrossPageSelection()
this.queryParams.pageNum = 1
}
},
deep: true
}
},
methods: {
// 查询
handleQuery() {
// 重置分页到第一页
this.queryParams.pageNum = 1
// 清空缓存数据,强制重新获取
this.allData = []
this.getList()
},
// 重置
handleReset() {
this.$refs.queryForm.resetFields()
// 重置分页
this.queryParams.pageNum = 1
// 清空缓存数据,强制重新获取
this.allData = []
// 清空跨页选中状态
this.clearCrossPageSelection()
this.getList()
},
// 清空跨页选中状态
clearCrossPageSelection() {
console.log('=== 清空所有选中状态 ===')
// 清空数据
this.selectedDataArray = []
this.multipleSelection = []
// 清空当前页表格的选中样式
if (this.$refs.equipmentList) {
// 设置标志位防止触发selection-change事件
this.isRestoringSelection = true
this.$refs.equipmentList.clearSelection()
// 清空当前页数据的isActive状态
this.equipmentList.forEach(item => {
item.isActive = false
if (!this.isEdit && !this.isDetail) {
item.directNum = undefined
}
})
// 重置标志位
this.$nextTick(() => {
this.isRestoringSelection = false
console.log('清空选中状态完成')
})
} else {
this.isRestoringSelection = false // 重置标志位
}
},
// 清空所有状态
clearAllStates() {
this.allData = []
this.equipmentList = []
this.total = 0
this.clearCrossPageSelection()
this.queryParams.pageNum = 1
},
// 获取列表
async getList() {
this.loading = true
try {
// 只在第一次查询或者查询条件变化时重新获取数据
const needRefreshData = this.queryParams.pageNum === 1 || this.allData.length === 0
if (needRefreshData) {
const params = {
agreementId: this.maForm.backAgreementId,
maId: this.queryParams.maId,
typeId: this.queryParams.typeId,
keyWord: this.queryParams.keyWord
// 不传递分页参数,获取全量数据
}
const res = await getUseringData(params)
console.log('🚀 ~ 获取列表 ~ res:', res)
// 存储全量数据
if (res.data && res.data.records) {
this.allData = res.data.records
} else if (Array.isArray(res.data)) {
this.allData = res.data
} else {
this.allData = []
}
}
// 前端分页处理
this.total = this.allData.length
const startIndex = (this.queryParams.pageNum - 1) * this.queryParams.pageSize
const endIndex = startIndex + this.queryParams.pageSize
// 设置标志位防止更新equipmentList时触发selection-change事件
this.isRestoringSelection = true
this.equipmentList = this.allData.slice(startIndex, endIndex)
console.log(`🚀 ~ 分页信息 ~ 总数据:${this.total}, 当前页:${this.queryParams.pageNum}, 每页:${this.queryParams.pageSize}, 当前页数据:${this.equipmentList.length}`)
// 编辑模式下的回显数据处理(只在第一次加载时执行)
if ((this.isEdit || this.isDetail) && this.multipleSelectionTemp.length > 0 && needRefreshData) {
console.log('编辑模式初始化选中数据:', this.multipleSelectionTemp.length)
// 将编辑数据添加到选中数据数组中
this.selectedDataArray = [...this.multipleSelectionTemp.map(row => ({
...row,
isActive: true
}))]
this.updateCrossPageSelection()
console.log('编辑模式回显选中数据已添加到selectedDataArray:', this.selectedDataArray.length)
}
// 恢复当前页的勾选状态
this.$nextTick(() => {
this.restoreCurrentPageSelection()
})
} catch (error) {
console.log('🚀 ~ 获取列表 ~ error:', error)
this.allData = []
this.equipmentList = []
this.total = 0
} finally {
this.loading = false
}
},
// 获取物资类型
async getMaTypeOpt() {
try {
const params = {
agreementId: this.maForm.backAgreementId
}
console.log('🚀 ~ getMaTypeOpt ~ params:', params)
const res = await getEquipmentThreeTypes(params)
console.log('🚀 ~ getMaTypeOpt ~ res:', res)
this.materialTypeOpts = res.data
} catch (error) {
console.log('🚀 ~ getMaTypeOpt ~ error:', error)
}
},
// 获取规格型号
async getTypeModelNameOpt(type) {
try {
const params = {
typeId: type.typeId
}
const res = await getMaTypeOpt(params)
console.log('🚀 ~ getTypeModelNameOpt ~ res:', res)
this.typeModelNameOpts = res.data
} catch (error) {
console.log('🚀 ~ getTypeModelNameOpt ~ error:', error)
}
},
// 获取协议id
async getAgreementId() {
try {
const params = {
unitId: this.maForm.backUnitId,
projectId: this.maForm.backProId
}
const res = await getAgreement(params)
console.log('🚀 ~ getAgreementId ~ res:', res)
this.maForm.backAgreementId = res.data.agreementId
this.maForm.backAgreementCode = res.data.agreementCode
// 协议变化时清空缓存数据和选中状态
this.allData = []
this.clearCrossPageSelection()
this.queryParams.pageNum = 1
this.getList()
} catch (error) {
console.log('🚀 ~ getAgreementId ~ error:', error)
}
},
async getLeaseAgreementId() {
try {
const params = {
unitId: this.maForm.leaseUnitId,
projectId: this.maForm.leaseProId
}
const res = await getAgreement(params)
console.log('🚀 ~ getAgreementId ~ res:', res)
this.maForm.leaseAgreementId = res.data.agreementId
this.maForm.leaseAgreementCode = res.data.agreementCode
} catch (error) {
console.log('🚀 ~ getAgreementId ~ error:', error)
}
},
// 查看领料记录
handleApplyRecord() {
this.$router.push({ path: '/business/businessHandlingRecord/directApplyRecord' })
},
/** 转换菜单数据结构 */
normalizer(node) {
if (node.children && !node.children.length) {
delete node.children
}
return {
id: node.id,
label: node.name,
children: node.children
}
},
normalizer2(node) {
if (node.children && !node.children.length) {
delete node.children
}
return {
id: node.typeId,
label: node.typeName,
children: node.children
}
},
selectMaType(val) {
console.log('val', val)
this.queryParams.typeModelName = ''
this.typeModelNameOpts = []
this.getTypeModelNameOpt(val)
},
uniteChange(val) {
setTimeout(() => {
getListProject({ unitId: this.maForm.backUnitId,enableFilter: true }).then(response => {
this.projectList = response.data
this.maForm.backProId = null
})
}, 500)
},
projectChange(val) {
setTimeout(() => {
getListUnite({enableFilter: true}).then(response => {
this.uniteList = response.data
})
this.getAgreementId()
}, 500)
},
leaseUniteChange(val) {
setTimeout(() => {
getListProject({ unitId: this.maForm.leaseUnitId }).then(res => {
this.leaseProjectList = res.data
this.maForm.leaseProId = null
})
}, 500)
},
leaseProjectChange(val) {
setTimeout(() => {
getListUnite({}).then(res => {
this.leaseUniteList = res.data
})
this.getLeaseAgreementId()
}, 500)
},
/** 租赁单位和工程-下拉选 */
projectInfoList() {
console.log("kkkkkkkkkkk",this.isEdit)
if (!this.isEdit) {
//转出单位
getUnitProDepList({ projectId: null,enableFilter: true }).then(response => {
this.uniteList = response.data
})
//转出工程
getListProject({ unitId: null,enableFilter: true }).then(response => {
this.projectList = response.data
})
//转入单位
getUnitProDepList({ projectId: null }).then(response => {
this.lessUniteList = response.data
})
//转入工程
getListProject({ unitId: null }).then(response => {
this.leaseProjectList = response.data
})
} else {
//转出单位
getUnitProDepList({ projectId: null,enableFilter: true }).then(response => {
this.uniteList = response.data
})
//转出工程
getListProject({ unitId: this.maForm.backUnitId,enableFilter: true }).then(response => {
this.projectList = response.data
})
//转入单位
getUnitProDepList({ projectId: null }).then(response => {
this.lessUniteList = response.data
})
//转入工程
getListProject({ unitId: this.maForm.leaseUnitId }).then(response => {
this.leaseProjectList = response.data
})
}
},
//获取任务详情--- 编辑回显数据
async getTaskInfo() {
const loading = this.$loading()
try {
const res = await receiveDetail({ id: this.id })
console.log('🚀 ~ getTaskInfo ~ res:', res)
this.maForm = res.data
this.multipleSelectionTemp = res.data.directApplyDetails
this.getList()
console.log('🚀 ~ getTaskInfo ~ this.equipmentList:', this.equipmentList)
loading.close()
} catch (error) {
console.log('🚀 ~ error:', error)
loading.close()
}
},
checkSelectable(row) {
if(row.transNum==0){
return false
}
if (!row.nextCheckTime) return true // 如果没有时间,不禁用
const now = new Date()
const nextCheckTime = new Date(row.nextCheckTime)
return nextCheckTime >= now // 如果时间未到,允许选中;否则禁用
},
// 多选框选中数据
handleSelectionChange(currentPageSelectedRows) {
// 如果正在恢复选中状态,忽略此事件
if (this.isRestoringSelection) {
console.log('正在恢复选中状态忽略selection-change事件')
console.trace('忽略selection-change的调用栈:')
return
}
console.log('=== handleSelectionChange 开始 ===')
console.trace('handleSelectionChange调用栈:')
console.log('当前页选中数据:', currentPageSelectedRows)
console.log('选中前全局数据数量:', this.selectedDataArray.length)
console.log('当前页码:', this.queryParams.pageNum)
// 获取当前页所有数据的rowKey
const currentPageRowKeys = this.equipmentList.map(item => this.getRowKey(item))
// 从selectedDataArray中移除属于当前页的数据不影响其他页面的数据
const beforeCount = this.selectedDataArray.length
this.selectedDataArray = this.selectedDataArray.filter(item =>
!currentPageRowKeys.includes(this.getRowKey(item))
)
const afterCount = this.selectedDataArray.length
console.log(`移除当前页数据:${beforeCount} -> ${afterCount},移除了 ${beforeCount - afterCount}`)
// 添加当前页新选中的数据到数组中
currentPageSelectedRows.forEach(row => {
const completeRow = {
...row,
directNum: row.directNum || row.transNum,
isActive: true
}
this.selectedDataArray.push(completeRow)
})
console.log(`添加当前页选中数据:${currentPageSelectedRows.length}`)
// 更新当前页的isActive状态
this.equipmentList.forEach(item => {
const isSelected = currentPageSelectedRows.some(selectedRow => this.getRowKey(selectedRow) === this.getRowKey(item))
item.isActive = isSelected
if (isSelected && !item.directNum && item.transNum) {
item.directNum = item.transNum
} else if (!isSelected && !this.isEdit && !this.isDetail) {
item.directNum = undefined
}
})
// 更新multipleSelection
this.multipleSelection = [...this.selectedDataArray]
console.log('选中后全局数据数量:', this.selectedDataArray.length)
console.log('当前页选中rowKey列表:', currentPageSelectedRows.map(row => this.getRowKey(row)))
console.log('全局选中rowKey列表:', this.selectedDataArray.map(row => this.getRowKey(row)))
console.log('=== handleSelectionChange 结束 ===')
console.log('')
},
// 数量变更
directNumChange(row) {
if (row.unitValue == 1) {
row.directNum = Number(String(row.directNum).replace(/[^\d.]/g, ''))
} else {
row.directNum = Number(String(row.directNum).replace(/[^\d]/g, ''))
}
if (row.directNum > row.transNum) {
this.$message.error('直转数量不能大于可转数量')
this.$nextTick(() => {
row.directNum = row.transNum
})
}
// 如果行被选中,同步更新跨页选中数据数组
const rowKey = this.getRowKey(row)
const selectedIndex = this.selectedDataArray.findIndex(item => this.getRowKey(item) === rowKey)
if (selectedIndex !== -1) {
// 更新数组中对应的数据
this.selectedDataArray[selectedIndex] = {
...this.selectedDataArray[selectedIndex],
...row,
directNum: row.directNum,
isActive: true
}
// 同步更新multipleSelection
this.multipleSelection = [...this.selectedDataArray]
console.log('数量变更后跨页选中总数:', this.selectedDataArray.length)
}
},
// 获取行的唯一标识
getRowKey(row) {
// 使用最核心的字段确保唯一性,避免编辑数据和实际数据的字段差异
const key = `${row.typeId || row.id || 'unknown'}_${row.maCode || ''}_${row.typeModelName || ''}`
// 在调试模式下记录 rowKey 生成
// console.log('生成rowKey:', key, 'for:', row.typeModelName)
return key
},
// 恢复当前页的勾选状态
restoreCurrentPageSelection() {
// 如果标志位未设置,则设置它
if (!this.isRestoringSelection) {
this.isRestoringSelection = true
}
this.$nextTick(() => {
if (!this.$refs.equipmentList) {
this.isRestoringSelection = false // 确保标志位重置
return
}
console.log('=== 开始恢复选中状态 ===')
console.log('标志位状态:', this.isRestoringSelection)
console.log('全局选中数量:', this.selectedDataArray.length)
console.log('当前页数据数量:', this.equipmentList.length)
console.log('当前页码:', this.queryParams.pageNum)
console.log('是否编辑模式:', this.isEdit || this.isDetail)
if (this.selectedDataArray.length > 0) {
console.log('全局选中数据的前3个rowKey:', this.selectedDataArray.slice(0, 3).map(item => this.getRowKey(item)))
console.log('当前页数据的前3个rowKey:', this.equipmentList.slice(0, 3).map(item => this.getRowKey(item)))
}
try {
// 先清除所有选中状态(此时标志位已设置)
this.$refs.equipmentList.clearSelection()
// 遍历当前页数据,检查是否在选中数组中
let matchedCount = 0
this.equipmentList.forEach(row => {
const rowKey = this.getRowKey(row)
// 在选中数组中查找对应的数据
const selectedData = this.selectedDataArray.find(item => this.getRowKey(item) === rowKey)
if (selectedData) {
matchedCount++
// 恢复保存的数据
row.directNum = selectedData.directNum
row.isActive = true
// 恢复表格选中状态
this.$refs.equipmentList.toggleRowSelection(row, true)
console.log(`恢复选中: ${rowKey}`)
} else {
row.isActive = false
if (!this.isEdit && !this.isDetail) {
row.directNum = undefined
}
}
})
console.log(`当前页匹配到 ${matchedCount} 条选中数据`)
// 如果是编辑模式且匹配数量为0显示详细的调试信息
if ((this.isEdit || this.isDetail) && matchedCount === 0 && this.selectedDataArray.length > 0) {
console.warn('编辑模式下当前页没有匹配到任何选中数据检查rowKey匹配:')
console.log('当前页所有rowKey:', this.equipmentList.map(item => this.getRowKey(item)))
console.log('全局选中所有rowKey:', this.selectedDataArray.map(item => this.getRowKey(item)))
}
const restoredCount = this.equipmentList.filter(row => row.isActive).length
console.log('恢复选中状态完成,当前页选中数量:', this.$refs.equipmentList.selection?.length || 0)
console.log('恢复选中状态完成当前页isActive数量:', restoredCount)
console.log('全局选中数量:', this.selectedDataArray.length)
console.log('当前页应该恢复的rowKey:', this.equipmentList.filter(row => {
const rowKey = this.getRowKey(row)
return this.selectedDataArray.some(item => this.getRowKey(item) === rowKey)
}).map(row => this.getRowKey(row)))
console.log('=== 恢复选中状态结束 ===')
console.log('')
} catch (error) {
console.error('恢复选中状态时出错:', error)
} finally {
// 无论如何都要清除标志位
this.isRestoringSelection = false
console.log('标志位已重置为:', this.isRestoringSelection)
}
})
},
// 更新跨页选中状态
updateCrossPageSelection() {
// 直接使用选中数据数组
this.multipleSelection = [...this.selectedDataArray]
},
/** 保存按钮操作 */
handleSave() {
// 确保使用最新的跨页选中数据
this.updateCrossPageSelection()
console.log('=== 保存操作开始 ===')
console.log('maForm', this.maForm)
console.log('selectedDataArray:', this.selectedDataArray)
console.log('multipleSelection:', this.multipleSelection)
console.log('选中数据总数:', this.selectedDataArray.length)
console.log('=====================')
if (this.selectedDataArray.length > 0) {
this.$refs['maForm'].validate(valid => {
if (valid) {
this.$modal.confirm('是否确认提交').then(async () => {
const isPass = this.multipleSelection.every(item => {
return item.directNum
})
if (!isPass) {
this.$message.error('请填写直转数量且不能为0')
return
}
const loading = this.$loading()
try {
const params = {
directApplyInfo: this.maForm,
directApplyInfoDetails: this.multipleSelection
}
let fileList = []
console.log('params2222222222', params)
if (params.directApplyInfo.dirUrls.length > 0) {
fileList = params.directApplyInfo.dirUrls.map(e => {
if(e.response && e.response.code===200){
return {
name: e.response.data.name,
url: e.response.data.url,
type: e.response.data.url.substring(
e.response.data.url.lastIndexOf('.') + 1
)
}
}else{
return {
name: null,
url: e.url,
}
}
// console.log("11111111111",e.response)
// if (e.response.code === 200) {
// return {
// name: e.response.data.name,
// url: e.response.data.url,
// type: e.response.data.url.substring(
// e.response.data.url.lastIndexOf('.') + 1
// )
// }
// }
})
}
params.directApplyInfo.dirUrls = fileList
if (this.isEdit) {
delete params.directApplyInfo.directApplyDetails
console.log('🚀 ~ this.$modal.confirm ~ params:', params)
const res = await receiveEdit(params)
console.log('🚀 ~ handleSave ~ res:', res)
} else {
const res = await receiveSubmitTwo(params)
console.log('🚀 ~ handleSave ~ res:', res)
}
this.$message.success('操作成功')
this.$refs['maForm'].resetFields()
// 清空所有状态
this.clearAllStates()
this.delBusinessFileIdList = []
loading.close()
} catch (error) {
console.log('🚀 ~ handleSave ~ error:', error)
loading.close()
}
})
}
})
} else {
this.$modal.msgError('请先选择转出数据')
}
},
// 上传图片
handleChangeBusinessList(file, fileList) {
console.log("iiiiiiiiiiiiiiiiii",file)
console.log("ppppppppp",fileList)
const fileListTemp = fileList.filter(item => {
return item.uid != file.uid
})
const parts = file.name?.split('.')
const extension = parts?.pop().toLowerCase()
if (fileList.length > 3) {
this.$message.warning('最多上传3张附件')
fileList = fileList.filter(item => {
return item.uid != file.uid
})
} else if (!(extension === 'png' || extension === 'jpg' || extension === 'jpeg' || extension === 'pdf')) {
this.$message.warning('文件格式不正确')
fileList = fileList.filter(item => {
return item.uid != file.uid
})
} else if (file.size > 1024 * 1024 * 10) {
this.$message.warning('文件大小不能超过10Mb')
fileList = fileList.filter(item => {
return item.uid != file.uid
})
} else if (file.name.length > 40) {
this.$message.warning('文件名长度不能超过40个字符')
fileList = fileList.filter(item => {
return item.uid != file.uid
})
} else if (fileListTemp.some(item => item.name === file.name)) {
this.$message.warning('文件名重复')
fileList = fileList.filter(item => {
return item.uid != file.uid
})
}
fileList.forEach(file => {
if (extension === 'pdf') {
this.urlTemp = require('@/assets/file.png')
}
})
this.maForm.dirUrls = fileList
console.log('🚀 ~ handleChangeBusinessList ~ this.dirUrls:', this.dirUrls)
// 手动触发表单验证
this.$refs.maForm.validateField('dirUrls')
},
// 判断文件类型
isImage(file) {
this.urlTemp = require('@/assets/file.png')
if (this.updataIf(file)) {
return false
} else {
return true
}
},
// 判断文件类型,图片预览,文件下载
updataIf(e) {
if (e.fileName) {
const parts = e.fileName?.split('.')
const extension = parts?.pop().toLowerCase()
if (extension === 'png' || extension === 'jpeg' || extension === 'jpg') {
return false
} else {
return true
}
} else {
const parts = e.url?.split('.')
const extension = parts?.pop().toLowerCase()
if (extension === 'png' || extension === 'jpeg' || extension === 'jpg') {
return false
} else {
return true
}
}
},
beforeUpload(file) {
const validExtensions = ['.png', '.jpg', '.jpeg', '.pdf'];
const fileName = file.name.toLowerCase();
const hasValidExtension = validExtensions.some(ext => fileName.endsWith(ext));
if (!hasValidExtension) {
this.$message.error('仅支持上传 .png, .jpg, .jpeg, .pdf 格式的文件');
return false;
}
// 检查文件大小是否超过 10MB
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
this.$message.error('文件大小不能超过 10MB');
return false;
}
// 检查文件名长度是否超过 40 个字符
if (file.name.length > 40) {
this.$message.error('文件名长度不能超过 40 个字符');
return false;
}
return true;
},
//上传组件-图片查看
picturePreviewFbs(file) {
console.log("xxxxxxxxxxxx",file)
this.dialogImageUrl =file.response ? file.response.data.url : file.url.replaceAll('#', '%23')
console.log("zzzzzzzzzz",this.dialogImageUrl)
// const parts = file.name ? file.name:file.url.split('.')
// console.log("yyyyyyyyy",parts)
// const extension = parts?.pop()
// if (extension === 'pdf') {
// const windowName = file.name ? file.name : file.url
// window.open(file.url, windowName)
// } else {
this.dialogVisible = true
// }
},
//上传组件-图片删除
handleRemoveElectricianImgList(file, fileList) {
let sum = 0
this.maForm.dirUrls.forEach((item, index) => {
if (item.uid == file.uid) {
sum = index
}
})
this.maForm.dirUrls.splice(sum, 1)
if (file.status == 'success') {
this.delBusinessFileIdList.push(file.url)
}
console.log('delBusinessFileIdList', this.delBusinessFileIdList)
},
handleDownload(file) {
console.log(file)
if (file.status === 'ready') {
downloadFile({
fileName: file.name ? file.name : file.url,
fileData: file.raw,
fileType: 'application/vnd.ms-excel;charset=utf-8'
})
} else if (file.status === 'success') {
downloadFileData({ fileName: file.url, fileUrl: file.url })
}
}
}
}
</script>
<style lang="scss" scoped>
//隐藏图片上传框的css
::v-deep .disabledFbs {
.el-upload--picture-card {
display: none;
width: 100px;
height: 100px;
}
}
::v-deep .el-upload--picture-card {
width: 100px;
height: 100px;
}
::v-deep .el-upload-list__item {
margin-bottom: 20px;
overflow: unset !important;
width: 103px;
height: 103px;
}
::v-deep .el-upload-list__item-actions {
overflow: unset !important;
width: 100px;
height: 100px;
}
.popper-select {
.el-cascader-panel .el-scrollbar .el-checkbox {
display: none;
}
.el-cascader-panel .el-scrollbar:nth-child(4) .el-checkbox {
display: block !important;
}
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-icon-arrow-down.is-reverse {
transform: rotateZ(180deg);
}
// .el-tree {
// max-height: 300px;
// overflow-y: auto;
// }
::v-deep .highlight-text {
background-color: #ffd04b;
color: #000;
}
::v-deep .el-input-group__append {
padding: 0;
.el-button {
padding: 0 10px;
border: none;
height: 100%;
&:first-child {
border-right: 1px solid #dcdfe6;
}
&[disabled] {
color: #c0c4cc;
}
}
}
.type-select-dropdown {
.el-select-dropdown__wrap {
max-height: 400px !important;
}
.el-select-dropdown__item {
height: auto;
padding: 8px 20px;
white-space: normal;
word-break: break-all;
}
}
.el-input-group__append {
padding: 0;
.el-button {
padding: 0 10px;
border: none;
height: 100%;
&:first-child {
border-right: 1px solid #dcdfe6;
}
&[disabled] {
color: #c0c4cc;
}
}
}
.el-upload-list__item-thumbnail {
/* height: 145px !important; */
width: 100px;
height: 100px;
}
.picture-card-container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
.picture-card {
width: 100%;
height: 100%;
object-fit: cover;
justify-content: center;
// border: 1px solid #ddd;
// border-radius: 4px;
}
.file-name {
width: 90%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
position: absolute;
bottom: -35px;
margin-top: 8px;
text-align: center;
font-size: 12px;
color: #333;
z-index: 999999;
}
.file-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-size: 20px;
}
// 居中
.cont-center {
display: flex;
justify-content: center;
align-items: center;
}
// 数据状态提示样式
.data-status-info {
font-size: 14px;
@media (max-width: 768px) {
flex-direction: column;
gap: 10px;
align-items: stretch !important;
}
strong {
font-weight: 600;
}
.el-button--text {
padding: 0;
margin-left: 15px;
&:hover {
color: #dc2626 !important;
}
}
.el-icon-info {
margin-right: 5px;
font-size: 16px;
}
}
::v-deep .vue-treeselect__single-value {
position: inherit !important;
white-space: pre-wrap !important;
}
</style>