|
|
<template>
|
|
|
<div class="table-page-container">
|
|
|
<div ref="lxHeader">
|
|
|
<lx-header icon="md-apps" text="维护规则" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
|
|
|
<slot>
|
|
|
<div style="display: flex;justify-content: flex-end;flex-wrap: wrap;">
|
|
|
<Button type="primary" @click="showAddRuleModal">新增规则</Button>
|
|
|
</div>
|
|
|
</slot>
|
|
|
</lx-header>
|
|
|
</div>
|
|
|
|
|
|
<div class="table-flex-content">
|
|
|
<xy-table
|
|
|
:list="list"
|
|
|
:total="total"
|
|
|
:table-item="table"
|
|
|
size="medium"
|
|
|
:height="tableHeight"
|
|
|
style="border-radius: 10px; overflow: hidden; box-shadow: 0 2px 12px 0 rgba(0,0,0,0.08); width: 100%;"
|
|
|
@pageSizeChange="pageSizeChange"
|
|
|
@pageIndexChange="pageChange"
|
|
|
>
|
|
|
<template v-slot:btns>
|
|
|
<el-table-column label="操作" width="240" header-align="center" class-name="table-col-action">
|
|
|
<template slot-scope="scope">
|
|
|
<div>
|
|
|
<Button type="primary" size="small" style="margin-left: 10px;" @click="handleEdit(scope.row)">编辑</Button>
|
|
|
<Poptip transfer confirm title="确认要删除吗?" @on-ok="handleDelete(scope.row)">
|
|
|
<Button type="error" style="margin-left: 10px;" size="small" ghost>删除</Button>
|
|
|
</Poptip>
|
|
|
<!-- <Button type="primary" size="small" ghost @click="">删除</Button> -->
|
|
|
<Button type="primary" size="small" style="margin-left: 10px;" ghost @click="handleAssociate(scope.row)">关联物资</Button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</template>
|
|
|
</xy-table>
|
|
|
</div>
|
|
|
|
|
|
<!-- 新增规则 Modal -->
|
|
|
<Modal v-model="showModal" title="新增维护规则" :footer="null" @on-cancel="handleCancel">
|
|
|
<Form ref="form" :model="form" :rules="rules" :label-width="120">
|
|
|
<FormItem label="规则名称" prop="name">
|
|
|
<Input v-model="form.name" placeholder="请输入规则名称" />
|
|
|
</FormItem>
|
|
|
<FormItem label="重复周期" prop="cycle">
|
|
|
<Select v-model="form.cycle">
|
|
|
<Option v-for="item in cycleOptions" :key="item.value" :value="item.value">{{ item.label }}</Option>
|
|
|
</Select>
|
|
|
</FormItem>
|
|
|
<FormItem label="起始日期设定" prop="startSetting">
|
|
|
<Select v-model="form.startSetting">
|
|
|
<Option v-for="item in startStandardOptions" :key="item.value" :value="item.value">{{ item.label }}</Option>
|
|
|
</Select>
|
|
|
</FormItem>
|
|
|
<!-- <FormItem label="生成计划时机" prop="timing">
|
|
|
<div class="timing-controls">
|
|
|
<Select v-model="form.timingUnit" style="width: 80px">
|
|
|
<Option value="days">提前</Option>
|
|
|
</Select>
|
|
|
<InputNumber v-model="form.timingValue" :min="1" style="width: 80px" />
|
|
|
<Select v-model="form.timingPeriod" style="width: 80px">
|
|
|
<Option value="days">天</Option>
|
|
|
</Select>
|
|
|
</div>
|
|
|
</FormItem> -->
|
|
|
<FormItem label="未完成时下次计划" prop="nextPlan">
|
|
|
<Select v-model="form.nextPlan">
|
|
|
<Option v-for="item in nextPlanOptions" :key="item.value" :value="item.value">{{ item.label }}</Option>
|
|
|
</Select>
|
|
|
</FormItem>
|
|
|
<FormItem label="备注" prop="notes">
|
|
|
<Input v-model="form.notes" type="textarea" :rows="3" placeholder="请输入备注" />
|
|
|
</FormItem>
|
|
|
</Form>
|
|
|
<div slot="footer" style="text-align: right;">
|
|
|
<Button @click="handleCancel">取消</Button>
|
|
|
<Button type="primary" style="margin-left: 8px;" @click="handleCustomSubmit">确定</Button>
|
|
|
</div>
|
|
|
</Modal>
|
|
|
|
|
|
<!-- 编辑规则 Modal -->
|
|
|
<Modal v-model="showEditModal" title="编辑维护规则" @on-ok="handleEditSubmit" @on-cancel="handleEditCancel">
|
|
|
<Form ref="editForm" :model="editForm" :rules="rules" :label-width="120">
|
|
|
<FormItem label="规则名称" prop="name">
|
|
|
<Input v-model="editForm.name" placeholder="请输入规则名称" />
|
|
|
</FormItem>
|
|
|
<FormItem label="重复周期" prop="cycle">
|
|
|
<Select v-model="editForm.cycle">
|
|
|
<Option v-for="item in cycleOptions" :key="item.value" :value="item.value">{{ item.label }}</Option>
|
|
|
</Select>
|
|
|
</FormItem>
|
|
|
<FormItem label="起始日期设定" prop="startSetting">
|
|
|
<Select v-model="editForm.startSetting">
|
|
|
<Option v-for="item in startStandardOptions" :key="item.value" :value="item.value">{{ item.label }}</Option>
|
|
|
</Select>
|
|
|
</FormItem>
|
|
|
<!-- <FormItem label="生成计划时机" prop="timing">
|
|
|
<div class="timing-controls">
|
|
|
<Select v-model="editForm.timingUnit" style="width: 80px">
|
|
|
<Option value="days">提前</Option>
|
|
|
</Select>
|
|
|
<InputNumber v-model="editForm.timingValue" :min="1" style="width: 80px" />
|
|
|
<Select v-model="editForm.timingPeriod" style="width: 80px">
|
|
|
<Option value="days">天</Option>
|
|
|
</Select>
|
|
|
</div>
|
|
|
</FormItem> -->
|
|
|
<FormItem label="未完成时下次计划" prop="nextPlan">
|
|
|
<Select v-model="editForm.nextPlan">
|
|
|
<Option v-for="item in nextPlanOptions" :key="item.value" :value="item.value">{{ item.label }}</Option>
|
|
|
</Select>
|
|
|
</FormItem>
|
|
|
<FormItem label="备注" prop="notes">
|
|
|
<Input v-model="editForm.notes" type="textarea" :rows="3" placeholder="请输入备注" />
|
|
|
</FormItem>
|
|
|
</Form>
|
|
|
</Modal>
|
|
|
|
|
|
<!-- 关联物资 Modal -->
|
|
|
<Modal v-model="showAssociateModal" title="关联物资" width="1000" @on-ok="handleAssociateSubmit" @on-cancel="handleAssociateCancel">
|
|
|
<div class="associate-content">
|
|
|
<div class="associate-toolbar">
|
|
|
<Input v-model="associateSearch" placeholder="搜索物资名称..." style="width: 250px; margin-right: 10px;" clearable />
|
|
|
<el-cascader
|
|
|
size="small"
|
|
|
v-model="associateFenlei"
|
|
|
:options="fenleiList"
|
|
|
:props="{label:'name',value:'id'}"
|
|
|
placeholder="选择分类"
|
|
|
style="width: 250px; margin-right: 10px;"
|
|
|
clearable
|
|
|
@change="changeAssociateFenlei"
|
|
|
/>
|
|
|
<!-- <Select v-model="select.storehouses_id" style="width: 120px; margin-right: 10px;" clearable placeholder="仓库类型" @on-change="getWarehouseNames">
|
|
|
<Option v-for="item in warehouseTypes" :key="item.id" :value="item.id">{{ item.name }}</Option>
|
|
|
</Select> -->
|
|
|
<!-- <Select v-model="select.area" style="width: 120px; margin-right: 10px;" clearable placeholder="所在区域" @on-change="getWarehouseNames">
|
|
|
<Option v-for="item in warehouseAreas" :key="item.id" :value="item.value">{{ item.value }}</Option>
|
|
|
</Select> -->
|
|
|
<!-- <Select v-model="associateWarehouseName" style="width: 120px; margin-right: 10px;" clearable placeholder="仓库名称">
|
|
|
<Option v-for="warehouse in warehouseNames" :key="warehouse.value" :value="warehouse.label">{{ warehouse.label }}</Option>
|
|
|
</Select> -->
|
|
|
<Button type="primary" @click="searchMaterialsPost">搜索</Button>
|
|
|
<Button style="margin-left: 8px;" @click="resetAssociateSearch">重置</Button>
|
|
|
</div>
|
|
|
<div class="batch-operations" style="margin-bottom: 15px;">
|
|
|
<Button type="primary" @click="batchAssociate" :disabled="!hasSelectedItems || isAssociating || isDisassociating" :loading="isAssociating">
|
|
|
{{ isAssociating ? '关联中...' : '批量关联' }}
|
|
|
</Button>
|
|
|
<Button type="error" style="margin-left: 8px;" @click="batchDisassociate" :disabled="!hasSelectedItems || isAssociating || isDisassociating" :loading="isDisassociating">
|
|
|
{{ isDisassociating ? '取消关联中...' : '批量取消关联' }}
|
|
|
</Button>
|
|
|
<span style="margin-left: 15px; color: #666;">已选择 {{ selectedItems.length }} 项</span>
|
|
|
</div>
|
|
|
<Table :columns="associateColumns" :data="associateList" :height="400" style="margin-top: 15px;" @on-selection-change="handleSelectionChange">
|
|
|
<template slot="action" slot-scope="{ row }">
|
|
|
<div style="display: flex; gap: 8px; justify-content: center;">
|
|
|
<!--
|
|
|
<Button
|
|
|
v-else-if="row.equipment_maintain_config"
|
|
|
type="warning"
|
|
|
size="small"
|
|
|
ghost
|
|
|
style="border-radius: 6px;"
|
|
|
:title="row.equipment_maintain_config ? `已关联规则: ${row.equipment_maintain_config.name}` : ''"
|
|
|
@click="toggleAssociation(row)"
|
|
|
>
|
|
|
重新绑定
|
|
|
</Button> -->
|
|
|
<Button
|
|
|
v-if="isMaterialAssociated(row)"
|
|
|
type="error"
|
|
|
size="small"
|
|
|
ghost
|
|
|
style="border-radius: 6px;"
|
|
|
@click="toggleAssociation(row)"
|
|
|
>
|
|
|
解除绑定
|
|
|
</Button>
|
|
|
<Button
|
|
|
v-else
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
ghost
|
|
|
style="border-radius: 6px;"
|
|
|
@click="toggleAssociation(row)"
|
|
|
>
|
|
|
绑定
|
|
|
</Button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</Table>
|
|
|
<div class="pagination-container">
|
|
|
<el-pagination
|
|
|
:current-page="associateCurrentPage"
|
|
|
:page-sizes="[10, 20, 30, 50, 100]"
|
|
|
:page-size="associatePageSize"
|
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
|
:total="associateTotal"
|
|
|
@size-change="handleAssociatePageSizeChange"
|
|
|
@current-change="handleAssociatePageChange"
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
</Modal>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { Button, Modal, Form, FormItem, Input, Select, Option, InputNumber, Table } from 'view-design'
|
|
|
import { getStorehouseTypeList } from '@/api/system/storehouseType'
|
|
|
import { getparameteritem } from '@/api/system/dictionary.js'
|
|
|
import { index } from '@/api/system/baseForm.js'
|
|
|
import { saveMaintainConfig, getMaintainConfigList, deleteMaintainConfig } from '@/api/maintenance/maintenance.js'
|
|
|
import { saveStocksItem } from '@/api/stocks-item.js'
|
|
|
import request from '@/utils/request'
|
|
|
import qs from 'qs'
|
|
|
import { index as getFenleilist } from '@/api/fenlei.js'
|
|
|
|
|
|
export default {
|
|
|
components: {
|
|
|
Button,
|
|
|
Modal,
|
|
|
Form,
|
|
|
FormItem,
|
|
|
Input,
|
|
|
Select,
|
|
|
Option,
|
|
|
InputNumber,
|
|
|
Table
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
select: {
|
|
|
page: 1,
|
|
|
page_size: 999,
|
|
|
keyword: '',
|
|
|
table_name: 'materialstorages',
|
|
|
area: '',
|
|
|
storehouses_id: ''
|
|
|
},
|
|
|
total: 0,
|
|
|
list: [],
|
|
|
cycleOptions: [
|
|
|
{ value: '0.5', label: '每半月' },
|
|
|
{ value: '1.0', label: '每月' },
|
|
|
{ value: '3.0', label: '每季度' },
|
|
|
{ value: '6.0', label: '每半年' },
|
|
|
{ value: '12.0', label: '每年' }
|
|
|
],
|
|
|
startStandardOptions: [
|
|
|
{ value: '1', label: '从每年第一天开始运算' },
|
|
|
{ value: '2', label: '首次关联物资时' }
|
|
|
],
|
|
|
nextPlanOptions: [
|
|
|
{ value: '1', label: '暂停生成(直到上次计划已经执行完成)' },
|
|
|
{ value: '2', label: '强制生成(忽略未完成状态)' }
|
|
|
],
|
|
|
table: [
|
|
|
{ label: '序号', type: 'index', width: 60 },
|
|
|
{ label: '规则名称', prop: 'name', minWidth: 160 },
|
|
|
{ label: '重复周期', prop: 'month_frequency', minWidth: 120, formatter: row => this.cycleOptions.find(opt => opt.value == row.month_frequency)?.label || row.month_frequency },
|
|
|
{ label: '起始日期设定', prop: 'start_standard', minWidth: 160, formatter: row => this.startStandardOptions.find(opt => opt.value == row.start_standard)?.label || row.start_standard },
|
|
|
// { label: '生成计划时机(天)', prop: 'advance_days', minWidth: 120 },
|
|
|
// { label: '生成计划时机(天)', prop: 'advance_days', minWidth: 120 },
|
|
|
{
|
|
|
label: '已用于物资数',
|
|
|
prop: 'equipment_maintain_config_material_infos',
|
|
|
minWidth: 120,
|
|
|
formatter: row => row.equipment_maintain_config_material_infos ? row.equipment_maintain_config_material_infos.length : 0
|
|
|
},
|
|
|
{ label: '未完成时下次计划', prop: 'next_plan_type', minWidth: 160, formatter: row => this.nextPlanOptions.find(opt => opt.value == row.next_plan_type)?.label || row.next_plan_type }
|
|
|
],
|
|
|
tableHeight: 550,
|
|
|
showModal: false,
|
|
|
showEditModal: false,
|
|
|
showAssociateModal: false,
|
|
|
form: {
|
|
|
name: '',
|
|
|
cycle: '',
|
|
|
startSetting: '',
|
|
|
timingUnit: 'days',
|
|
|
timingValue: 7,
|
|
|
timingPeriod: 'days',
|
|
|
nextPlan: '',
|
|
|
notes: ''
|
|
|
},
|
|
|
editForm: {
|
|
|
name: '',
|
|
|
cycle: '',
|
|
|
startSetting: '',
|
|
|
timingUnit: 'days',
|
|
|
timingValue: 7,
|
|
|
timingPeriod: 'days',
|
|
|
nextPlan: '',
|
|
|
notes: ''
|
|
|
},
|
|
|
rules: {
|
|
|
name: [{ required: true, message: '请输入规则名称', trigger: 'blur' }],
|
|
|
cycle: [{ required: true, message: '请选择重复周期', trigger: 'change' }],
|
|
|
startSetting: [{ required: true, message: '请选择起始日期设定', trigger: 'change' }],
|
|
|
nextPlan: [{ required: true, message: '请选择未完成时下次计划', trigger: 'change' }]
|
|
|
},
|
|
|
associateSearch: '',
|
|
|
associateWarehouseName: '',
|
|
|
associatePageSize: 30,
|
|
|
associateCurrentPage: 1,
|
|
|
associateTotal: 0,
|
|
|
associateFenlei: '',
|
|
|
fenleiList: [],
|
|
|
associateColumns: [
|
|
|
{
|
|
|
type: 'selection',
|
|
|
width: 60,
|
|
|
align: 'center'
|
|
|
},
|
|
|
{
|
|
|
title: '已关联规则',
|
|
|
key: 'equipment_maintain_config_material_infos',
|
|
|
minWidth: 180,
|
|
|
render: (h, params) => {
|
|
|
const relations = params.row.equipment_maintain_config_material_infos
|
|
|
if (!relations || relations.length === 0) {
|
|
|
return h('span', '-')
|
|
|
}
|
|
|
|
|
|
// 如果有多个规则,每行显示一个
|
|
|
if (relations.length === 1) {
|
|
|
const rule = relations[0]
|
|
|
return h('span', rule.equipment_maintain_config && rule.equipment_maintain_config.name ? rule.equipment_maintain_config.name : '-')
|
|
|
} else {
|
|
|
// 多个规则,每行显示一个
|
|
|
const ruleElements = relations.map(rule => {
|
|
|
const ruleName = rule.equipment_maintain_config && rule.equipment_maintain_config.name ? rule.equipment_maintain_config.name : '-'
|
|
|
return h('div', { style: 'line-height: 1.5; margin-bottom: 2px;' }, ruleName)
|
|
|
})
|
|
|
return h('div', ruleElements)
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
title: '物资名称',
|
|
|
key: 'zichanmingcheng',
|
|
|
minWidth: 180
|
|
|
},
|
|
|
{
|
|
|
title: '所属种类',
|
|
|
key: 'fenlei_detail',
|
|
|
minWidth: 180,
|
|
|
render: (h, params) => {
|
|
|
const relation = params.row.fenlei_detail
|
|
|
return h('span', relation && relation.name ? relation.name : '-')
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
title: '物资类型',
|
|
|
key: 'wuzileixing',
|
|
|
minWidth: 120
|
|
|
},
|
|
|
{
|
|
|
title: '物资型号',
|
|
|
key: 'guigexinghao',
|
|
|
minWidth: 120
|
|
|
},
|
|
|
{
|
|
|
title: '物资规格',
|
|
|
key: 'wuziguige',
|
|
|
minWidth: 120
|
|
|
},
|
|
|
{
|
|
|
title: '单位',
|
|
|
key: 'jiliangdanwei',
|
|
|
minWidth: 80
|
|
|
},
|
|
|
{
|
|
|
title: '储备年限',
|
|
|
key: 'chubeinianxian',
|
|
|
minWidth: 80
|
|
|
},
|
|
|
{
|
|
|
title: '存放要求',
|
|
|
key: 'cunfangyaoqiu',
|
|
|
minWidth: 120
|
|
|
},
|
|
|
{
|
|
|
title: '维护要求',
|
|
|
key: 'weihuyaoqiu',
|
|
|
minWidth: 120
|
|
|
},
|
|
|
{
|
|
|
title: '保养频次',
|
|
|
key: 'equipment_maintain_config_id_equipment_maintain_configs_id_relation',
|
|
|
minWidth: 120,
|
|
|
render: (h, params) => {
|
|
|
const relation = params.row.equipment_maintain_config_id_equipment_maintain_configs_id_relation
|
|
|
return h('span', relation && relation.name ? relation.name : '-')
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
title: '备注',
|
|
|
key: 'beizhu',
|
|
|
minWidth: 240
|
|
|
},
|
|
|
{
|
|
|
title: '操作',
|
|
|
slot: 'action',
|
|
|
width: 200,
|
|
|
fixed: 'right',
|
|
|
align: 'center',
|
|
|
headerAlign: 'center',
|
|
|
className: 'table-col-action'
|
|
|
}
|
|
|
],
|
|
|
associateList: [],
|
|
|
currentRule: null,
|
|
|
ruleAssociations: new Map(),
|
|
|
warehouseTypes: [],
|
|
|
warehouseAreas: [],
|
|
|
warehouseNames: [],
|
|
|
allWarehouses: [],
|
|
|
currentWarehouseNames: [],
|
|
|
selectedItems: [],
|
|
|
hasSelectedItems: false,
|
|
|
isSelecting: false,
|
|
|
isAssociating: false,
|
|
|
isDisassociating: false,
|
|
|
selectionTimer: null
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
associateWarehouseArea(val) {
|
|
|
if (val) {
|
|
|
this.getWarehouseNames(val)
|
|
|
} else {
|
|
|
this.warehouseNames = []
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
this.getList()
|
|
|
this.getWarehouseTypes()
|
|
|
this.getWarehouseAreas()
|
|
|
this.getWarehouseNames()
|
|
|
},
|
|
|
mounted() {
|
|
|
this.calcTableHeight()
|
|
|
window.addEventListener('resize', this.calcTableHeight)
|
|
|
},
|
|
|
beforeDestroy() {
|
|
|
window.removeEventListener('resize', this.calcTableHeight)
|
|
|
// 清理选择定时器
|
|
|
if (this.selectionTimer) {
|
|
|
clearTimeout(this.selectionTimer)
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
async getList() {
|
|
|
try {
|
|
|
const res = await getMaintainConfigList({
|
|
|
page: this.select.page,
|
|
|
page_size: this.select.page_size
|
|
|
// 可加其它筛选参数
|
|
|
})
|
|
|
if (res && res.data) {
|
|
|
this.list = res.data
|
|
|
this.total = res.total
|
|
|
}
|
|
|
} catch (e) {
|
|
|
this.$message.error('获取运维规则列表失败')
|
|
|
}
|
|
|
},
|
|
|
pageChange(e) {
|
|
|
this.select.page = e
|
|
|
this.getList()
|
|
|
},
|
|
|
pageSizeChange(e) {
|
|
|
this.select.page_size = e
|
|
|
this.getList()
|
|
|
},
|
|
|
calcTableHeight() {
|
|
|
const header = this.$refs.lxHeader ? this.$refs.lxHeader.offsetHeight : 0
|
|
|
const windowHeight = window.innerHeight
|
|
|
const minTableHeight = 600
|
|
|
this.tableHeight = Math.max(windowHeight - header - 100, minTableHeight)
|
|
|
},
|
|
|
showAddRuleModal() {
|
|
|
this.form = {
|
|
|
name: '',
|
|
|
cycle: '',
|
|
|
startSetting: '',
|
|
|
timingUnit: 'days',
|
|
|
timingValue: 7,
|
|
|
timingPeriod: 'days',
|
|
|
nextPlan: '',
|
|
|
notes: ''
|
|
|
}
|
|
|
this.showModal = true
|
|
|
this.$nextTick(() => {
|
|
|
if (this.$refs.form) {
|
|
|
this.$refs.form.resetFields()
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
handleCancel() {
|
|
|
this.showModal = false
|
|
|
this.$refs.form.resetFields()
|
|
|
},
|
|
|
handleEdit(row) {
|
|
|
this.currentRule = row
|
|
|
this.editForm = {
|
|
|
name: row.name,
|
|
|
cycle: String(row.month_frequency),
|
|
|
startSetting: String(row.start_standard),
|
|
|
timingUnit: 'days',
|
|
|
timingValue: row.advance_days,
|
|
|
timingPeriod: 'days',
|
|
|
nextPlan: String(row.next_plan_type),
|
|
|
notes: row.remark || ''
|
|
|
}
|
|
|
this.showEditModal = true
|
|
|
},
|
|
|
handleEditSubmit() {
|
|
|
this.$refs.editForm.validate(async(valid) => {
|
|
|
if (valid) {
|
|
|
const data = {
|
|
|
id: this.currentRule.id,
|
|
|
name: this.editForm.name,
|
|
|
month_frequency: this.editForm.cycle,
|
|
|
start_standard: this.editForm.startSetting,
|
|
|
advance_days: this.editForm.timingValue,
|
|
|
next_plan_type: this.editForm.nextPlan,
|
|
|
remark: this.editForm.notes
|
|
|
}
|
|
|
try {
|
|
|
await saveMaintainConfig(data)
|
|
|
this.$message.success('编辑成功')
|
|
|
this.showEditModal = false
|
|
|
this.getList()
|
|
|
} catch (e) {
|
|
|
this.$message.error('编辑失败')
|
|
|
}
|
|
|
} else {
|
|
|
this.$message.error('请填写所有必填项')
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
handleEditCancel() {
|
|
|
this.showEditModal = false
|
|
|
this.$refs.editForm.resetFields()
|
|
|
},
|
|
|
handleDelete(row) {
|
|
|
this.currentRule = row
|
|
|
this.$confirm('确认要删除该维护规则吗?', '提示', {
|
|
|
confirmButtonText: '确定',
|
|
|
cancelButtonText: '取消',
|
|
|
type: 'warning'
|
|
|
}).then(async() => {
|
|
|
try {
|
|
|
await deleteMaintainConfig({ id: this.currentRule.id })
|
|
|
this.$message.success('删除成功')
|
|
|
this.getList()
|
|
|
} catch (e) {
|
|
|
this.$message.error('删除失败')
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
handleAssociate(row) {
|
|
|
this.currentRule = row
|
|
|
// 重置弹窗相关数据
|
|
|
this.associateSearch = ''
|
|
|
this.associateFenlei = ''
|
|
|
this.select.storehouses_id = ''
|
|
|
this.select.area = ''
|
|
|
this.associateWarehouseName = ''
|
|
|
this.associateCurrentPage = 1
|
|
|
// 重置选择状态
|
|
|
this.selectedItems = []
|
|
|
this.hasSelectedItems = false
|
|
|
// 重置操作状态
|
|
|
this.isAssociating = false
|
|
|
this.isDisassociating = false
|
|
|
// 先关闭再打开,确保弹窗能弹出
|
|
|
this.showAssociateModal = false
|
|
|
this.$nextTick(() => {
|
|
|
this.showAssociateModal = true
|
|
|
this.loadAssociations()
|
|
|
this.getFenlei()
|
|
|
// 重置分页到第一页
|
|
|
this.associateCurrentPage = 1
|
|
|
// 重置物资列表
|
|
|
this.associateList = []
|
|
|
this.associateTotal = 0
|
|
|
// 重新获取物资列表
|
|
|
this.searchMaterialsPost()
|
|
|
})
|
|
|
},
|
|
|
loadAssociations() {
|
|
|
// Load saved associations from localStorage
|
|
|
const saved = localStorage.getItem('ruleAssociations')
|
|
|
if (saved) {
|
|
|
const parsed = JSON.parse(saved)
|
|
|
Object.entries(parsed).forEach(([ruleId, materials]) => {
|
|
|
this.ruleAssociations.set(ruleId, new Set(materials))
|
|
|
})
|
|
|
}
|
|
|
},
|
|
|
async getFenlei() {
|
|
|
try {
|
|
|
const res = await getFenleilist({
|
|
|
tree: 1,
|
|
|
sort_type: 'ASC',
|
|
|
sort_name: 'sort'
|
|
|
})
|
|
|
this.fenleiList = this.removeEmptyChildren(res)
|
|
|
} catch (e) {
|
|
|
console.error('获取分类列表失败:', e)
|
|
|
this.$message.error('获取分类列表失败')
|
|
|
}
|
|
|
},
|
|
|
changeAssociateFenlei(e) {
|
|
|
if (e) {
|
|
|
this.associateFenlei = e[e.length - 1]
|
|
|
} else {
|
|
|
this.associateFenlei = ''
|
|
|
}
|
|
|
},
|
|
|
// 移除children=[]
|
|
|
removeEmptyChildren(node) {
|
|
|
if (Array.isArray(node)) {
|
|
|
return node.map(child => {
|
|
|
if (child.children) {
|
|
|
// 递归处理子节点
|
|
|
child.children = this.removeEmptyChildren(child.children);
|
|
|
// 若处理后 children 为空,删除该属性
|
|
|
if (child.children.length === 0) {
|
|
|
delete child.children;
|
|
|
}
|
|
|
}
|
|
|
return child;
|
|
|
});
|
|
|
}
|
|
|
return [];
|
|
|
},
|
|
|
// 判断物资是否已关联到当前规则
|
|
|
isMaterialAssociated(material) {
|
|
|
if (!this.currentRule || !this.currentRule.equipment_maintain_config_material_infos) {
|
|
|
return false
|
|
|
}
|
|
|
return this.currentRule.equipment_maintain_config_material_infos.some(
|
|
|
item => item.material_info_id === material.id
|
|
|
)
|
|
|
},
|
|
|
saveAssociations() {
|
|
|
const serialized = {}
|
|
|
this.ruleAssociations.forEach((materials, ruleId) => {
|
|
|
serialized[ruleId] = Array.from(materials)
|
|
|
})
|
|
|
localStorage.setItem('ruleAssociations', JSON.stringify(serialized))
|
|
|
},
|
|
|
async searchMaterialsPost() {
|
|
|
try {
|
|
|
const data = {
|
|
|
page_size: this.associatePageSize,
|
|
|
page: this.associateCurrentPage,
|
|
|
'show_relation[0]': 'equipmentMaintainConfig',
|
|
|
'show_relation[1]': 'materialInfo.materialstorage',
|
|
|
|
|
|
'materialstorages_cangkumingcheng': this.associateWarehouseName ? this.associateWarehouseName : '',
|
|
|
'materialstorages_suozaiquyu': this.select.area ? this.select.area : '',
|
|
|
'storehouses_id': this.select.storehouses_id ? this.select.storehouses_id : '',
|
|
|
|
|
|
'filter[0][key]': 'zichanmingcheng',
|
|
|
'filter[0][op]': 'like',
|
|
|
'filter[0][value]': this.associateSearch ? this.associateSearch : '',
|
|
|
// 'filter[1][key]': 'wuzileixing',
|
|
|
// 'filter[1][op]': 'eq',
|
|
|
// 'filter[1][value]': '一物一码'
|
|
|
}
|
|
|
|
|
|
// 如果选择了分类,添加分类筛选
|
|
|
if (this.associateFenlei) {
|
|
|
data['filter[1][key]'] = 'fenlei'
|
|
|
data['filter[1][op]'] = 'eq'
|
|
|
data['filter[1][value]'] = this.associateFenlei
|
|
|
}
|
|
|
|
|
|
const res = await request({
|
|
|
url: '/api/admin/material-infos/index',
|
|
|
method: 'post',
|
|
|
data: qs.stringify(data),
|
|
|
headers: {
|
|
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
|
}
|
|
|
})
|
|
|
if (res && res.data) {
|
|
|
this.associateList = res.data.map(material => ({
|
|
|
...material,
|
|
|
selected: this.ruleAssociations.get(this.currentRule.id)?.has(material.id) || false
|
|
|
}))
|
|
|
this.associateTotal = res.total
|
|
|
// 重置选择状态
|
|
|
this.selectedItems = []
|
|
|
this.hasSelectedItems = false
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('获取物资种类列表失败:', e)
|
|
|
this.$message.error('获取物资种类失败')
|
|
|
}
|
|
|
},
|
|
|
async toggleAssociation(row) {
|
|
|
if (!this.currentRule) return
|
|
|
let equipment_maintain_config_material_infos = this.currentRule.equipment_maintain_config_material_infos
|
|
|
console.log("this.currentRule",this.currentRule,row)
|
|
|
const targetIndex = this.currentRule.equipment_maintain_config_material_infos.findIndex(
|
|
|
item => item.material_info_id === row.id
|
|
|
);
|
|
|
|
|
|
// 3. 若找到对应项(索引不为 -1),则删除该项
|
|
|
console.log("targetIndex",targetIndex)
|
|
|
if (targetIndex !== -1) {
|
|
|
equipment_maintain_config_material_infos.splice(targetIndex, 1); // splice(索引, 删除数量)
|
|
|
}else{
|
|
|
equipment_maintain_config_material_infos.push({
|
|
|
material_info_id:row.id,
|
|
|
equipment_maintain_config_time:''
|
|
|
})
|
|
|
}
|
|
|
console.log("equipment_maintain_config_material_infos",equipment_maintain_config_material_infos)
|
|
|
// return
|
|
|
await saveMaintainConfig({
|
|
|
id:this.currentRule.id,
|
|
|
equipment_maintain_config_material_infos:equipment_maintain_config_material_infos
|
|
|
})
|
|
|
this.$message.success('操作成功')
|
|
|
this.getList()
|
|
|
this.searchMaterialsPost()
|
|
|
|
|
|
return
|
|
|
if (row.equipment_maintain_config?.id === this.currentRule.id) {
|
|
|
// 解除绑定
|
|
|
try {
|
|
|
await saveStocksItem({
|
|
|
id: row.id,
|
|
|
equipment_maintain_config_id: null
|
|
|
})
|
|
|
this.$message.success('已解除绑定物资')
|
|
|
this.searchMaterialsPost()
|
|
|
} catch (e) {
|
|
|
this.$message.error('解除绑定失败')
|
|
|
}
|
|
|
} else {
|
|
|
// 绑定
|
|
|
try {
|
|
|
// await saveStocksItem({
|
|
|
// id: row.id,
|
|
|
// equipment_maintain_config_id: this.currentRule.id
|
|
|
// })
|
|
|
let equipment_maintain_config_material_infos = []
|
|
|
if(this.currentRule.material_info.length>0){
|
|
|
|
|
|
}else{
|
|
|
equipment_maintain_config_material_infos.push({
|
|
|
material_info_id:row.id,
|
|
|
equipment_maintain_config_time:''
|
|
|
})
|
|
|
}
|
|
|
await saveMaintainConfig({
|
|
|
id:this.currentRule.id,
|
|
|
|
|
|
})
|
|
|
this.$message.success('已成功绑定物资')
|
|
|
this.searchMaterialsPost()
|
|
|
} catch (e) {
|
|
|
this.$message.error('绑定失败:' + e.message)
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
updateMaterialCount() {
|
|
|
const count = this.ruleAssociations.get(this.currentRule.id)?.size || 0
|
|
|
const index = this.list.findIndex(item => item.id === this.currentRule.id)
|
|
|
if (index !== -1) {
|
|
|
this.$set(this.list[index], 'materialCount', count)
|
|
|
}
|
|
|
},
|
|
|
handleAssociatePageChange(page) {
|
|
|
this.associateCurrentPage = page
|
|
|
this.searchMaterialsPost()
|
|
|
},
|
|
|
handleAssociateSubmit() {
|
|
|
this.showAssociateModal = false
|
|
|
// 弹窗关闭时重置列表状态
|
|
|
this.associateList = []
|
|
|
this.associateTotal = 0
|
|
|
this.associateCurrentPage = 1
|
|
|
this.selectedItems = []
|
|
|
this.hasSelectedItems = false
|
|
|
this.getList()
|
|
|
},
|
|
|
handleAssociateCancel() {
|
|
|
this.showAssociateModal = false
|
|
|
// 弹窗关闭时重置列表状态
|
|
|
this.associateList = []
|
|
|
this.associateTotal = 0
|
|
|
this.associateCurrentPage = 1
|
|
|
this.selectedItems = []
|
|
|
this.hasSelectedItems = false
|
|
|
},
|
|
|
handleSelectionChange(selection) {
|
|
|
// 防抖处理,避免频繁更新导致的卡顿
|
|
|
if (this.selectionTimer) {
|
|
|
clearTimeout(this.selectionTimer)
|
|
|
}
|
|
|
|
|
|
this.selectionTimer = setTimeout(() => {
|
|
|
this.selectedItems = selection
|
|
|
this.hasSelectedItems = selection.length > 0
|
|
|
}, 100)
|
|
|
},
|
|
|
async batchAssociate() {
|
|
|
if (this.selectedItems.length === 0) {
|
|
|
this.$message.warning('请先选择需要关联的物资')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
this.isAssociating = true
|
|
|
try {
|
|
|
let equipment_maintain_config_material_infos = [...(this.currentRule.equipment_maintain_config_material_infos || [])]
|
|
|
|
|
|
// 批量添加选中的物资
|
|
|
this.selectedItems.forEach(item => {
|
|
|
const existingIndex = equipment_maintain_config_material_infos.findIndex(
|
|
|
existing => existing.material_info_id === item.id
|
|
|
)
|
|
|
if (existingIndex === -1) {
|
|
|
equipment_maintain_config_material_infos.push({
|
|
|
material_info_id: item.id,
|
|
|
equipment_maintain_config_time: ''
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
|
|
|
await saveMaintainConfig({
|
|
|
id: this.currentRule.id,
|
|
|
equipment_maintain_config_material_infos: equipment_maintain_config_material_infos
|
|
|
})
|
|
|
|
|
|
this.$message.success(`批量关联成功,共关联 ${this.selectedItems.length} 项物资`)
|
|
|
this.selectedItems = []
|
|
|
this.hasSelectedItems = false
|
|
|
this.getList()
|
|
|
this.searchMaterialsPost()
|
|
|
} catch (e) {
|
|
|
this.$message.error('批量关联失败')
|
|
|
} finally {
|
|
|
this.isAssociating = false
|
|
|
}
|
|
|
},
|
|
|
async batchDisassociate() {
|
|
|
if (this.selectedItems.length === 0) {
|
|
|
this.$message.warning('请先选择需要取消关联的物资')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
this.isDisassociating = true
|
|
|
try {
|
|
|
let equipment_maintain_config_material_infos = [...(this.currentRule.equipment_maintain_config_material_infos || [])]
|
|
|
|
|
|
// 批量移除选中的物资
|
|
|
this.selectedItems.forEach(item => {
|
|
|
const existingIndex = equipment_maintain_config_material_infos.findIndex(
|
|
|
existing => existing.material_info_id === item.id
|
|
|
)
|
|
|
if (existingIndex !== -1) {
|
|
|
equipment_maintain_config_material_infos.splice(existingIndex, 1)
|
|
|
}
|
|
|
})
|
|
|
|
|
|
await saveMaintainConfig({
|
|
|
id: this.currentRule.id,
|
|
|
equipment_maintain_config_material_infos: equipment_maintain_config_material_infos
|
|
|
})
|
|
|
|
|
|
this.$message.success(`批量取消关联成功,共取消关联 ${this.selectedItems.length} 项物资`)
|
|
|
this.selectedItems = []
|
|
|
this.hasSelectedItems = false
|
|
|
this.getList()
|
|
|
this.searchMaterialsPost()
|
|
|
} catch (e) {
|
|
|
this.$message.error('批量取消关联失败')
|
|
|
} finally {
|
|
|
this.isDisassociating = false
|
|
|
}
|
|
|
},
|
|
|
handleAssociatePageSizeChange(size) {
|
|
|
this.associatePageSize = size
|
|
|
this.associateCurrentPage = 1
|
|
|
this.searchMaterialsPost()
|
|
|
},
|
|
|
resetAssociateSearch() {
|
|
|
this.associateSearch = ''
|
|
|
this.associateFenlei = ''
|
|
|
this.select.storehouses_id = ''
|
|
|
this.select.area = ''
|
|
|
this.associateWarehouseName = ''
|
|
|
this.associateCurrentPage = 1
|
|
|
this.searchMaterialsPost()
|
|
|
},
|
|
|
async getWarehouseTypes() {
|
|
|
try {
|
|
|
const res = await getStorehouseTypeList({
|
|
|
page: 1,
|
|
|
page_size: 999
|
|
|
})
|
|
|
if (res && res.data) {
|
|
|
this.warehouseTypes = res.data
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('获取仓库类型列表失败:', e)
|
|
|
this.$message.error('获取仓库类型列表失败')
|
|
|
}
|
|
|
},
|
|
|
|
|
|
async getWarehouseAreas() {
|
|
|
try {
|
|
|
const res = await getparameteritem('area')
|
|
|
if (res && res.detail) {
|
|
|
this.warehouseAreas = res.detail
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('获取仓库区域列表失败:', e)
|
|
|
this.$message.error('获取仓库区域列表失败')
|
|
|
}
|
|
|
},
|
|
|
|
|
|
async getWarehouseNames() {
|
|
|
try {
|
|
|
const res = await index({
|
|
|
page_size: this.select.page_size,
|
|
|
page: this.select.page,
|
|
|
table_name: this.select.table_name,
|
|
|
filter: [{
|
|
|
key: 'cangkumingcheng',
|
|
|
op: 'like',
|
|
|
value: this.select.keyword ? this.select.keyword : ''
|
|
|
}, {
|
|
|
key: 'quyu_id',
|
|
|
op: 'eq',
|
|
|
value: this.select.area ? this.select.area : ''
|
|
|
}, {
|
|
|
key: 'storehouses_id',
|
|
|
op: 'eq',
|
|
|
value: this.select.storehouses_id ? this.select.storehouses_id : ''
|
|
|
}]
|
|
|
})
|
|
|
if (res && res.data) {
|
|
|
this.warehouseNames = res.data.map(warehouse => ({
|
|
|
value: warehouse.id,
|
|
|
label: warehouse.cangkumingcheng
|
|
|
}))
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('获取仓库名称列表失败:', e)
|
|
|
this.$message.error('获取仓库名称列表失败')
|
|
|
}
|
|
|
},
|
|
|
|
|
|
clearArea(e) {
|
|
|
this.select.area = e || ''
|
|
|
this.filterWarehouses()
|
|
|
},
|
|
|
|
|
|
clearType(e) {
|
|
|
this.select.storehouses_id = e || ''
|
|
|
this.filterWarehouses()
|
|
|
},
|
|
|
async getAllWarehouses() {
|
|
|
try {
|
|
|
const formData = new FormData()
|
|
|
formData.append('page', 1)
|
|
|
formData.append('page_size', 999)
|
|
|
formData.append('table_name', 'materialstorages')
|
|
|
|
|
|
const res = await index(formData)
|
|
|
if (res && res.data) {
|
|
|
this.allWarehouses = res.data
|
|
|
this.filterWarehouses()
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('获取仓库列表失败:', e)
|
|
|
this.$message.error('获取仓库列表失败')
|
|
|
}
|
|
|
},
|
|
|
|
|
|
filterWarehouses() {
|
|
|
let filtered = [...this.allWarehouses]
|
|
|
|
|
|
// 按仓库类型筛选
|
|
|
if (this.select.storehouses_id) {
|
|
|
filtered = filtered.filter(warehouse =>
|
|
|
warehouse.storehouses_id === this.select.storehouses_id
|
|
|
)
|
|
|
}
|
|
|
|
|
|
// 按区域筛选
|
|
|
if (this.select.area) {
|
|
|
filtered = filtered.filter(warehouse =>
|
|
|
warehouse.quyu_id === this.select.area
|
|
|
)
|
|
|
}
|
|
|
|
|
|
// 更新仓库名称列表
|
|
|
this.warehouseNames = filtered.map(warehouse => ({
|
|
|
value: warehouse.id,
|
|
|
label: warehouse.cangkumingcheng
|
|
|
}))
|
|
|
},
|
|
|
|
|
|
async handleCustomSubmit() {
|
|
|
this.$refs.form.validate(async(valid) => {
|
|
|
if (valid) {
|
|
|
const data = {
|
|
|
name: this.form.name,
|
|
|
month_frequency: this.form.cycle,
|
|
|
start_standard: this.form.startSetting,
|
|
|
advance_days: this.form.timingValue,
|
|
|
next_plan_type: this.form.nextPlan,
|
|
|
remark: this.form.notes,
|
|
|
equipment_maintain_config_stocks_items: this.selectedMaterialIds?.map(id => [{ stocks_item_id: id }]) || []
|
|
|
}
|
|
|
try {
|
|
|
await saveMaintainConfig(data)
|
|
|
this.$message.success('保存成功')
|
|
|
this.showModal = false
|
|
|
this.getList()
|
|
|
} catch (e) {
|
|
|
this.$message.error('保存失败')
|
|
|
}
|
|
|
} else {
|
|
|
this.$message.error('请填写所有必填项')
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
.table-page-container {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
height: 100vh;
|
|
|
box-sizing: border-box;
|
|
|
background: #f5f7fa;
|
|
|
}
|
|
|
.table-flex-content {
|
|
|
flex: 1 1 0;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
min-height: 0;
|
|
|
}
|
|
|
.el-table th {
|
|
|
background: #f5f7fa !important;
|
|
|
color: #333;
|
|
|
font-weight: bold;
|
|
|
font-size: 15px;
|
|
|
}
|
|
|
.el-table td {
|
|
|
font-size: 14px;
|
|
|
height: 48px;
|
|
|
}
|
|
|
.el-table {
|
|
|
border-radius: 10px;
|
|
|
overflow: hidden;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
}
|
|
|
.timing-controls {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 8px;
|
|
|
}
|
|
|
.associate-toolbar {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
flex-wrap: wrap;
|
|
|
gap: 10px;
|
|
|
margin-bottom: 15px;
|
|
|
}
|
|
|
.pagination-container {
|
|
|
display: flex;
|
|
|
justify-content: flex-end;
|
|
|
align-items: center;
|
|
|
margin-top: 15px;
|
|
|
}
|
|
|
/* 确保加载提示显示在模态框之上 */
|
|
|
.ivu-message {
|
|
|
z-index: 9999 !important;
|
|
|
}
|
|
|
.ivu-loading-mask {
|
|
|
z-index: 9999 !important;
|
|
|
}
|
|
|
.ivu-message-notice {
|
|
|
z-index: 9999 !important;
|
|
|
}
|
|
|
.ivu-message-notice-content {
|
|
|
z-index: 9999 !important;
|
|
|
}
|
|
|
.ivu-modal-mask {
|
|
|
z-index: 1000 !important;
|
|
|
}
|
|
|
.ivu-modal-wrap {
|
|
|
z-index: 1000 !important;
|
|
|
}
|
|
|
/* .ivu-btn {
|
|
|
margin: 0 4px;
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
.ivu-btn-error {
|
|
|
background-color: #ed4014;
|
|
|
border-color: #ed4014;
|
|
|
color: #fff;
|
|
|
}
|
|
|
|
|
|
.ivu-btn-error:hover {
|
|
|
background-color: #f16643;
|
|
|
border-color: #f16643;
|
|
|
color: #fff;
|
|
|
}
|
|
|
|
|
|
.ivu-btn-warning {
|
|
|
background-color: #ff9900;
|
|
|
border-color: #ff9900;
|
|
|
color: #fff;
|
|
|
}
|
|
|
|
|
|
.ivu-btn-warning:hover {
|
|
|
background-color: #ffad33;
|
|
|
border-color: #ffad33;
|
|
|
color: #fff;
|
|
|
}
|
|
|
|
|
|
.ivu-btn-primary {
|
|
|
background-color: #2d8cf0;
|
|
|
border-color: #2d8cf0;
|
|
|
color: #fff;
|
|
|
}
|
|
|
|
|
|
.ivu-btn-primary:hover {
|
|
|
background-color: #5cadff;
|
|
|
border-color: #5cadff;
|
|
|
color: #fff;
|
|
|
} */
|
|
|
</style>
|