feat(订单明细): 添加删除订单明细功能

feat(辅料管理): 新增辅料变动记录功能

feat(仪表拓扑): 在仪表标签中显示上次抄表记录

fix(设备管理): 修复图片预览空值问题

refactor(员工管理): 部门树显示负责人信息

style(备件变动): 优化备件变动页面布局

docs(订单记录): 更新操作类型映射表

test(销售异议): 新增销售异议管理模块

chore: 更新.gitignore文件
This commit is contained in:
砂糖
2026-01-04 14:42:51 +08:00
parent aeecf4bcf7
commit 42dbbf79ae
16 changed files with 1724 additions and 316 deletions

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询辅料列表
export function listAuxiliaryMaterial(query) {
return request({
url: '/mes/auxiliaryMaterial/list',
method: 'get',
params: query
})
}
// 查询辅料详细
export function getAuxiliaryMaterial(auxiliaryId) {
return request({
url: '/mes/auxiliaryMaterial/' + auxiliaryId,
method: 'get'
})
}
// 新增辅料
export function addAuxiliaryMaterial(data) {
return request({
url: '/mes/auxiliaryMaterial',
method: 'post',
data: data
})
}
// 修改辅料
export function updateAuxiliaryMaterial(data) {
return request({
url: '/mes/auxiliaryMaterial',
method: 'put',
data: data
})
}
// 删除辅料
export function delAuxiliaryMaterial(auxiliaryId) {
return request({
url: '/mes/auxiliaryMaterial/' + auxiliaryId,
method: 'delete'
})
}

View File

@@ -0,0 +1,52 @@
import request from '@/utils/request'
// 查询辅料变动记录列表
export function listAuxiliaryMaterialChange(query) {
return request({
url: '/mes/auxiliaryMaterialChange/list',
method: 'get',
params: query
})
}
// 查询辅料变动记录详细
export function getAuxiliaryMaterialChange(changeId) {
return request({
url: '/mes/auxiliaryMaterialChange/' + changeId,
method: 'get'
})
}
// 新增辅料变动记录
export function addAuxiliaryMaterialChange(data) {
return request({
url: '/mes/auxiliaryMaterialChange',
method: 'post',
data: data
})
}
// 修改辅料变动记录
export function updateAuxiliaryMaterialChange(data) {
return request({
url: '/mes/auxiliaryMaterialChange',
method: 'put',
data: data
})
}
// 删除辅料变动记录
export function delAuxiliaryMaterialChange(changeId) {
return request({
url: '/mes/auxiliaryMaterialChange/' + changeId,
method: 'delete'
})
}
export function changeStock(data) {
return request({
url: '/mes/auxiliaryMaterialChange/changeStock',
method: 'post',
data
})
}

View File

@@ -246,9 +246,10 @@ export default {
/** 删除按钮操作 */
handleDelete(row) {
const itemIds = row.itemId || this.ids;
const orderId = this.orderId;
this.$modal.confirm('是否确认删除正式订单明细编号为"' + itemIds + '"的数据项?').then(() => {
this.loading = true;
return delOrderItem(itemIds);
return actions[ORDER_ACTIONS.deleteOrderDetail].handler(itemIds, orderId)
}).then(() => {
this.loading = false;
this.getList();

View File

@@ -119,7 +119,8 @@ export default {
[ORDER_ACTIONS.createOrder]: '创建正式订单',
[ORDER_ACTIONS.updateOrder]: '修改正式订单',
[ORDER_ACTIONS.createOrderdetail]: '创建订单明细',
[ORDER_ACTIONS.updateOrderdetail]: '修改订单明细'
[ORDER_ACTIONS.updateOrderdetail]: '修改订单明细',
[ORDER_ACTIONS.deleteOrderDetail]: '删除订单明细',
};
// 若不存在对应映射,返回原始类型
return actionNameMap[type] || type || '未知操作';

View File

@@ -1,5 +1,5 @@
import { addOrder, updateOrder } from '@/api/crm/order'
import { addOrderItem, updateOrderItem } from '@/api/crm/orderItem'
import { addOrderItem, updateOrderItem, delOrderItem } from '@/api/crm/orderItem'
import { addOrderOperationTrace } from '@/api/crm/orderOperationTrace'
// 需要被记录的操作
@@ -11,6 +11,7 @@ const ORDER_ACTIONS = {
updateOrder: 'updateOrder',
createOrderdetail: 'createOrderdetail',
updateOrderdetail: 'updateOrderdetail',
deleteOrderDetail: 'deleteOrderDetail'
}
const actions = {
@@ -66,11 +67,12 @@ const actions = {
const { data: orderItem } = await addOrderItem({
...payload,
})
if (orderItem.orderItemId) {
console.log(payload)
if (payload.orderId) {
addOrderOperationTrace({
orderId: orderItem.orderId,
orderId: payload.orderId,
operationType: ORDER_ACTIONS.createOrderdetail,
newStatus: payload.orderItemId,
newStatus: payload.orderId,
operationContent: JSON.stringify(payload)
})
}
@@ -90,7 +92,7 @@ const actions = {
addOrderOperationTrace({
orderId: payload.orderId,
operationType: ORDER_ACTIONS.updateOrderdetail,
newStatus: payload.orderItemId,
newStatus: payload.orderId,
operationContent: JSON.stringify(payload)
})
@@ -98,6 +100,25 @@ const actions = {
}
},
deleteOrderDetail: {
type: 'deleteOrderDetail',
name: '删除订单明细',
description: '删除订单明细的相关信息',
// 订单明细的相关信息
async handler(payload, orderId) {
await delOrderItem(payload)
console.log(payload)
addOrderOperationTrace({
orderId: orderId,
operationType: ORDER_ACTIONS.deleteOrderDetail,
newStatus: payload,
operationContent: payload
})
return payload
}
},
// 预订单审批为正式订单
approvePreOrder: {
type: 'approvePreOrder',

View File

@@ -0,0 +1,360 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="异议编号" prop="objectionCode">
<el-input v-model="queryParams.objectionCode" placeholder="请输入异议编号" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="处理人" prop="handleUser">
<el-input v-model="queryParams.handleUser" placeholder="请输入处理人" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="salesObjectionList" @selection-change="handleSelectionChange">
<el-table-column label="编号" align="center" prop="objectionCode" />
<!-- <el-table-column label="异议类型" align="center" prop="objectionType" /> -->
<!-- <el-table-column label="异议内容" align="center" prop="objectionContent" /> -->
<el-table-column label="状态" align="center" prop="objectionStatus">
<template slot-scope="scope">
<el-tag v-if="scope.row.objectionStatus === 0" type="danger">待处理</el-tag>
<el-tag v-else-if="scope.row.objectionStatus === 1" type="success">已处理</el-tag>
<el-tag v-else-if="scope.row.objectionStatus === 2" type="info">已关闭</el-tag>
</template>
</el-table-column>
<!-- <el-table-column label="处理内容" align="center" prop="handleContent" /> -->
<el-table-column label="处理人" align="center" prop="handleUser" />
<el-table-column label="处理时间" align="center" prop="handleTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="结案时间" align="center" prop="closeTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.closeTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column> -->
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"></el-button>
<el-button size="mini" type="text" icon="el-icon-check" @click="handleDo(scope.row)"
v-if="scope.row.objectionStatus == 0"></el-button>
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"
v-if="scope.row.objectionStatus == 1"></el-button>
<!-- <el-button
size="mini"
type="text"
icon="el-icon-check"
@click="handleFinish(scope.row)"
>结案</el-button> -->
<el-button size="mini" type="text" icon="el-icon-delete" @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 :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="异议编号" prop="objectionCode">
<el-input v-model="form.objectionCode" placeholder="请输入异议编号" />
</el-form-item>
<el-form-item label="异议内容">
<editor v-model="form.objectionContent" :min-height="192" />
</el-form-item>
<el-form-item label="订单编号">
<order-select v-model="form.orderId" placeholder="请选择订单" />
</el-form-item>
<el-form-item label="异议客户">
<customer-select v-model="form.customerId" placeholder="请选择客户" />
</el-form-item>
<!-- <el-form-item label="处理内容">
<editor v-model="form.handleContent" :min-height="192"/>
</el-form-item>
<el-form-item label="处理人" prop="handleUser">
<el-input v-model="form.handleUser" placeholder="请输入处理人" />
</el-form-item>
<el-form-item label="处理时间" prop="handleTime">
<el-date-picker clearable
v-model="form.handleTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择处理时间">
</el-date-picker>
</el-form-item>
<el-form-item label="结案时间" prop="closeTime">
<el-date-picker clearable
v-model="form.closeTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择结案时间">
</el-date-picker>
</el-form-item> -->
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<el-dialog title="处理订单" :visible.sync="checkOpen" width="500px" append-to-body>
<el-form ref="form" :model="checkForm" :rules="rules" label-width="80px">
<el-form-item label="处理内容">
<editor v-model="checkForm.handleContent" :min-height="192" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitCheckForm"> </el-button>
<el-button @click="checkOpen = false"> </el-button>
</div>
</el-dialog>
<el-dialog title="查看处理结果" :visible.sync="viewOpen" width="500px" append-to-body>
<el-descriptions :column="2" :data="viewForm" label-width="80px">
<el-descriptions-item label="处理人">{{ viewForm.handleUser }}</el-descriptions-item>
<el-descriptions-item label="处理时间">{{ viewForm.handleTime }}</el-descriptions-item>
<el-descriptions-item label="处理内容" :span="2">
<div v-html="viewForm.handleContent"></div>
</el-descriptions-item>
</el-descriptions>
<div slot="footer" class="dialog-footer">
<el-button @click="viewOpen = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listSalesObjection, getSalesObjection, delSalesObjection, addSalesObjection, updateSalesObjection } from "@/api/crm/salesObjection";
import OrderSelect from "@/components/KLPService/OrderSelect";
import CustomerSelect from "@/components/KLPService/CustomerSelect";
export default {
name: "SalesObjection",
components: {
OrderSelect,
CustomerSelect,
},
computed: {
currentUserName() {
return this.$store.getters.name;
}
},
created() {
this.getList();
},
data() {
return {
// 按钮loading
buttonLoading: false,
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 销售异议管理表格数据
salesObjectionList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
objectionCode: undefined,
orderId: undefined,
customerId: undefined,
objectionType: undefined,
objectionContent: undefined,
objectionStatus: undefined,
handleContent: undefined,
handleUser: undefined,
handleTime: undefined,
closeTime: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
},
checkForm: {
handleContent: undefined,
},
checkOpen: false,
viewForm: {},
viewOpen: false,
};
},
methods: {
/** 查询销售异议管理列表 */
getList() {
this.loading = true;
listSalesObjection(this.queryParams).then(response => {
this.salesObjectionList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
handleView(row) {
this.viewForm = row;
this.viewOpen = true;
},
// 表单重置
reset() {
this.form = {
objectionId: undefined,
objectionCode: undefined,
orderId: this.orderId,
customerId: this.customerId,
objectionType: 0,
objectionContent: undefined,
objectionStatus: undefined,
handleContent: undefined,
handleUser: undefined,
handleTime: undefined,
closeTime: undefined,
remark: undefined,
createBy: undefined,
createTime: undefined,
updateBy: undefined,
updateTime: undefined,
delFlag: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.objectionId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
handleDo(row) {
console.log(row, '处理')
this.checkForm = row;
this.checkOpen = true;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加销售异议管理";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
this.reset();
const objectionId = row.objectionId || this.ids
getSalesObjection(objectionId).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改销售异议管理";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.form.objectionId != null) {
updateSalesObjection(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
addSalesObjection(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
/** 提交处理按钮 */
submitCheckForm() {
this.buttonLoading = true;
updateSalesObjection({
...this.checkForm,
handleUser: this.currentUserName,
handleTime: this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
objectionStatus: 1,
}).then(response => {
this.$modal.msgSuccess("处理成功");
this.checkOpen = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
},
/** 删除按钮操作 */
handleDelete(row) {
const objectionIds = row.objectionId || this.ids;
this.$modal.confirm('是否确认删除销售异议管理编号为"' + objectionIds + '"的数据项?').then(() => {
this.loading = true;
return delSalesObjection(objectionIds);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
/** 导出按钮操作 */
handleExport() {
this.download('crm/salesObjection/export', {
...this.queryParams
}, `salesObjection_${new Date().getTime()}.xlsx`)
}
}
};
</script>

View File

@@ -49,6 +49,7 @@
<div style="width: 100%; height: 1px; background: #ebeef5; margin: 8px 0;"></div>
<div class="legend-item">
<span style="font-size: 11px; color: #909399;">不同能源类型使用不同图案三角星形等</span>
<span style="font-size: 11px; color: #909399;">括号内的数字为上次抄表时的记录值没有括号则表示未抄过表</span>
</div>
</div>
</div>
@@ -445,10 +446,15 @@ export default {
const deviceShape = this.getDeviceShape(meter.energyTypeId);
// 根据设备状态选择不同的颜色
const deviceColor = this.getDeviceColor(meter.status);
let label = meter.meterCode;
if (meter.lastReading) {
label += `(${meter.lastReading || '-'})`
}
nodesData.push({
id: deviceId,
label: meter.meterCode,
label,
title: `${meter.meterCode} (${energyType?.name || '-'})`,
shape: deviceShape,
size: 20,
@@ -457,7 +463,7 @@ export default {
data: {
type: 'device',
...meter,
energyType: energyType?.name || '-'
energyType: energyType?.name || '-',
}
});

View File

@@ -1,163 +1,201 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="文档编号" prop="docNo">
<el-input
v-model="queryParams.docNo"
placeholder="请输入文档编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="文档名称" prop="docName">
<el-input
v-model="queryParams.docName"
placeholder="请输入文档名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="文档分类" prop="docCategory">
<el-select v-model="queryParams.docCategory" placeholder="请选择文档分类" clearable>
<el-option
v-for="dict in dict.type.doc_category"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="文档类型" prop="docType">
<el-select v-model="queryParams.docType" placeholder="请选择文档类型" clearable>
<el-option
v-for="dict in dict.type.doc_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="发布状态" prop="publishStatus">
<el-select v-model="queryParams.publishStatus" placeholder="请选择发布状态" clearable>
<el-option
v-for="dict in dict.type.publish_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="发布日期" prop="publishTime">
<el-date-picker clearable
v-model="queryParams.publishTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择发布日期">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 左右分栏布局左侧自定义列表右侧预览 -->
<el-row :gutter="20" class="layout-row">
<!-- 左侧自定义列表区域占10列 -->
<el-col :span="6" class="left-list-container">
<!-- 本地搜索表单改造后 -->
<el-form
@submit.native.prevent
:model="searchForm"
ref="searchForm"
size="small"
:inline="true"
v-show="showSearch"
label-width="68px"
class="query-form"
>
<!-- 关键字搜索文档编号+文档名称联合搜索 -->
<el-form-item label="关键字搜索" prop="keyword">
<el-input
v-model="searchForm.keyword"
placeholder="请输入文档编号/文档名称"
clearable
@change="handleLocalSearch"
/>
</el-form-item>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
<!-- 文档分类el-radio-button 单选 -->
<el-form-item label="文档分类" prop="docCategory">
<el-radio-group v-model="searchForm.docCategory" @change="handleLocalSearch">
<el-radio-button label="" value="">全部</el-radio-button>
<el-radio-button
v-for="dict in dict.type.doc_category"
:key="dict.value"
:label="dict.value"
:value="dict.value"
>{{ dict.label }}</el-radio-button>
</el-radio-group>
</el-form-item>
<!-- 文档类型el-radio-button 单选 -->
<el-form-item label="文档类型" prop="docType">
<el-radio-group v-model="searchForm.docType" @change="handleLocalSearch">
<el-radio-button label="" value="">全部</el-radio-button>
<el-radio-button
v-for="dict in dict.type.doc_type"
:key="dict.value"
:label="dict.value"
:value="dict.value"
>{{ dict.label }}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleLocalSearch">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetLocalSearch">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="handleLocalSearch"></right-toolbar>
</el-row>
<!-- 自定义文档列表替代表格无分页 -->
<div v-loading="loading" class="custom-doc-list">
<!-- 单个文档项 -->
<div
v-for="item in safetyEnvDocList"
:key="item.docId"
class="doc-item"
:class="{ 'active': currentSelectDoc && currentSelectDoc.docId === item.docId }"
@click="handleDocItemClick(item)"
>
<div class="doc-status">
<dict-tag :options="dict.type.publish_status" :value="item.publishStatus"/>
</div>
<div class="doc-base-info">
<p class="doc-no">{{ item.docName || '-' }}</p>
<p class="doc-name">{{ item.docNo || '-' }}</p>
</div>
<div class="doc-operate">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click.stop="handleUpdate(item)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click.stop="handleDelete(item)"
>删除</el-button>
</div>
</div>
<!-- 无数据提示 -->
<div v-if="!loading && safetyEnvDocList.length === 0" class="empty-list">
<el-empty description="暂无文档数据" :image-size="100"></el-empty>
</div>
</div>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改</el-button>
<!-- 右侧预览区域占14列增加iframe附件预览 -->
<el-col :span="18" class="right-preview-container">
<el-card title="文档详情预览" class="preview-card" :body-style="{ padding: '20px', height: '100%', 'box-sizing': 'border-box' }">
<!-- 无选中数据时的提示 -->
<div v-if="!previewData" class="empty-preview">
<el-empty description="请选择左侧文档进行预览" :image-size="120"></el-empty>
</div>
<!-- 有选中数据时的预览内容 -->
<div v-else class="preview-content">
<!-- 文档基本信息 -->
<el-descriptions :column="3" border class="doc-descriptions">
<el-descriptions-item label="文档编号">
{{ previewData.docNo || '-' }}
</el-descriptions-item>
<el-descriptions-item label="文档名称">
{{ previewData.docName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="文档分类">
<dict-tag :options="dict.type.doc_category" :value="previewData.docCategory"/>
</el-descriptions-item>
<el-descriptions-item label="文档类型">
<dict-tag :options="dict.type.doc_type" :value="previewData.docType"/>
</el-descriptions-item>
<el-descriptions-item label="发布状态">
<dict-tag :options="dict.type.publish_status" :value="previewData.publishStatus"/>
</el-descriptions-item>
<el-descriptions-item label="发布日期">
{{ parseTime(previewData.publishTime, '{y}-{m}-{d} {h}:{i}:{s}') || '-' }}
</el-descriptions-item>
<el-descriptions-item label="备注">
{{ previewData.remark || '-' }}
</el-descriptions-item>
</el-descriptions>
<!-- iframe PDF附件预览 -->
<div class="pdf-preview-area">
<!-- 有附件时显示iframe -->
<iframe
v-if="previewData.accessory"
:src="pdfUrl"
class="pdf-iframe"
frameborder="0"
title="PDF附件预览"
></iframe>
<!-- 无附件时显示提示 -->
<div v-else class="no-pdf-tip">
<el-empty description="暂无PDF附件可供预览" :image-size="80"></el-empty>
</div>
</div>
</div>
</el-card>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="safetyEnvDocList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="文档编号" align="center" prop="docNo" />
<el-table-column label="文档名称" align="center" prop="docName" />
<el-table-column label="文档分类" align="center" prop="docCategory">
<template slot-scope="scope">
<dict-tag :options="dict.type.doc_category" :value="scope.row.docCategory"/>
</template>
</el-table-column>
<el-table-column label="文档类型" align="center" prop="docType">
<template slot-scope="scope">
<dict-tag :options="dict.type.doc_type" :value="scope.row.docType"/>
</template>
</el-table-column>
<el-form-item label="附件" prop="accessory">
<file-upload v-model="form.accessory" :limit="1" :fileType="fileType" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-table-column label="发布状态" align="center" prop="publishStatus">
<template slot-scope="scope">
<dict-tag :options="dict.type.publish_status" :value="scope.row.publishStatus"/>
</template>
</el-table-column>
<el-table-column label="发布日期" align="center" prop="publishTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.publishTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@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"
/>
<!-- 添加或修改安全环保制度文档对话框 -->
<!-- 添加或修改安全环保制度文档对话框保留原有功能附件仅支持PDF -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="文档编号" prop="docNo">
@@ -186,8 +224,8 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="附件" prop="accessory">
<file-upload v-model="form.accessory" :limit="1" :fileType="fileType" type="textarea" placeholder="请输入内容" />
<el-form-item label="PDF附件" prop="accessory">
<file-upload v-model="form.accessory" :limit="1" :fileType="fileType" type="textarea" placeholder="请上传PDF格式附件" />
</el-form-item>
<el-form-item label="发布状态" prop="publishStatus">
<el-radio-group v-model="form.publishStatus">
@@ -199,11 +237,13 @@
</el-radio-group>
</el-form-item>
<el-form-item label="发布日期" prop="publishTime">
<el-date-picker clearable
<el-date-picker
clearable
v-model="form.publishTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择发布日期">
placeholder="请选择发布日期"
>
</el-date-picker>
</el-form-item>
<el-form-item label="备注" prop="remark">
@@ -220,6 +260,7 @@
<script>
import { listSafetyEnvDoc, getSafetyEnvDoc, delSafetyEnvDoc, addSafetyEnvDoc, updateSafetyEnvDoc } from "@/api/ems/safetyEnvDoc";
import { listByIds } from '@/api/system/oss'
export default {
name: "SafetyEnvDoc",
@@ -238,18 +279,44 @@ export default {
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 安全环保制度文档表格数据
// 原始全部文档数据(用于本地搜索过滤)
originSafetyEnvDocList: [],
// 过滤后展示的文档数据
safetyEnvDocList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
// 本地搜索表单参数
searchForm: {
keyword: "", // 关键字(文档编号+文档名称)
docCategory: "", // 文档分类
docType: "" // 文档类型
},
// 表单参数
form: {},
// 表单校验
rules: {},
// 右侧预览数据
previewData: null,
// 当前选中的文档(左侧列表高亮用)
currentSelectDoc: null,
// 文件类型限制仅支持PDF
fileType: ['pdf'],
pdfUrl: '',
};
},
created() {
this.getList();
},
methods: {
/** 获取所有文档数据pageSize=1000无分页 */
getList() {
this.loading = true;
// 查询参数设置pageSize=1000获取全部数据
const queryParams = {
pageNum: 1,
pageSize: 10,
pageSize: 1000, // 无分页,获取所有数据
docNo: undefined,
docName: undefined,
docCategory: undefined,
@@ -257,24 +324,12 @@ export default {
accessory: undefined,
publishStatus: undefined,
publishTime: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
}
};
},
created() {
this.getList();
},
methods: {
/** 查询安全环保制度文档列表 */
getList() {
this.loading = true;
listSafetyEnvDoc(this.queryParams).then(response => {
this.safetyEnvDocList = response.rows;
this.total = response.total;
};
listSafetyEnvDoc(queryParams).then(response => {
// 存储原始全部数据
this.originSafetyEnvDocList = response.rows || [];
// 初始化展示全部数据
this.safetyEnvDocList = [...this.originSafetyEnvDocList];
this.loading = false;
});
},
@@ -304,21 +359,77 @@ export default {
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
/** 本地搜索(关键字+文档分类+文档类型过滤) */
handleLocalSearch() {
const { keyword, docCategory, docType } = this.searchForm;
// 基于原始数据进行过滤
let filterList = [...this.originSafetyEnvDocList];
// 1. 关键字过滤(文档编号+文档名称,模糊匹配,忽略大小写)
if (keyword.trim()) {
const key = keyword.trim().toLowerCase();
filterList = filterList.filter(item => {
const docNo = (item.docNo || "").toLowerCase();
const docName = (item.docName || "").toLowerCase();
return docNo.includes(key) || docName.includes(key);
});
}
// 2. 文档分类过滤(精确匹配,非全部时过滤)
if (docCategory) {
filterList = filterList.filter(item => item.docCategory === docCategory);
}
// 3. 文档类型过滤(精确匹配,非全部时过滤)
if (docType) {
filterList = filterList.filter(item => item.docType === docType);
}
// 更新展示列表
this.safetyEnvDocList = filterList;
// 过滤后清空选中和预览数据
if (filterList.length === 0) {
this.currentSelectDoc = null;
this.previewData = null;
this.ids = [];
this.single = true;
this.multiple = true;
}
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
/** 重置本地搜索表单 */
resetLocalSearch() {
this.resetForm("searchForm");
// 重置后重新展示全部数据
this.safetyEnvDocList = [...this.originSafetyEnvDocList];
// 清空选中和预览
this.currentSelectDoc = null;
this.previewData = null;
this.ids = [];
this.single = true;
this.multiple = true;
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.docId)
this.single = selection.length!==1
this.multiple = !selection.length
// 自定义列表项点击事件
handleDocItemClick(item) {
// 更新当前选中文档(高亮)
this.currentSelectDoc = item;
// 更新预览数据
this.previewData = item;
// 更新选中ids用于修改/删除)
this.ids = [item.docId];
// 生成PDF预览URL
if (item.accessory) {
listByIds(item.accessory).then(response => {
if (response.data && response.data.length > 0) {
// 检查是否是PDF文件
if (response.data[0].fileSuffix === '.pdf') {
this.pdfUrl = response.data[0].url;
console.log(this.pdfUrl)
}
}
});
}
this.single = false; // 单个选中,取消修改按钮禁用
this.multiple = true; // 非多个选中,删除按钮禁用(单个可删除,此处保持原有逻辑)
},
/** 新增按钮操作 */
handleAdd() {
@@ -330,7 +441,8 @@ export default {
handleUpdate(row) {
this.loading = true;
this.reset();
const docId = row.docId || this.ids
const docId = row?.docId || this.ids[0];
if (!docId) return;
getSafetyEnvDoc(docId).then(response => {
this.loading = false;
this.form = response.data;
@@ -343,20 +455,22 @@ export default {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
const handleSuccess = () => {
this.$modal.msgSuccess(this.form.docId ? "修改成功" : "新增成功");
this.open = false;
// 重新获取全部数据并刷新列表
this.getList();
// 清空选中和预览
this.currentSelectDoc = null;
this.previewData = null;
};
if (this.form.docId != null) {
updateSafetyEnvDoc(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
updateSafetyEnvDoc(this.form).then(handleSuccess).finally(() => {
this.buttonLoading = false;
});
} else {
addSafetyEnvDoc(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
addSafetyEnvDoc(this.form).then(handleSuccess).finally(() => {
this.buttonLoading = false;
});
}
@@ -365,14 +479,21 @@ export default {
},
/** 删除按钮操作 */
handleDelete(row) {
const docIds = row.docId || this.ids;
const docIds = row?.docId || this.ids;
if (!docIds || docIds.length === 0) return;
this.$modal.confirm('是否确认删除安全环保制度文档编号为"' + docIds + '"的数据项?').then(() => {
this.loading = true;
return delSafetyEnvDoc(docIds);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
// 重新获取全部数据并刷新列表
this.getList();
// 清空选中和预览
this.currentSelectDoc = null;
this.previewData = null;
this.ids = [];
this.single = true;
this.multiple = true;
}).catch(() => {
}).finally(() => {
this.loading = false;
@@ -381,9 +502,174 @@ export default {
/** 导出按钮操作 */
handleExport() {
this.download('ems/safetyEnvDoc/export', {
...this.queryParams
pageNum: 1,
pageSize: 1000,
...this.searchForm
}, `safetyEnvDoc_${new Date().getTime()}.xlsx`)
}
}
};
</script>
<style scoped>
/* 整体布局样式 */
.layout-row {
height: calc(100vh - 124px); /* 适配页面高度 */
}
/* 左侧列表容器 */
.left-list-container {
height: 100%;
overflow: auto;
box-sizing: border-box;
border-radius: 4px;
}
/* 搜索表单样式 */
.query-form {
margin-bottom: 10px;
padding: 10px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.04);
}
/* 自定义文档列表样式 */
.custom-doc-list {
border-radius: 4px;
padding: 10px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.04);
}
/* 单个文档项样式 */
.doc-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 10px;
background-color: #fff;
border: 1px solid #f0f0f0;
cursor: pointer;
border-radius: 4px;
margin-bottom: 5px;
transition: background-color 0.2s ease;
}
.doc-item:hover {
background-color: #f5fafe;
}
/* 选中项高亮样式 */
.doc-item.active {
background-color: #e6f7ff;
border: 1px solid #91d5ff;
}
.doc-base-info {
flex: 1;
}
.doc-no {
font-size: 13px;
color: #606266;
margin: 0 0 4px 0;
}
.doc-name {
font-size: 14px;
color: #303133;
margin: 0;
font-weight: 500;
}
.doc-status {
margin: 0 15px;
}
.doc-operate {
display: flex;
}
/* 无列表数据提示 */
.empty-list {
display: flex;
justify-content: center;
align-items: center;
padding: 20px 0;
}
/* 右侧预览容器 */
.right-preview-container {
height: 100%;
overflow: auto;
padding: 10px;
box-sizing: border-box;
}
/* 预览卡片样式 */
.preview-card {
height: 100%;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.04);
}
/* 无数据预览样式 */
.empty-preview {
display: flex;
justify-content: center;
align-items: center;
height: 80%;
}
/* 预览内容样式 */
.preview-content {
height: 100%; /* 关键继承父级el-card body的100%高度 */
overflow: auto;
display: flex;
flex-direction: column; /* 垂直布局让pdf区域占据剩余空间 */
box-sizing: border-box; /* 防止内边距撑破容器 */
}
/* 文档详情描述样式 */
.doc-descriptions {
margin-bottom: 5px;
}
.pdf-preview-area {
flex: 1; /* 关键:占据父级 preview-content 的剩余空间 */
width: 100%;
overflow: hidden; /* 防止内部元素溢出容器 */
box-sizing: border-box;
}
.preview-title {
font-size: 15px;
color: #303133;
font-weight: 500;
margin: 0 0 10px 0;
padding-bottom: 5px;
border-bottom: 1px solid #e4e7ed;
}
/* PDF iframe样式 */
.pdf-iframe {
width: 100%;
height: 100%;
border-radius: 4px;
border: 1px solid #e4e7ed;
}
/* 无PDF提示样式 */
.no-pdf-tip {
display: flex;
justify-content: center;
align-items: center;
height: 500px;
background-color: #fafafa;
border-radius: 4px;
border: 1px dashed #dcdfe6;
}
/* 间距样式 */
.mb8 {
margin-bottom: 8px;
}
</style>

View File

@@ -8,17 +8,20 @@
<el-button size="small" icon="el-icon-refresh" @click="loadDeptTree">刷新</el-button>
</div>
<div class="tree-wrapper">
<el-tree
v-loading="deptLoading"
:data="deptTree"
:props="{ label: 'deptName', children: 'children' }"
node-key="deptId"
default-expand-all
highlight-current
:expand-on-click-node="false"
@node-click="handleDeptNodeClick"
>
<span slot-scope="{ node }" class="tree-node-label">{{ node.label }}</span>
<el-tree v-loading="deptLoading" :data="deptTree" :props="{ label: 'deptName', children: 'children' }"
node-key="deptId" default-expand-all highlight-current :expand-on-click-node="false"
@node-click="handleDeptNodeClick">
<span slot-scope="{ node }" class="tree-node-label">
<span>
{{ node.label }}
</span>
<span v-if="node.data.leader" class="leader-tag">
({{ node.data.leader }})
</span>
<span v-else class="leader-tag" style="color: red;" @click="goDept">
请配置负责人
</span>
</span>
</el-tree>
</div>
</el-card>
@@ -28,33 +31,14 @@
<div slot="header" class="card-header">
<span class="header-title">员工档案</span>
<div class="header-actions">
<el-input
v-model="query.empName"
placeholder="姓名/工号"
size="small"
clearable
style="width: 180px;"
@keyup.enter.native="loadEmployeeList"
/>
<el-select
v-model="query.postId"
size="small"
placeholder="岗位"
clearable
filterable
style="width: 160px;"
@change="loadEmployeeList"
>
<el-input v-model="query.empName" placeholder="姓名/工号" size="small" clearable style="width: 180px;"
@keyup.enter.native="loadEmployeeList" />
<el-select v-model="query.postId" size="small" placeholder="岗位" clearable filterable style="width: 160px;"
@change="loadEmployeeList">
<el-option v-for="post in postOptions" :key="post.postId" :label="post.postName" :value="post.postId" />
</el-select>
<el-select
v-model="query.status"
size="small"
placeholder="状态"
clearable
style="width: 120px;"
@change="loadEmployeeList"
>
<el-select v-model="query.status" size="small" placeholder="状态" clearable style="width: 120px;"
@change="loadEmployeeList">
<el-option label="在职" value="onboard" />
<el-option label="离职" value="leave" />
</el-select>
@@ -62,7 +46,7 @@
<el-button size="small" type="primary" icon="el-icon-plus" @click="handleAdd">新增员工</el-button>
</div>
</div>
<el-table :data="employeeList" v-loading="empLoading" stripe height="calc(100vh - 220px)">
<el-table-column prop="empNo" label="工号" min-width="110" />
<el-table-column prop="empName" label="姓名" min-width="120" />
@@ -71,7 +55,8 @@
<el-table-column prop="mobile" label="手机号" min-width="130" />
<el-table-column prop="status" label="状态" min-width="100">
<template slot-scope="scope">
<el-tag :type="scope.row.status === 'onboard' ? 'success' : 'info'" size="small">{{ scope.row.status === 'onboard' ? '在职' : '离职' }}</el-tag>
<el-tag :type="scope.row.status === 'onboard' ? 'success' : 'info'" size="small">{{ scope.row.status ===
'onboard' ? '在职' : '离职' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150" fixed="right">
@@ -83,15 +68,9 @@
</el-table>
<div class="pagination-wrapper">
<el-pagination
:current-page="query.pageNum"
:page-sizes="[10, 20, 50, 100]"
:page-size="query.pageSize"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handlePageChange"
/>
<el-pagination :current-page="query.pageNum" :page-sizes="[10, 20, 50, 100]" :page-size="query.pageSize"
:total="total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
@current-change="handlePageChange" />
</div>
</el-card>
</div>
@@ -114,15 +93,9 @@
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="主部门" prop="deptId">
<el-cascader
v-model="empForm.deptId"
:options="deptTree"
<el-cascader v-model="empForm.deptId" :options="deptTree"
:props="{ label: 'deptName', value: 'deptId', children: 'children', emitPath: false, checkStrictly: true }"
clearable
filterable
placeholder="请选择主部门"
style="width: 100%"
/>
clearable filterable placeholder="请选择主部门" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -165,23 +138,12 @@
</el-row>
<el-row :gutter="16" v-if="empForm.linkUser">
<el-col :span="24">
<el-form-item label="选择用户" prop="userId" :rules="empForm.linkUser ? [{ required: true, message: '请选择系统用户', trigger: 'change' }] : []">
<el-select
v-model="empForm.userId"
placeholder="请选择系统用户"
filterable
remote
:remote-method="searchUsers"
:loading="userLoading"
style="width: 100%"
clearable
>
<el-option
v-for="user in userOptions"
:key="user.userId"
:label="`${user.userName} (${user.nickName || ''})`"
:value="user.userId"
/>
<el-form-item label="选择用户" prop="userId"
:rules="empForm.linkUser ? [{ required: true, message: '请选择系统用户', trigger: 'change' }] : []">
<el-select v-model="empForm.userId" placeholder="请选择系统用户" filterable remote :remote-method="searchUsers"
:loading="userLoading" style="width: 100%" clearable>
<el-option v-for="user in userOptions" :key="user.userId"
:label="`${user.userName} (${user.nickName || ''})`" :value="user.userId" />
</el-select>
<div class="form-hint" v-if="!userSearchHint">
<span v-if="empForm.empName">已根据姓名"{{ empForm.empName }}"自动搜索</span>
@@ -256,6 +218,9 @@ export default {
this.deptLoading = false
})
},
goDept() {
this.$router.push('/renshi/dept')
},
buildTree(list) {
const map = {}
const roots = []
@@ -456,46 +421,57 @@ export default {
padding: 20px;
background-color: #f0f2f5;
}
.main-layout {
display: grid;
grid-template-columns: 280px 1fr;
gap: 16px;
}
.dept-tree-card, .employee-list-card {
.dept-tree-card,
.employee-list-card {
border: none;
border-radius: 4px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
.header-title {
font-size: 16px;
font-weight: 600;
color: #303133;
}
.header-actions {
display: flex;
gap: 8px;
}
}
.tree-wrapper {
height: calc(100vh - 160px);
overflow-y: auto;
}
.tree-node-label {
font-size: 14px;
}
.pagination-wrapper {
margin-top: 16px;
display: flex;
justify-content: flex-end;
}
.form-hint {
font-size: 12px;
color: #909399;
margin-top: 4px;
}
.dialog-footer {
text-align: right;
}

View File

@@ -0,0 +1,404 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="辅料名称" prop="auxiliaryName">
<el-input
v-model="queryParams.auxiliaryName"
placeholder="请输入备件名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="辅料品类" prop="materialCategory">
<el-input
v-model="queryParams.materialCategory"
placeholder="请输入物料品类"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="辅料品牌" prop="auxiliaryModel">
<el-input
v-model="queryParams.auxiliaryModel"
placeholder="请输入辅料品牌"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="计量单位" prop="unit">
<el-input
v-model="queryParams.unit"
placeholder="请输入计量单位"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- <el-form-item label="关联设备" prop="equipmentId">
<el-select v-model="queryParams.equipmentId" placeholder="请选择关联设备" filterable>
<el-option v-for="item in equipmentList" :key="item.equipmentId" :label="item.equipmentName" :value="item.equipmentId" />
</el-select>
</el-form-item> -->
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="AuxiliaryMaterialList" @row-click="handleRowClick" highlight-current-row @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="辅料名称" align="center" prop="auxiliaryName" />
<el-table-column label="辅料品类" align="center" prop="materialCategory" />
<el-table-column label="辅料品牌" align="center" prop="auxiliaryModel" />
<el-table-column label="计量单位" align="center" prop="unit" />
<!-- <el-table-column label="关联设备" align="center" prop="equipmentName" /> -->
<el-table-column label="当前库存" align="center" prop="quantity" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click.native.stop="handleAddChange(scope.row)"
>增加</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click.native.stop="handleReduce(scope.row)"
>减少</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click.native.stop="handleUpdate(scope.row)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click.native.stop="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 :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="辅料名称" prop="auxiliaryName">
<el-input v-model="form.auxiliaryName" placeholder="请输入辅料名称" />
</el-form-item>
<el-form-item label="辅料品类" prop="materialCategory">
<el-input v-model="form.materialCategory" placeholder="请输入辅料品类" />
</el-form-item>
<el-form-item label="辅料品牌" prop="auxiliaryModel">
<el-input v-model="form.auxiliaryModel" placeholder="请输入辅料品牌" />
</el-form-item>
<el-form-item label="计量单位" prop="unit">
<el-input v-model="form.unit" placeholder="请输入计量单位" />
</el-form-item>
<!-- <el-form-item label="关联设备ID" prop="equipmentId">
<el-select v-model="form.equipmentId" placeholder="请选择关联设备ID" filterable>
<el-option v-for="item in equipmentList" :key="item.equipmentId" :label="item.equipmentName" :value="item.equipmentId" />
</el-select>
</el-form-item> -->
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<el-dialog title="库存变动" :visible.sync="changeOpen" width="500px" append-to-body>
<el-form ref="changeForm" :model="changeForm" label-width="80px">
<el-form-item label="变动类型">
<el-select v-model="changeForm.changeType" placeholder="请选择变动类型">
<el-option label="增加" value="增加" />
<el-option label="减少" value="减少" />
</el-select>
</el-form-item>
<el-form-item label="变动数量">
<el-input-number v-model="changeForm.changeQuantity" :min="0" :step="1" placeholder="请输入变动数量" size="mini"/>
</el-form-item>
<el-form-item label="变动原因">
<el-input type="textarea" v-model="changeForm.reason" placeholder="请输入变动原因" size="mini"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="changeSubmitForm"> </el-button>
<el-button @click="changeCancel"> </el-button>
</div>
</el-dialog>
<!-- 辅料变动记录对话框 -->
<auxiliaryChange ref="auxiliaryChange" v-if="currentRow.auxiliaryId" :auxiliaryId="currentRow.auxiliaryId" />
<el-empty v-else description="请选择辅料查看变动记录" />
</div>
</template>
<script>
import { listAuxiliaryMaterial, getAuxiliaryMaterial, delAuxiliaryMaterial, addAuxiliaryMaterial, updateAuxiliaryMaterial } from "@/api/mes/eqp/auxiliaryMaterial";
import { changeStock } from "@/api/mes/eqp/auxiliaryMaterialChange";
import auxiliaryChange from '../components/pages/auxiliaryChange.vue';
export default {
name: "Auxiliary",
components: {
auxiliaryChange
},
data() {
return {
currentRow: {},
// 按钮loading
buttonLoading: false,
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 辅料表格数据
AuxiliaryMaterialList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
auxiliaryName: undefined,
materialCategory: undefined,
auxiliaryModel: undefined,
unit: undefined,
equipmentId: undefined,
quantity: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
},
equipmentList: [],
changeOpen: false,
changeTitle: '',
changeForm: {},
};
},
created() {
this.getList();
// this.getEquipmentList();
},
methods: {
/** 查询辅料列表 */
// getEquipmentList() {
// listEquipmentManagement({ pageNum: 1, pageSize: 1000 }).then(response => {
// this.equipmentList = response.rows;
// });
// },
getList() {
this.loading = true;
listAuxiliaryMaterial(this.queryParams).then(response => {
this.AuxiliaryMaterialList = response.rows;
this.total = response.total;
this.loading = false;
});
},
handleRowClick(row) {
this.currentRow = row;
},
handleAddChange(row) {
this.changeOpen = true;
this.changeForm = {
changeType: '增加',
auxiliaryId: row.auxiliaryId,
}
},
handleReduce(row) {
this.changeOpen = true;
this.changeForm = {
changeType: '减少',
auxiliaryId: row.auxiliaryId,
}
},
changeCancel() {
this.changeOpen = false;
},
changeSubmitForm() {
this.buttonLoading = true;
changeStock(this.changeForm).then(response => {
this.buttonLoading = false;
this.$modal.msgSuccess("操作成功");
this.getList();
this.$refs["partChange"].getList();
}).finally(() => {
this.buttonLoading = false;
this.changeCancel();
})
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
auxiliaryId: undefined,
auxiliaryName: undefined,
materialCategory: undefined,
auxiliaryModel: undefined,
unit: undefined,
equipmentId: undefined,
quantity: 0,
createBy: undefined,
updateBy: undefined,
createTime: undefined,
updateTime: undefined,
delFlag: undefined,
remark: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.auxiliaryId)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加辅料";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
this.reset();
const auxiliaryId = row.auxiliaryId || this.ids
getAuxiliaryMaterial(auxiliaryId).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改辅料";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.form.auxiliaryId != null) {
updateAuxiliaryMaterial(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
addAuxiliaryMaterial(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const auxiliaryIds = row.auxiliaryId || this.ids;
this.$modal.confirm('是否确认删除辅料编号为"' + auxiliaryIds + '"的数据项?').then(() => {
this.loading = true;
return delAuxiliaryMaterial(auxiliaryIds);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
/** 导出按钮操作 */
handleExport() {
this.download('eqp/AuxiliaryMaterial/export', {
...this.queryParams
}, `AuxiliaryMaterial_${new Date().getTime()}.xlsx`)
}
}
};
</script>

View File

@@ -0,0 +1,253 @@
<template>
<div>
<el-form v-if="!auxiliaryId" :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
label-width="68px">
<el-form-item label="关联备件" prop="auxiliaryId">
<el-select v-model="queryParams.auxiliaryId" placeholder="请选择关联备件">
<el-option v-for="item in auxiliaryList" :key="item.auxiliaryId" :label="item.auxiliaryName" :value="item.auxiliaryId" />
</el-select>
</el-form-item>
<el-form-item label="变动数量" prop="changeQuantity">
<el-input v-model="queryParams.changeQuantity" placeholder="请输入变动数量" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="变动原因" prop="reason">
<el-input v-model="queryParams.reason" placeholder="请输入变动原因" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="变动时间" prop="changeTime">
<el-date-picker clearable v-model="queryParams.changeTime" type="date" value-format="yyyy-MM-dd"
placeholder="请选择变动时间">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="AuxiliaryMaterialChangeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="关联辅料" align="center" prop="auxiliaryName" v-if="!auxiliaryId">
<template slot-scope="scope">
<span>{{ getAuxiliaryMaterialName(scope.row.auxiliaryId) }}</span>
</template>
</el-table-column>
<el-table-column label="变动类型" align="center" prop="changeType" />
<el-table-column label="变动数量" align="center" prop="changeQuantity" />
<el-table-column label="变动原因" align="center" prop="reason" />
<el-table-column label="变动时间" align="center" prop="changeTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.changeTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
</div>
</template>
<script>
import { listAuxiliaryMaterialChange, getAuxiliaryMaterialChange, delAuxiliaryMaterialChange, addAuxiliaryMaterialChange, updateAuxiliaryMaterialChange } from "@/api/mes/eqp/auxiliaryMaterialChange";
import { listAuxiliaryMaterial } from "@/api/mes/eqp/auxiliaryMaterial";
export default {
name: "AuxiliaryMaterialChange",
props: {
auxiliaryId: {
type: String,
default: undefined
}
},
data() {
return {
// 按钮loading
buttonLoading: false,
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 备品备件变动记录表格数据
AuxiliaryMaterialChangeList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
auxiliaryId: this.auxiliaryId,
changeType: undefined,
changeQuantity: undefined,
reason: undefined,
changeTime: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
},
partList: []
};
},
created() {
this.getList();
if (this.auxiliaryId) {
return;
}
this.getPartList();
},
watch: {
auxiliaryId: {
handler(newVal, oldVal) {
if (newVal !== oldVal && newVal !== undefined) {
this.queryParams.auxiliaryId = newVal;
this.getList();
}
},
immediate: true
}
},
methods: {
// 获取辅料名称
getAuxiliaryMaterialName(auxiliaryId) {
const auxiliary = this.partList.find(item => item.auxiliaryId == auxiliaryId);
return auxiliary ? auxiliary.auxiliaryName : '';
},
getPartList() {
listAuxiliaryMaterial({ pageNum: 1, pageSize: 1000 }).then(response => {
this.partList = response.rows;
});
},
/** 查询备品备件变动记录列表 */
getList() {
this.loading = true;
listAuxiliaryMaterialChange(this.queryParams).then(response => {
this.AuxiliaryMaterialChangeList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
changeId: undefined,
auxiliaryId: this.auxiliaryId,
changeType: undefined,
changeQuantity: undefined,
reason: undefined,
changeTime: undefined,
createBy: undefined,
updateBy: undefined,
createTime: undefined,
updateTime: undefined,
delFlag: undefined,
remark: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.changeId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加备品备件变动记录";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
this.reset();
const changeId = row.changeId || this.ids
getAuxiliaryMaterialChange(changeId).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改备品备件变动记录";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.form.changeId != null) {
updateAuxiliaryMaterialChange(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
addAuxiliaryMaterialChange(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const changeIds = row.changeId || this.ids;
this.$modal.confirm('是否确认删除备品备件变动记录编号为"' + changeIds + '"的数据项?').then(() => {
this.loading = true;
return delAuxiliaryMaterialChange(changeIds);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
/** 导出按钮操作 */
handleExport() {
this.download('eqp/AuxiliaryMaterialChange/export', {
...this.queryParams
}, `AuxiliaryMaterialChange_${new Date().getTime()}.xlsx`)
}
}
};
</script>

View File

@@ -66,7 +66,7 @@
<el-table-column label="负责人" align="center" prop="manager" />
<el-table-column label="图片" align="center" prop="ossId" v-if="preview">
<template slot-scope="scope">
<image-preview :src="scope.row.ossId" fit="fill" />
<image-preview v-if="scope.row.ossId" :src="scope.row.ossId" fit="fill" />
</template>
</el-table-column>
<el-table-column label="启用时间" align="center" prop="enableTime" width="180" v-if="isInService">
@@ -78,13 +78,13 @@
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button v-if="isInService" type="text" plain icon="el-icon-delete" size="mini" :loading="buttonLoading"
@click="handleSetStatus(scope.row)">
@click.stop="handleSetStatus(scope.row)">
停用
</el-button>
<el-button v-else size="mini" type="text" icon="el-icon-caret-right" :loading="buttonLoading"
@click="handleSetStatus(scope.row)">启用</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
@click.stop="handleSetStatus(scope.row)">启用</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click.stop="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>

View File

@@ -1,5 +1,5 @@
<template>
<div class="app-container">
<div>
<el-form v-if="!partId" :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="关联备件" prop="partId">
<el-select v-model="queryParams.partId" placeholder="请选择关联备件">
@@ -51,7 +51,7 @@
<el-table v-loading="loading" :data="sparePartsChangeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="关联备件" align="center" prop="partName" />
<el-table-column label="关联备件" align="center" prop="partName" v-if="!partId" />
<el-table-column label="变动类型" align="center" prop="changeType" />
<el-table-column label="变动数量" align="center" prop="changeQuantity" />
<el-table-column label="变动原因" align="center" prop="reason" />
@@ -81,7 +81,7 @@ export default {
name: "SparePartsChange",
props: {
partId: {
type: Number,
type: String,
default: undefined
}
},

View File

@@ -1,16 +1,32 @@
<template>
<div>
<partChange />
<el-tabs v-model="activeTab" type="border-card">
<el-tab-pane label="备件变动" name="partChange">
<partChange v-if="activeTab === 'partChange'"/>
</el-tab-pane>
<el-tab-pane label="辅料变动" name="auxiliaryChange">
<auxiliaryChange v-if="activeTab === 'auxiliaryChange'"/>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import partChange from '../components/pages/partChange.vue';
import auxiliaryChange from '../components/pages/auxiliaryChange.vue';
export default {
name: "ReadyChange",
data() {
return {
activeTab: 'partChange'
}
},
components: {
partChange
partChange,
auxiliaryChange
}
}
</script>

View File

@@ -243,25 +243,12 @@ export default {
changeOpen: false,
changeTitle: '',
changeForm: {},
changes: [],
};
},
created() {
this.getList();
this.getEquipmentList();
},
watch: {
currentRow: {
handler(newVal) {
if (newVal.partId) {
listSparePartsChange({ partId: newVal.partId, pageNum: 1, pageSize: 1000 }).then(response => {
this.changes = response.rows;
})
}
},
deep: true
}
},
methods: {
/** 查询备品备件列表 */
getEquipmentList() {

View File

@@ -214,10 +214,11 @@ export default {
let currentX = margin; // 当前X坐标
let currentY = margin; // 当前Y坐标
let currentIndex = 0; // 当前处理的库位索引
const totalCount = this.warehouseList.length;
const list = this.warehouseList.filter(item => item.actualWarehouseCode.includes('X'));
const totalCount = list.length;
// 遍历所有库位生成二维码并添加到PDF
for (const [index, item] of this.warehouseList.entries()) {
for (const [index, item] of list.entries()) {
currentIndex = index;
// 跳过无ID的项