bonus-ui/src/views/EquipmentRetireApply/detail.vue

372 lines
12 KiB
Vue
Raw Normal View History

2025-11-16 23:55:09 +08:00
<template>
<div class="app-container">
2025-11-20 18:02:34 +08:00
<el-card style="margin-bottom: 20px">
2025-11-16 23:55:09 +08:00
<div slot="header" class="clearfix">
<span>{{ isNew ? '新增退役申请' : '退役申请明细' }}</span>
</div>
<!-- 基本信息 -->
2025-11-20 18:02:34 +08:00
<el-form ref="baseForm" :model="baseInfo" label-width="70px" inline style="height: 36px" >
<el-form-item label="申请单号" style="margin-bottom: 0; height: 36px">
<!-- 申请单号禁用的输入框 -->
<el-input
v-model="baseInfo.code"
placeholder="无"
disabled
:value="!isNew ? baseInfo.code : '新增'"
style="width: 240px;"
/>
</el-form-item>
<el-form-item label="任务状态">
<!-- 任务状态禁用的输入框 + 标签样式 -->
<el-input
:value="getStatusLabel()"
disabled
style="background: transparent; border: none; padding-left: 0; width: 240px;"
>
</el-input>
</el-form-item>
<el-form-item label="申请人">
<!-- 申请人禁用的输入框 -->
<el-input v-model="baseInfo.createUser" placeholder="无" disabled style="width: 240px;" />
</el-form-item>
<el-form-item label="申请时间">
<!-- 申请时间禁用的输入框 -->
<el-input v-model="baseInfo.createTime" placeholder="无" disabled style="width: 240px;" />
</el-form-item>
</el-form>
</el-card>
2025-11-16 23:55:09 +08:00
<!-- 装备和工具列表 -->
2025-11-20 18:02:34 +08:00
<el-card>
2025-11-16 23:55:09 +08:00
<div class="detail-section">
<div class="section-header">
2025-11-21 14:01:43 +08:00
<el-col :span="4">
<span style="font-size: 20px; font-weight: 800">申请列表</span>
</el-col>
<el-col :span="20" style="display: flex; justify-content: flex-end">
<el-button type="primary" size="small" :disabled="!canEdit" @click="onHandleAddItem">
2025-11-16 23:55:09 +08:00
添加装备/工具
</el-button>
2025-11-21 14:01:43 +08:00
<!-- 操作按钮 -->
<el-button type="primary" size="small" :disabled="!canEdit" @click="onHandleSubmit">确认申请</el-button>
</el-col>
2025-11-16 23:55:09 +08:00
</div>
<el-table :data="detailList" style="width: 100%" border stripe size="small" fit>
<el-table-column align="center" type="index" label="序号" width="70" />
<el-table-column align="center" prop="type" label="分类" width="90" />
<el-table-column align="center" prop="typeName" label="类目" width="180" />
<el-table-column align="center" prop="typeModelName" label="规格型号" width="180" />
<el-table-column align="center" prop="manageMode" label="管理模式" width="120" />
<el-table-column align="center" prop="devCode" label="设备编码" min-width="120" />
<el-table-column v-if="isNew" align="center" prop="inStockNum" label="在库数量" width="80" />
<el-table-column align="center" prop="scrapQuantity" label="申请报废数量" width="120" />
<el-table-column align="center" prop="retireReason" label="退役原因" width="180">
<template slot-scope="scope">
<el-input
v-model="scope.row.retireReason"
placeholder="请输入退役原因"
size="small"
maxlength="20"
show-word-limit
:disabled="!canEdit"
/>
</template>
</el-table-column>
<el-table-column align="center" label="报废附件" width="140">
<template slot-scope="scope">
<div style="display: flex;align-items: center;justify-content: center;">
<el-upload
ref="upload"
:limit="1"
:headers="upload.headers"
:action="upload.url"
:show-file-list="false"
accept=".png, .jpg, .jpeg, .pdf, .doc, .docx"
:on-success="(res) => handleFileSuccess(res, scope.row)"
:auto-upload="true"
:disabled="!canEdit"
>
<el-button type="primary" size="mini" :disabled="!canEdit">上传附件</el-button>
</el-upload>
<el-button v-if="scope.row.bmFileInfos && scope.row.bmFileInfos.length > 0" type="text" size="mini" @click="picturePreview(scope.row)">
查看
</el-button>
</div>
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="100">
<template slot-scope="scope">
<el-button type="danger" size="mini" :disabled="!canEdit" @click="onHandleDeleteItem(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
2025-11-21 14:01:43 +08:00
2025-11-16 23:55:09 +08:00
</el-card>
<!-- 添加装备/工具弹窗 -->
<add-item-dialog
ref="addItemDialog"
:existing-items="detailList"
@confirm="onAddItemConfirm"
/>
</div>
</template>
<script>
import { getRetireApplyDetailAPI, submitRetireApplyTaskAPI } from '@/api/EquipmentRetireApply/index.js'
import AddItemDialog from './components/AddItemDialog'
import { getToken } from '@/utils/auth'
export default {
components: {
AddItemDialog
},
data() {
return {
isNew: false,
baseInfo: {
id: '',
code: '',
reviewStatus: '1',
createUser: '',
createTime: ''
},
detailList: [],
fileData: {},
upload: {
headers: { Authorization: 'Bearer ' + getToken() },
url: process.env.VUE_APP_BASE_API + '/file/upload'
}
}
},
computed: {
// 判断是否可以编辑(新增状态或待审批状态下可以编辑)
canEdit() {
if (this.isNew) {
return true
}
const status = this.getStatusLabel()
return status === '待审批'
}
},
methods: {
async getDetail() {
const id = this.$route.params.id
if (id === 'new') {
this.isNew = true
this.baseInfo.createUser = this.$store.state.user?.nickName || '当前用户'
this.baseInfo.createTime = new Date().toLocaleString()
} else {
// 从query参数中获取任务基本信息
const taskInfoStr = this.$route.query.taskInfo
if (taskInfoStr) {
const taskInfo = JSON.parse(taskInfoStr)
this.baseInfo = {
id: taskInfo.id,
code: taskInfo.code,
reviewStatus: taskInfo.reviewStatus,
createUser: taskInfo.createUser,
createTime: taskInfo.createTime
}
}
// 调用API获取明细列表
const res = await getRetireApplyDetailAPI(id)
const data = res.data || []
// 所有数据都是明细项
this.detailList = data.map(item => ({
id: item.id,
keyId: item.keyId,
type: item.type,
typeId: item.typeId,
devType: item.devType,
groupName: item.groupName,
typeName: item.typeName,
typeModelName: item.typeModelName,
manageMode: item.manageMode,
devCode: item.devCode,
code: item.code,
inStockNum: item.inStockNum,
scrapQuantity: item.scrapNum,
retireReason: item.reasonVal,
bmFileInfos: item.bmFileInfos || [],
reviewStatus: item.reviewStatus // 审批状态
}))
}
},
onHandleAddItem() {
this.$refs.addItemDialog.open()
},
async onAddItemConfirm(items) {
// 确保新添加的项有bmFileInfos字段
const itemsWithFileInfo = items.map(item => ({
...item,
bmFileInfos: item.bmFileInfos || []
}))
this.detailList.push(...itemsWithFileInfo)
},
onHandleDeleteItem(row) {
this.$confirm('确定删除该项吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const index = this.detailList.indexOf(row)
if (index > -1) {
this.detailList.splice(index, 1)
}
this.$message.success('删除成功')
}).catch(() => {})
},
async onHandleSubmit() {
if (this.detailList.length === 0) {
this.$message.warning('请至少添加一项装备或工具')
return
}
try {
// 构建提交数据
const submitData = {
...this.baseInfo,
operationType: this.isNew ? 'add' : 'edit', // ✅ 区分新增或编辑
toBeScrapList: this.detailList.map(item => ({
keyId: item.keyId,
devCode: item.devCode,
type: item.type,
typeId: item.typeId,
devType: item.devType,
scrapNum: item.scrapQuantity,
reasonVal: item.retireReason,
bmFileInfos: item.bmFileInfos || []
}))
}
await submitRetireApplyTaskAPI(submitData)
this.$message.success('申请提交成功')
this.$router.push('/equipment/retire-apply/index')
} catch (error) {
this.$message.error('提交失败')
}
},
onHandleCancel() {
this.$router.back()
},
getStatusLabel() {
// 新增状态下显示待审批
if (this.isNew) {
return '待审批'
}
// 根据明细列表的审批状态计算任务状态
if (this.detailList.length === 0) {
return '待审批'
}
// 统计各状态的数量
const processedCount = this.detailList.filter(item => item.reviewStatus === '1' || item.reviewStatus === '2').length
const totalCount = this.detailList.length
if (processedCount === 0) {
// 一条都没处理
return '待审批'
} else if (processedCount === totalCount) {
// 全部处理完成
return '审批完成'
} else {
// 处理了部分
return '审批中'
}
},
getStatusType() {
// 根据任务状态返回标签类型
const label = this.getStatusLabel()
const typeMap = {
'待审批': 'warning',
'审批中': 'info',
'审批完成': 'success'
}
return typeMap[label] || 'info'
},
// 上传前保存行数据
beforeFileUpload(row) {
this.fileData = row
},
// 文件上传成功处理
handleFileSuccess(response, row) {
if (response.code === 200) {
// 初始化bmFileInfos数组
if (!row.bmFileInfos) {
row.bmFileInfos = []
}
// 添加上传的文件信息
const fileObj = {
name: response.data.name,
url: response.data.url
}
row.bmFileInfos = [fileObj]
this.$message.success('文件上传成功')
} else {
this.$message.error('文件上传失败')
}
},
// 图片查看
picturePreview(row) {
if (row.bmFileInfos && row.bmFileInfos.length > 0) {
const file = row.bmFileInfos[0]
const parts = file.name.split('.')
const extension = parts.pop()
if (extension === 'doc' || extension === 'docx' || extension === 'pdf') {
window.open(file.url, file.name)
} else {
this.$message.info('预览图片: ' + file.name)
}
}
}
},
created() {
this.getDetail()
}
}
</script>
<style lang="scss" scoped>
.box-card {
margin: 20px;
}
.detail-section {
margin: 30px 0;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
font-weight: 600;
font-size: 14px;
}
}
.action-buttons {
text-align: center;
margin-top: 30px;
}
</style>