bonus-ui/src/views/business/apply/addApply.vue

1110 lines
38 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-card v-show="showSearch" style="margin-bottom: 20px">
<el-form :model="queryParams" ref="queryForm" :rules="outFormRules" inline label-width="110px">
<el-form-item label="需求单位" prop="useUnit">
<el-input style="width: 200px" v-model="queryParams.useUnit" placeholder="请输入需求单位"
:disabled="queryParams.status=='0'" clearable
/>
</el-form-item>
<el-form-item label="使用项目" prop="proCode">
<el-select
clearable
:disabled="!routerParams.isEdit"
style="width: 200px"
placeholder="请选择使用项目"
v-model="queryParams.proCode"
@change="onChangeProCode"
>
<el-option
:key="item.proCode"
:label="item.proName"
:value="item.proCode"
v-for="item in useProjectList"
/>
</el-select>
</el-form-item>
<el-form-item label="项目类型" prop="proType">
<el-input style="width: 200px" disabled v-model="queryParams.proType"/>
</el-form-item>
<el-form-item label="电压等级" prop="voltageLevel">
<el-input style="width: 200px" disabled v-model="queryParams.voltageLevel"/>
</el-form-item>
<el-form-item label="项目所在省" prop="proProvince">
<el-input style="width: 200px" disabled v-model="queryParams.proProvince"/>
</el-form-item>
<el-form-item label="项目所在市" prop="proCity">
<el-input style="width: 200px" disabled v-model="queryParams.proCity"/>
</el-form-item>
<el-form-item label="项目所在区/县" prop="proCounty">
<el-input style="width: 200px" disabled v-model="queryParams.proCounty"/>
</el-form-item>
<el-form-item label="使用到期日期" prop="useTimeRange">
<el-date-picker
:disabled="!routerParams.isEdit"
v-model="queryParams.useTimeRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
style="width: 225px"
>
</el-date-picker>
</el-form-item>
</el-form>
</el-card>
<el-card>
<el-row :gutter="10" class="mb8" justify="end">
<el-col :span="4">
<span style="font-size: 20px; font-weight: 800">自用申请设备</span>
</el-col>
<el-col v-if="!routerParams.isView" :span="20" style="display: flex; justify-content: flex-end">
<el-button type="primary" @click="handleDialog">添加</el-button>
<el-button type="primary" @click="submit">确定申请</el-button>
</el-col>
</el-row>
<el-table
v-loading="isLoading"
:data="tableList"
highlight-current-row
border
stripe
:max-height="650"
style="width: 100%"
>
<el-table-column
type="index"
width="55"
label="序号"
align="center"
/>
<el-table-column label="分类" align="center" prop="devType" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.row.devType==1">{{ '装备' }}</span>
<span v-if="scope.row.devType==2">{{ '工具' }}</span>
</template>
</el-table-column>
<el-table-column label="类目" align="center" prop="category" :show-overflow-tooltip="true"/>
<el-table-column label="名称" align="center" prop="typeName" :show-overflow-tooltip="true" width="120px"/>
<el-table-column label="规格型号" align="center" prop="typeModelName" :show-overflow-tooltip="true"/>
<el-table-column label="管理模式" align="center" prop="manageType" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.row.manageType==0">{{ '编码设备' }}</span>
<span v-if="scope.row.manageType==1">{{ '数量设备' }}</span>
</template>
</el-table-column>
<el-table-column label="设备编码" align="center" prop="devCode" :show-overflow-tooltip="true" width="140px"/>
<el-table-column label="当前库存" align="center" prop="storageNum" :show-overflow-tooltip="true"/>
<el-table-column label="申请数量" align="center" prop="num" :show-overflow-tooltip="true"/>
<el-table-column label="使用到期日期" align="center" width="250px">
<template slot-scope="scope">
<el-date-picker
:disabled="!routerParams.isEdit"
v-model="scope.row.useTimeRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"
>
</el-date-picker>
</template>
</el-table-column>
<el-table-column label="操作" align="center" v-if="!routerParams.isView">
<template slot-scope="{ row }">
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(row)" style="color: red"
>删除
</el-button
>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 添加申请 -->
<el-dialog title="添加申请" :visible.sync="openAdd" width="1200px" append-to-body>
<!-- 完善后的查询表单:支持类目查询 -->
<el-form :model="addQuery" ref="addQueryForm" label-width="auto" inline class="query-form">
<!-- 分类选择下拉框(装备/工具) -->
<el-form-item label="分类" prop="devType">
<el-select
v-model="addQuery.devType"
placeholder="请选择分类"
clearable
@change="handleDevTypeChange"
style="width: 200px"
>
<el-option label="装备" value="1"/>
<el-option label="工具" value="2"/>
</el-select>
</el-form-item>
<!-- 动态显示:装备类目级联选择器 -->
<el-form-item
v-if="addQuery.devType === '1'"
label="装备类目"
prop="categoryPath"
>
<el-cascader
v-model="addQuery.categoryPath"
:options="processedTreeData"
:props="cascaderProps"
placeholder="请选择装备类目"
clearable
style="width: 200px"
filterable
popper-class="six-level-cascader"
@change="handleCategoryChange"
/>
</el-form-item>
<!-- 动态显示:工具类目级联选择器 -->
<el-form-item
v-if="addQuery.devType === '2'"
label="工具类目"
prop="toolCategoryPath"
>
<el-cascader
v-model="addQuery.toolCategoryPath"
:options="toolTreeData"
:props="toolCascaderProps"
placeholder="请选择工具类目"
clearable
style="width: 200px"
filterable
popper-class="six-level-cascader"
@change="handleToolCategoryChange"
/>
</el-form-item>
<!-- 名称查询 -->
<el-form-item label="名称" prop="typeName">
<el-input
v-model="addQuery.typeName"
maxlength="20"
placeholder="请输入名称"
style="width: 200px"
/>
</el-form-item>
<!-- 规格型号查询 -->
<el-form-item label="规格型号" prop="typeModelName">
<el-input
v-model="addQuery.typeModelName"
maxlength="20"
placeholder="请输入规格型号"
style="width: 200px"
/>
</el-form-item>
<!-- 编码查询 -->
<el-form-item label="编码" prop="devCode">
<el-input
v-model="addQuery.devCode"
maxlength="20"
placeholder="请输入编码"
style="width: 200px"
/>
</el-form-item>
<!-- 管理模式(仅工具显示) -->
<el-form-item
v-if="addQuery.devType === '2'"
label="管理模式"
prop="manageType"
>
<el-select
v-model="addQuery.manageType"
placeholder="请选择管理模式"
clearable
style="width: 200px"
>
<el-option label="编码工具" value="0"/>
<el-option label="数量工具" value="1"/>
</el-select>
</el-form-item>
</el-form>
<!-- 操作按钮行 -->
<el-row :gutter="10" class="mb8" justify="end">
<el-col style="display: flex; justify-content: flex-end">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleAddQuery">查询</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetAddQuery">重置</el-button>
<el-button type="primary" size="mini" @click="saveAdd">确定添加</el-button>
</el-col>
</el-row>
<!-- 设备列表表格 -->
<el-table ref="addTable" :data="addList" height="500" @selection-change="handleSelectionChange" border stripe>
<el-table-column type="selection" width="55" align="center" :selectable="selectable"/>
<el-table-column label="序号" align="center" width="80" type="index">
<template slot-scope="scope">
<span>{{
(addQuery.pageNum - 1) * 10 + scope.$index + 1
}}</span>
</template>
</el-table-column>
<el-table-column label="分类" align="center" prop="devType" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.row.devType==1">{{ '装备' }}</span>
<span v-if="scope.row.devType==2">{{ '工具' }}</span>
</template>
</el-table-column>
<el-table-column label="类目" align="center" prop="category" :show-overflow-tooltip="true"/>
<el-table-column label="名称" align="center" prop="typeName" :show-overflow-tooltip="true"/>
<el-table-column label="规格型号" align="center" prop="typeModelName" :show-overflow-tooltip="true"/>
<el-table-column label="管理模式" align="center" prop="manageType" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.row.manageType==0">{{ '编码设备' }}</span>
<span v-if="scope.row.manageType==1">{{ '数量设备' }}</span>
</template>
</el-table-column>
<el-table-column label="设备编码" align="center" prop="devCode" :show-overflow-tooltip="true" width="140px"/>
<el-table-column label="当前库存" align="center" prop="storageNum" :show-overflow-tooltip="true"/>
<el-table-column label="申请数量" align="center" prop="num">
<template slot-scope="scope">
<span v-if="scope.row.manageType==0">{{ 1 }}</span>
<el-input-number v-if="scope.row.manageType==1" :disabled="isRowSelected(scope.row)" v-model="scope.row.num"
:min="0" :max="scope.row.storageNum" :default-value="0" style="width: 120px"
@change="applyNumChange(scope.row)"
/>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
v-show="addTotal > 0"
:total="addTotal"
:page.sync="addQuery.pageNum"
:limit.sync="addQuery.pageSize"
@pagination="getApplyList"
/>
</el-dialog>
</div>
</template>
<script>
import { getListByApplyIdApi, deleteToolApi, updateToolApplyApi } from '@/api/toolsManage'
import { getApplyListApi, addApplyApi, getApplyDetailsApi, editApplyApi } from '@/api/business'
import {
getUseProjectListAPI,
getVoltageListAPI,
addProjectOutAPI
} from '@/api/EquipmentLedger/equ-out'
import { regionData } from 'element-china-area-data'
import { getEquipmentTreeAPI } from '@/api/EquipmentConfig/index.js'
import { getTreeSelectApi } from '@/api/toolsManage/index.js' // 替换为实际工具接口路径
export default {
name: 'AddEditApply',
data() {
return {
useTimeRange: [], // 主表单的全局日期范围
routerParams: {},
isLoading: false,
showSearch: true,
timeRange: [],
processedTreeData: [], // 装备分类树
toolTreeData: [], // 工具分类树
// 装备分类级联配置
cascaderProps: {
value: 'id',
label: 'name',
children: 'children',
checkStrictly: true,
expandTrigger: 'click'
},
// 工具分类级联配置匹配返回字段typeId/typeName
toolCascaderProps: {
value: 'typeId',
label: 'typeName',
children: 'children',
checkStrictly: true,
expandTrigger: 'click'
},
queryParams: {
type: 2, // 出库
status: '0', // 变更状态
proCode: '', // 使用项目id
proName: '', // 使用项目名称
proType: '', // 项目类型
voltageLevel: '', // 电压等级
proProvince: '', // 项目所在省
proCity: '', // 项目所在市
proCounty: '', // 项目所在区/县
proLocation: '', // 详细地址
useUnit: '', // 需求单位
useTime: null,
leaseType: '0',
pageNum: 1, // 页码
pageSize: 10 // 每页条数
},
useProjectList: [], // 使用项目下拉选
voltageList: [], // 电压等级下拉选
provinceList: [],
cityList: [],
countyList: [],
outFormRules: {
status: [{ required: true, message: '请选择变更状态', trigger: 'change' }],
proCode: [{ required: true, message: '请选择使用项目', trigger: 'change' }],
proType: [{ required: true, message: '请选择项目类型', trigger: 'change' }],
voltageLevel: [{ required: true, message: '请选择电压等级', trigger: 'change' }],
proProvince: [{ required: true, message: '请选择项目所在省', trigger: 'change' }],
proCity: [{ required: true, message: '请选择项目所在市', trigger: 'change' }],
proCounty: [{ required: true, message: '请选择项目所在区/县', trigger: 'change' }],
proLocation: [{ required: true, message: '请输入详细地址', trigger: 'blur' }],
useUnit: [{ required: true, message: '请输入需求单位', trigger: 'blur' }],
useTimeRange: [{ required: true, message: '请选择使用到期日期', trigger: 'change' }]
},
typeList: [
{ label: '数量管理', value: '1' },
{ label: '编码管理', value: '0' }
],
total: 0, // 总条数
tableList: [], // 表格数据
openAdd: false, // 添加申请弹窗开关
addQuery: { // 页面输入的查询参数
typeName: '', // 名称
typeModelName: '', // 规格型号
devCode: '', // 设备编码
devType: '', // 核心分类选择1=装备2=工具)
manageType: '',
categoryPath: '', // 装备分类路径(数组)
toolCategoryPath: '', // 工具分类路径(数组)
pageNum: 1, // 页码
pageSize: 10 // 每页条数
},
filterParams: { // 存储筛选条件(分页时保留)
typeName: '',
typeModelName: '',
devCode: '',
categoryEquipment: '', // 装备分类ID字符串
toolTypeId: '', // 工具分类ID字符串
devType: '',// 筛选类型1=装备2=工具)
manageType: ''
},
addTotal: 0, // 添加申请列表总条数
addList: [], // 添加申请列表数据
addTempList: [], // 添加申请临时列表
ids: [], // 选中的id
single: false, // 单选标识
multiple: false, // 多选标识
// 新增:当前选中的类目名称(用于显示)
currentCategoryName: '',
currentToolCategoryName: ''
}
},
created() {
this.routerParams = this.$route.query
let title = '新增申请'
if (this.routerParams.isView) {
title = '查看申请'
} else if (this.routerParams.isEdit) {
title = '编辑申请'
}
this.queryParams.id = this.routerParams.id || ''
this.getUseProjectList()
// 如果是新增状态,默认填充当前部门名称
if (this.queryParams.status === '0') {
this.queryParams.useUnit = sessionStorage.getItem('deptName')
}
this.provinceList = regionData
const obj = Object.assign({}, this.$route, { title })
this.$tab.updatePage(obj)
this.getList()
this.getEquipmentTree() // 初始化加载装备分类树
this.getToolTree() // 初始化加载工具分类树
},
watch: {
// 监听主表单日期范围变化,同步更新表格中所有行的时间段
'queryParams.useTimeRange'(newVal) {
if (newVal && newVal.length === 2 && this.tableList.length > 0) {
this.tableList.forEach(item => {
item.useTimeRange = [...newVal] // 同步主表单的日期范围
})
}
}
},
methods: {
// 获取使用项目的下拉选
async getUseProjectList() {
try {
const [resProject, resVoltage] = await Promise.all([
getUseProjectListAPI(),
getVoltageListAPI()
])
this.useProjectList = resProject.data || []
this.voltageList = resVoltage.data || []
} catch (error) {
this.$message.error('获取项目或电压等级列表失败')
console.error(error)
}
},
// 选择使用项目
onChangeProCode(value) {
this.queryParams.proCode = value
const item = this.useProjectList.find((item) => item.proCode === value)
if (item) {
this.queryParams.proName = item.proName
const { proTypeName, voltage, city, county, province } = item
this.queryParams.proType = proTypeName
this.queryParams.voltageLevel = voltage + 'kV'
this.queryParams.proProvince = province
this.queryParams.proCity = city
this.queryParams.proCounty = county
}
},
// 选择省份
onChangeProvince(value) {
if (!value) {
this.cityList = []
return
}
this.cityList = this.provinceList.find((item) => item.label === value)?.children || []
},
// 选择城市
onChangeCity(value) {
if (!value) {
this.countyList = []
return
}
this.countyList = this.cityList.find((item) => item.label === value)?.children || []
},
// 获取列表数据
async getList(emit = {}) {
// 如果从emit传入id更新查询参数
if (emit.id) {
this.queryParams.id = emit.id
this.$route.query.id = this.queryParams.id
}
this.isLoading = true
try {
const params = { ...this.queryParams }
const res = await getApplyDetailsApi(params) // 调用接口获取详情
// 初始化表格数据(重点处理日期)
this.tableList = (res.data.devDetailsList || []).map(item => ({
...item,
// 将后端返回的 useStartTime/useEndTime 转为 Date 对象数组(适配 el-date-picker
useTimeRange: item.useStartTime && item.useEndTime
? [new Date(item.useStartTime), new Date(item.useEndTime)]
: [] // 无日期时设为空数组
}))
// 如果是编辑/查看模式,初始化主表单数据
if (this.queryParams.id && res.data.devInfo) {
Object.assign(this.queryParams, res.data.devInfo)
// 初始化主表单的全局日期范围(如果后端返回了全局日期)
if (res.data.devInfo.useStartTime && res.data.devInfo.useEndTime) {
this.queryParams.useTimeRange = [
new Date(res.data.devInfo.useStartTime),
new Date(res.data.devInfo.useEndTime)
]
}
}
this.total = res.data.total || 0
} catch (error) {
this.tableList = []
this.total = 0
this.$message.error('获取申请详情失败')
console.error('getList error:', error)
} finally {
this.isLoading = false
}
},
// 删除列表项
handleDelete(row) {
this.$confirm('此操作将永久删除该申请项, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.tableList = this.tableList.filter((item) => item.id !== row.id)
this.$message({
type: 'success',
message: '删除成功!'
})
}).catch(() => {
// 用户点击取消,不做操作
})
},
// 打开添加申请弹窗
handleDialog() {
this.addQuery.pageNum = 1
this.resetAddQuery() // 打开时重置查询条件和分页
this.openAdd = true
// 确保弹窗打开后表格能正确渲染
this.$nextTick(() => {
if (this.$refs.addTable) {
this.$refs.addTable.clearSelection()
}
})
},
/**
* 分页回调获取添加申请列表数据整合devType筛选
* @param {Object} pagination - 分页参数 { pageNum, pageSize }
*/
getApplyList(pagination = {}) {
// 合并分页参数,优先使用分页组件传递的参数
const pageNum = pagination.pageNum || this.addQuery.pageNum
const pageSize = pagination.pageSize || this.addQuery.pageSize
// 更新组件内的分页状态
this.addQuery.pageNum = pageNum
this.addQuery.pageSize = pageSize
// 构造完整的查询参数包含devType和类目筛选
const queryParams = {
...this.filterParams,
pageNum,
pageSize
}
this.isLoading = true
getApplyListApi(queryParams)
.then(response => {
if (response && response.data) {
this.addList = response.data.rows || []
this.addTotal = response.data.total || 0
// 初始化申请数量
this.addList.forEach(item => {
item.num = item.manageType == '0' ? 1 : 0
})
} else {
this.addList = []
this.addTotal = 0
this.$message.warning('获取数据格式异常')
}
})
.catch(error => {
this.addList = []
this.addTotal = 0
this.$message.error(`获取设备列表失败:${error.message || '未知错误'}`)
console.error('分页查询失败:', error)
})
.finally(() => {
this.isLoading = false
})
},
/**
* 分类切换事件(装备/工具)
*/
handleDevTypeChange(val) {
// 切换分类时,清空对应的类目选择
if (val === '1') {
this.addQuery.toolCategoryPath = ''
this.currentToolCategoryName = ''
} else if (val === '2') {
this.addQuery.categoryPath = ''
this.currentCategoryName = ''
} else {
// 未选择分类时,清空所有类目
this.addQuery.categoryPath = ''
this.addQuery.toolCategoryPath = ''
this.currentCategoryName = ''
this.currentToolCategoryName = ''
}
},
/**
* 装备类目选择变化
*/
handleCategoryChange(value) {
if (value && value.length > 0) {
// 获取选中的最后一级类目名称
let currentNode = this.findNodeInTree(this.processedTreeData, value[value.length - 1])
this.currentCategoryName = currentNode ? currentNode.name : ''
} else {
this.currentCategoryName = ''
}
},
/**
* 工具类目选择变化
*/
handleToolCategoryChange(value) {
if (value && value.length > 0) {
// 获取选中的最后一级类目名称
let currentNode = this.findNodeInToolTree(this.toolTreeData, value[value.length - 1])
this.currentToolCategoryName = currentNode ? currentNode.typeName : ''
} else {
this.currentToolCategoryName = ''
}
},
/**
* 在装备分类树中查找节点
*/
findNodeInTree(tree, nodeId) {
for (let node of tree) {
if (node.id === nodeId) {
return node
}
if (node.children && node.children.length > 0) {
let found = this.findNodeInTree(node.children, nodeId)
if (found) return found
}
}
return null
},
/**
* 在工具分类树中查找节点
*/
findNodeInToolTree(tree, nodeId) {
for (let node of tree) {
if (node.typeId === nodeId) {
return node
}
if (node.children && node.children.length > 0) {
let found = this.findNodeInToolTree(node.children, nodeId)
if (found) return found
}
}
return null
},
/**
* 添加申请查询核心处理devType和类目筛选逻辑
*/
handleAddQuery() {
this.addQuery.pageNum = 1 // 查询时重置页码为1
const queryParams = { ...this.addQuery }
// 1. 处理devType直接使用选择的分类值1=装备2=工具)
const devType = queryParams.devType || ''
// 2. 处理装备类目(仅当选择装备时生效)
let categoryEquipment = ''
if (devType === '1') {
// 如果选择了类目路径取最后一级ID作为查询条件
if (queryParams.categoryPath && Array.isArray(queryParams.categoryPath) && queryParams.categoryPath.length > 0) {
categoryEquipment = String(queryParams.categoryPath[queryParams.categoryPath.length - 1])
}
}
// 3. 处理工具类目(仅当选择工具时生效)
let toolTypeId = ''
if (devType === '2') {
// 如果选择了类目路径取最后一级ID作为查询条件
if (queryParams.toolCategoryPath && Array.isArray(queryParams.toolCategoryPath) && queryParams.toolCategoryPath.length > 0) {
toolTypeId = String(queryParams.toolCategoryPath[queryParams.toolCategoryPath.length - 1])
}
}
// 保存筛选条件包含devType和类目
this.filterParams = {
typeName: queryParams.typeName.trim(),
typeModelName: queryParams.typeModelName.trim(),
devCode: queryParams.devCode.trim(),
categoryEquipment, // 装备类目ID
toolTypeId, // 工具类目ID
devType, // 分类类型
manageType: queryParams.manageType // 管理模式(仅工具)
}
// 调用分页查询方法
this.getApplyList({
pageNum: this.addQuery.pageNum,
pageSize: this.addQuery.pageSize
})
},
/**
* 重置添加申请查询条件包含devType和类目
*/
resetAddQuery() {
this.addQuery = {
typeName: '',
typeModelName: '',
devCode: '',
devType: '', // 重置分类选择
manageType: '',
categoryPath: '', // 重置装备类目
toolCategoryPath: '', // 重置工具类目
pageNum: 1,
pageSize: 10
}
// 重置类目名称显示
this.currentCategoryName = ''
this.currentToolCategoryName = ''
// 同步重置筛选参数
this.filterParams = {
typeName: '',
typeModelName: '',
devCode: '',
categoryEquipment: '',
toolTypeId: '',
devType: '',
manageType: ''
}
// 重置后触发一次查询
this.getApplyList({ pageNum: 1, pageSize: this.addQuery.pageSize })
},
// 返回上一页
handleBack() {
this.$router.go(-1)
},
// 使用日期变化(批量设置表格中的使用日期)
useTimeChange(val) {
this.tableList.forEach(item => {
item.useTime = val
})
},
// 选择项变化表格勾选时触发保留devType
handleSelectionChange(selection) {
console.log(selection)
this.addTempList = []
this.ids = selection.map(item => item.id)
selection.forEach(item => {
this.addTempList.push({
id: item.id,
typeId: item.typeId,
devType: item.devType, // 关键保留分类类型1=装备2=工具)
category: item.category,
typeName: item.typeName,
typeModelName: item.typeModelName,
manageType: item.manageType,
devCode: item.devCode,
storageNum: item.storageNum,
num: item.manageType === '0' ? '1' : item.storageNum, // 编码设备默认1数量设备取输入值
useTime: this.queryParams.useTime ? new Date(this.queryParams.useTime) : null // 默认为主表单的使用日期
})
})
this.single = selection.length !== 1
this.multiple = !selection.length
},
// 表格选择框是否可勾选库存为0或已添加过的不可选
selectable(row) {
// 库存为0或null不可选
if (!row.storageNum || row.storageNum <= 0) {
return false
}
// 已在主列表中的不可选
return !this.tableList.some(item => item.id === row.id && item.typeId === row.typeId)
},
// 检查行是否被选中
isRowSelected(row) {
return this.ids.includes(row.id)
},
// 申请数量变化(校验:不能大于库存)
applyNumChange(row) {
if (row.num > row.storageNum) {
this.$message({
type: 'error',
message: '申请数量不能大于当前库存'
})
row.num = row.storageNum // 超过库存时,自动设为最大库存
} else if (row.num < 0) {
row.num = 0 // 防止输入负数
}
},
// 确认添加(将勾选的数据添加到主表格)
saveAdd() {
if (!this.ids.length) {
this.$message.error('请勾选要添加的数据')
return
}
const itemsToAdd = this.addList.filter(item => this.ids.includes(item.id))
const invalidItem = itemsToAdd.find(item => item.manageType === '1' && (item.num == 0 || !item.num))
if (invalidItem) {
this.$message.error('请为数量管理的设备填写申请数量。')
return
}
// 关键修改:新增设备时,初始化 useTimeRange 为 Date 对象数组
itemsToAdd.forEach(item => {
this.tableList.push({
...item,
// 逻辑:主表单有日期则用主表单日期,无则为空数组
useTimeRange: this.queryParams.useTime
? [new Date(this.queryParams.useTime), new Date(this.queryParams.useTime)]
: []
})
})
// 清除勾选状态
this.ids = []
if (this.$refs.addTable) {
this.$refs.addTable.clearSelection()
}
this.openAdd = false
},
// 提交申请(新增/编辑devType随数据传递
async submit() {
this.$refs.queryForm.validate(async(valid) => {
if (!valid) return
this.$confirm('是否确定提交申请?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async() => {
this.isLoading = true
try {
// --- 修改开始:健壮的日期格式化函数 ---
const safeFormatDate = (dateInput) => {
// 1. 检查输入是否为 null 或 undefined
if (!dateInput) {
console.warn('尝试格式化一个空的日期值')
return '' // 或根据业务返回 '1970-01-01' 等默认值
}
// 2. 确保输入是一个 Date 对象
let date
if (dateInput instanceof Date) {
date = dateInput
} else {
// 如果是字符串,尝试将其转换为 Date 对象
date = new Date(dateInput)
}
// 3. 检查 Date 对象是否有效
if (isNaN(date.getTime())) {
console.error('无效的日期值:', dateInput)
return '' // 或抛出错误
}
// 4. 执行格式化
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
return `${year}-${month}-${day}`
}
// --- 修改结束 ---
// 1. 处理主表单的日期范围
const devInfo = { ...this.queryParams }
if (devInfo.useTimeRange && devInfo.useTimeRange.length === 2) {
// 使用健壮的格式化函数
devInfo.useStartTime = safeFormatDate(devInfo.useTimeRange[0])
devInfo.useEndTime = safeFormatDate(devInfo.useTimeRange[1])
}
delete devInfo.useTimeRange
// 2. 处理表格数据的日期
const tempTableList = this.tableList.map(item => ({
...item,
category: null,
// 使用健壮的格式化函数
useStartTime: safeFormatDate(item.useTimeRange[0]),
useEndTime: safeFormatDate(item.useTimeRange[1]),
useTimeRange: undefined,
useTime: undefined
}))
const params = {
devInfo,
devDetailsList: tempTableList
}
// ... 后续提交逻辑 ...
let res
if (!this.routerParams.id) {
res = await addApplyApi(params)
} else {
res = await editApplyApi(params)
}
if (res.code === 200) {
this.$message.success(res.message || '操作成功!')
this.$router.go(-1)
} else {
this.$message.error(res.message || '操作失败!')
}
} catch (error) {
this.$message.error('提交申请异常,请稍后重试')
console.error('submit error:', error)
} finally {
this.isLoading = false
}
})
})
},
// 处理分类树数据(适配六级分类)
processTreeData(data) {
return Array.isArray(data) ? data : data ? [data] : []
},
// 递归处理装备分类节点限制六级补充level字段
processChildrenData(data, currentLevel = 1) {
if (currentLevel > 6) return []
return data.map(item => {
const nodeId = item.typeId ? Number(item.typeId) : item.id ? Number(item.id) : ''
const processedItem = {
id: nodeId,
name: item.typeName || item.name,
level: currentLevel,
parentId: item.parentId ? Number(item.parentId) : null,
...item
}
// 六级以下不再递归
if (item.children && item.children.length > 0 && currentLevel < 6) {
processedItem.children = this.processChildrenData(item.children, currentLevel + 1)
} else {
delete processedItem.children
}
return processedItem
})
},
// 获取装备分类树数据
async getEquipmentTree() {
try {
const res = await getEquipmentTreeAPI()
if (res.code === 200) {
const rawTreeData = this.processTreeData(res.data)
this.processedTreeData = this.processChildrenData(rawTreeData)
} else {
this.$message.error(res.msg || '获取装备分类失败')
}
} catch (error) {
this.$message.error('获取分类数据失败:' + (error.message || '未知错误'))
}
},
// 获取工具分类树数据适配返回字段限制最多6级
async getToolTree() {
try {
const res = await getTreeSelectApi()
if (res.code === 200) {
let rawData = res.data || []
this.toolTreeData = this.processToolTreeData(rawData)
} else {
this.$message.error(res.msg || '获取工具分类失败')
}
} catch (error) {
this.$message.error('获取工具分类数据失败:' + (error.message || '未知错误'))
}
},
// 递归处理工具分类节点(限制六级)
processToolTreeData(data, currentLevel = 1) {
if (currentLevel > 6) return []
return data.map(item => {
const processedItem = { ...item }
// 六级以下递归处理子节点
if (item.children && item.children.length > 0 && currentLevel < 6) {
processedItem.children = this.processToolTreeData(item.children, currentLevel + 1)
} else {
delete processedItem.children // 超过六级移除子节点
}
return processedItem
})
}
}
}
</script>
<style lang="scss" scoped>
/* 六级分类级联选择器样式 */
::v-deep .six-level-cascader .el-cascader-menu {
max-height: 300px;
overflow-y: auto;
}
::v-deep .six-level-cascader .el-cascader-menu__item {
position: relative;
transition: all 0.2s;
}
/* 各级分类缩进差异化 */
::v-deep .six-level-cascader .el-cascader-menu[data-level='1'] .el-cascader-menu__item {
padding-left: 20px;
font-weight: 500;
}
::v-deep .six-level-cascader .el-cascader-menu[data-level='2'] .el-cascader-menu__item {
padding-left: 35px;
font-weight: 400;
}
::v-deep .six-level-cascader .el-cascader-menu[data-level='3'] .el-cascader-menu__item {
padding-left: 50px;
font-size: 13px;
}
::v-deep .six-level-cascader .el-cascader-menu[data-level='4'] .el-cascader-menu__item {
padding-left: 65px;
font-size: 13px;
color: #666;
}
::v-deep .six-level-cascader .el-cascader-menu[data-level='5'] .el-cascader-menu__item {
padding-left: 80px;
font-size: 12px;
color: #888;
}
::v-deep .six-level-cascader .el-cascader-menu[data-level='6'] .el-cascader-menu__item {
padding-left: 95px;
font-size: 12px;
color: #999;
background-color: #f8f9fa;
}
/* 隐藏七级及以上分类 */
::v-deep .six-level-cascader .el-cascader-menu[data-level='7'] .el-cascader-menu__item {
display: none;
}
/* 滚动条样式优化 */
::v-deep .six-level-cascader .el-cascader-menu::-webkit-scrollbar {
width: 6px;
}
::v-deep .six-level-cascader .el-cascader-menu::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
::v-deep .six-level-cascader .el-cascader-menu::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
</style>