Files
ba_web/src/views/backOfficeSystem/basicsmanage/watchman-zb/police-equipment/index.vue
2025-09-26 12:56:52 +08:00

1070 lines
27 KiB
Vue

<template>
<div>
<div class="titleBox">
<div class="title">常用装备管理</div>
<div class="btnBox">
<el-button
type="primary"
@click="addLoad"
>
<el-icon style="vertical-align: middle">
<CirclePlus />
</el-icon>
<span style="vertical-align: middle">新增</span>
</el-button>
<el-button
@click="deletList"
:disabled="multipleSelection.length == 0"
typeof="danger"
>
<el-icon style="vertical-align: middle">
<Delete />
</el-icon>
<span style="vertical-align: middle">批量删除</span>
</el-button>
<el-button type="info" plain icon="Upload" @click="isImport = true">
<span style="vertical-align: middle">导入</span>
</el-button>
</div>
</div>
<div
class="searchBox"
ref="searchBox"
>
<el-form
class="mosty-from-wrap"
:model="listQuery"
:inline="true"
>
<el-form-item label="所属部门">
<MOSTY.Department
width="100%"
clearable
v-model="listQuery.ssbmdm"
/>
</el-form-item>
<el-form-item label="器械类型">
<el-select
v-model="listQuery.scode"
class="m-2"
placeholder="请选择器械类型"
>
<el-option
v-for="item in D_BZ_JYQXFL"
:label="item.label"
:key="item.value"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="装备名称">
<el-input v-model="listQuery.qxMc" placeholder="请输入装备名称"></el-input>
</el-form-item>
<el-form-item label="生产日期">
<el-date-picker
v-model="listQuery.cgrq"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
type="date"
placeholder="请选择日期"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
@selection-change="handleSelectionChange"
:data="tableData"
border
ref="dataTreeList"
row-key="id"
:tree-props="{ children: 'itemList', hasChildren: true }"
:height="tableHeight"
:key="keyCount"
v-loading="loadingTable"
element-loading-background="rgba(0,0,0,0.3)"
element-loading-text="数据加载中"
>
<el-table-column
align="center"
type="selection"
width="55"
/>
<el-table-column
type="index"
show-overflow-tooltip
align="center"
width="60px"
label="序号"
>
</el-table-column>
<el-table-column width="120" align="center" label="图片">
<template #default="{ row }">
<div class="phone">
<el-image v-if="row.tpid" :src="urlImg + row.tpid" fit="cover" lazy />
<el-image v-else :src="Person" fit="cover" lazy />
</div>
</template>
</el-table-column>
<el-table-column
prop="ssbm"
label="所属部门"
align="center"
></el-table-column>
<el-table-column
prop="scode"
show-overflow-tooltip
align="center"
label="器械类型"
>
<template #default="{ row }">
<dict-tag
:options="D_BZ_JYQXFL"
:value="row.scode"
:tag="false"
/>
</template>
</el-table-column>
<el-table-column
prop="qxMc"
show-overflow-tooltip
align="center"
label="器械名称"
>
</el-table-column>
<el-table-column
prop="qxbh"
show-overflow-tooltip
align="center"
label="器械型号"
>
</el-table-column>
<el-table-column
prop="cgrq"
show-overflow-tooltip
label="生产日期"
align="center"
>
</el-table-column>
<el-table-column
prop="qxPch"
show-overflow-tooltip
label="录入批次"
align="center"
>
</el-table-column>
<el-table-column
label="数量"
align="center"
prop="sl"
>
</el-table-column>
<el-table-column
label="状态"
align="center"
>
<template #default="{ row }">
<dict-tag
:value="row.zbzt"
:options="D_ZDY_SBZT"
></dict-tag>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
fixed="right"
width="180px"
>
<template #default="{ row }">
<el-button
@click="update(row.id)"
size="small"
>修改</el-button>
<!-- <el-button
type="warning"
size="small"
@click="handleReportLoss(row)"
>报损</el-button> -->
<!-- <el-button
type="warning"
size="small"
v-if="row.xfid"
@click="handelRellBack(row)"
>回退</el-button>
<el-button
type="success"
size="small"
@click="handleLssued(row)"
>下发</el-button> -->
<el-button
@click="delDictItem(row.id)"
type="danger"
size="small"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<div
class="fenye"
:style="{ top: tableHeight + 'px' }"
>
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageNo"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
<div
v-if="dialogFormVisible"
class="dialog"
>
<div class="head_box">
<span class="title">{{ diaTitle }}</span>
<div>
<el-button
type="primary"
:loading="btnLoading"
size="small"
@click="submit"
>保存</el-button>
<el-button
size="small"
@click="dialogFormVisible = false"
>关闭</el-button>
</div>
</div>
<el-form
ref="elform"
:model="form"
:rules="rules"
:inline="true"
label-position="top"
>
<div
style="
width: 25%;
display: flex;
justify-content: center;
margin-bottom: 10px;
"
>
<div style="position: relative; width: 90px; height: 100px">
<el-upload
action="/bagl/mosty-base/minio/image/upload/id"
:on-change="upImgFile"
:on-success="upImg"
:show-file-list="false"
>
<el-image v-if="imgUrl" :src="imgUrl" fit="cover" />
<el-icon v-else><Plus></Plus></el-icon>
<span
v-if="imgUrl"
style="position: absolute; top: -52px; right: -20px"
>
<el-icon size="20" @click.stop="deletImg"><Close /></el-icon>
</span>
</el-upload>
</div>
</div>
<el-form-item prop="ssbmdm" label="所属部门">
<MOSTY.Department
:placeholder="form.ssbm"
style="width: 100%"
ref="cascader"
clearable
filterable
:options="depList"
:props="props"
v-model="form.ssbmdm"
/>
</el-form-item>
<el-form-item
prop="scode"
label="器械类型"
>
<el-select
v-model="form.scode"
class="m-2"
placeholder="请选择"
style="width: 100%"
>
<el-option
v-for="item in D_BZ_JYQXFL"
:label="item.label"
:key="item.value"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
prop="zbzt"
label="器械状态"
>
<el-select
v-model="form.zbzt"
class="m-2"
placeholder="请选择"
style="width: 100%"
>
<el-option
v-for="item in D_ZDY_SBZT"
:label="item.label"
:key="item.value"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
prop="qxMc"
label="器械名称"
>
<el-input
v-model="form.qxMc"
placeholder="请填写器械名称"
clearable
style="width: 100%"
/>
</el-form-item>
<el-form-item
prop="qxbh"
label="器械型号"
>
<el-input
v-model="form.qxbh"
placeholder="请输入器械型号"
clearable
style="width: 100%"
/>
</el-form-item>
<el-form-item
prop="qxPch"
label="录入批次"
>
<el-input
v-model="form.qxPch"
placeholder="请输入录入批次"
></el-input>
</el-form-item>
<el-form-item
prop="cgrq"
label="生产日期"
>
<el-date-picker
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
v-model="form.cgrq"
type="date"
placeholder="请选择日期"
style="width: 100%"
:disabledDate="disableCgrq"
/>
</el-form-item>
<el-form-item
prop="dqsj"
label="到期日期"
>
<el-date-picker
@focus="cgrqTs"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
v-model="form.dqsj"
type="date"
placeholder="请选择日期"
style="width: 100%"
:disabledDate="disableDqsj"
/>
</el-form-item>
<el-form-item
prop="sl"
label="器械数量"
>
<el-input-number
style="width: 100%"
:step="1"
v-model="form.sl"
:min="1"
/>
</el-form-item>
<el-form-item
prop="sccs"
label="器械厂商"
>
<el-input
v-model="form.sccs"
placeholder="请输入器械厂商"
clearable
style="width: 100%"
/>
</el-form-item>
<el-form-item
label="备注"
style="width: 100%"
>
<el-input
v-model="form.bz"
placeholder="请输入关键字"
show-word-limit
type="textarea"
/>
</el-form-item>
</el-form>
</div>
<!-- 下发弹窗口 -->
<el-dialog
title="选择下发单位"
width="600px"
:model-value="lssuedDialog"
:close-on-click-modal="false"
:destroy-on-close="true"
@close="lssuedDialog = false"
>
<el-form
:model="lssuedForm"
ref="lssued"
:rules="ruleslssued"
>
<el-form-item
label="选择大队"
prop="ssbmdm"
>
<MOSTY.Department
width="100%"
clearable
v-model="lssuedForm.ssbmdm"
/>
</el-form-item>
<el-form-item
label="选择数量"
prop="sl"
>
<el-input
v-model="lssuedForm.sl"
placeholder="请选择数量"
clearable
style="width: 100%"
/>
</el-form-item>
<div class="footerBtn">
<el-button
@click="okLssued"
:loading="reportLossLoading"
>
确定下发
</el-button>
</div>
</el-form>
</el-dialog>
<!-- 报损 -->
<el-dialog
title="报损"
width="600px"
:model-value="reportLossDialog"
:close-on-click-modal="false"
:destroy-on-close="true"
@close="reportLossDialog = false"
>
<el-form
:model="reportLossForm"
ref="reportLoss"
:rules="ruleReportLoss"
>
<el-form-item
label="选择数量"
prop="sl"
>
<el-input
v-model="reportLossForm.sl"
placeholder="请选择数量"
clearable
style="width: 100%"
:rules="[{ required: true, message: '选择数量', trigger: 'blur' }]"
/>
</el-form-item>
<div class="footerBtn">
<el-button
@click="okreportLoss"
:loading="reportLossLoading"
>
确定报损
</el-button>
</div>
</el-form>
</el-dialog>
<!-- 回退 -->
<el-dialog
title="回退"
width="1000px"
:model-value="rellbackDialog"
:close-on-click-modal="false"
:destroy-on-close="true"
@close="rellbackDialog = false"
>
<el-table
border
:data="DataRellback"
width="100%"
element-loading-background="rgba(0,0,0,0.3)"
>
<el-table-column
label="装备信息"
align="center"
>
<el-table-column
label="单位名称"
prop="ssxgaj"
align="center"
></el-table-column>
<el-table-column
label="库存"
prop="sl"
align="center"
></el-table-column>
<el-table-column
label="报损"
prop="bss"
align="center"
></el-table-column>
<el-table-column
label="下发"
prop="xfs"
align="center"
></el-table-column>
</el-table-column>
<el-table-column
label=""
width="100"
/>
<el-table-column
label="回退信息"
align="center"
>
<el-table-column
label="库存"
prop="kc"
align="center"
width="136px"
>
<template #default="{ row }">
<el-input-number
v-model="RellbackData.sl"
:min="0"
:max="row.sl"
size="small"
></el-input-number>
</template>
</el-table-column>
<el-table-column
label="报损"
prop="bs"
align="center"
width="136px"
>
<template #default="{ row }">
<el-input-number
v-model="RellbackData.bss"
:min="0"
:max="row.bss"
size="small"
></el-input-number>
</template>
</el-table-column>
<el-table-column
label="下发"
prop="xf"
align="center"
width="136px"
>
<template #default="{ row }">
<el-input-number
v-model="RellbackData.xfs"
:min="0"
:max="row.xfs"
size="small"
></el-input-number>
</template>
</el-table-column>
</el-table-column>
</el-table>
<div class="footerBtn">
<el-button @click="okRellback"> 确定回退 </el-button>
</div>
</el-dialog>
<!-- 导入 -->
<Export
:show="isImport"
lx="jyqx"
@closeImport="isImport = false"
@handleImport="handleFilter"
/>
</div>
</template>
<script setup>
import Export from "@/components/export/index.vue";
import { selectDeptPage, getUserInfoToId } from "@/api/user-manage";
import * as MOSTY from "@/components/MyComponents/index";
import { getTree } from "@/api/basicsmanage/watchmanZbgl";
import {
getJyqx,
addJyqx,
putJyqx,
infoJyqx,
delJyqx,
lssuedJyzb,
RellBackJyzb,
ReportLossjYzb
} from "@/api/basicsmanage/equipment";
import Person from "@/assets/images/default_male.png";
import { ref, reactive, onMounted, getCurrentInstance, onUnmounted } from "vue";
const urlImg = ref("/bagl/mosty-base/minio/image/download/");
const multipleSelection = ref([]); //批量数据
const { proxy } = getCurrentInstance();
const isImport = ref(false);
const chackipt = ref(true);
const cascader = ref(null);
const loadingTable = ref(true);
const { D_BZ_JYQXFL, D_ZDY_SBZT } = proxy.$dict("D_BZ_JYQXFL", "D_ZDY_SBZT");
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const keyCount = ref(0); //tabel组件刷新值
const dialogFormVisible = ref(false); //是否显示新增弹窗
const disable = ref(false);
const chackadd = ref(true); //切换新增修改
const diaTitle = ref("");
const options = ref([]);
const depList = ref([]); //部门数据
const imgUrl = ref("");
const lssuedDialog = ref(false); //下发弹窗
const lssued = ref(null);
const lssuedForm = ref({ ssbmdm: "", sl: "1" }); //下发弹窗表单
const ruleslssued = reactive({
ssbmdm: [{ required: true, message: "请选择部门", trigger: "change" }],
sl: [{ required: true, message: "请选择数量", trigger: "change" }]
});
const reportLoss = ref(null);
const reportLossLoading = ref(false);
const reportLossDialog = ref(false); // 报损弹窗
const reportLossForm = ref({ sl: "" }); // 报损弹窗表单
const ruleReportLoss = reactive({
sl: [{ required: true, message: "请选择数量", trigger: "change" }]
});
const rellbackDialog = ref(false); //回退弹窗
const DataRellback = ref([]); //回退数据
const RellbackData = ref({
sl: 0,
bss: 0,
xfs: 0
});
//级联选择器配置
const props = {
expandTrigger: "children",
children: "childDeptList",
label: "orgName",
value: "orgCode",
checkStrictly: true,
emitPath: false
};
const btnLoading = ref(false);
//获取装备类型树
function getzbtree() {
getTree("ZB0002").then((res) => {
options.value = res[0].children;
});
}
const listQuery = ref({
pageNo: 1,
pageSize: 20,
ssbmdm: "",
scode: "",
gzrq: ""
});
function focusF() {
chackipt.value = false;
}
// 处理下发
function handleLssued(row) {
lssuedDialog.value = true;
lssuedForm.value.id = row.id;
}
// 提交下发
function okLssued() {
lssued.value.validate((valid) => {
if (!valid) return false;
reportLossLoading.value = true;
lssuedJyzb(lssuedForm.value)
.then((res) => {
proxy.$message({ type: "success", message: "下发成功" });
lssuedForm.value.ssbmdm = "";
lssuedForm.value.id = "";
lssuedDialog.value = false;
reportLossLoading.value = false;
handleFilter();
})
.catch(() => {
reportLossLoading.value = false;
});
});
}
// 报损
function handleReportLoss(row) {
reportLossDialog.value = true;
reportLossForm.value.id = row.id;
}
// 确定报损
function okreportLoss() {
reportLoss.value.validate((valid) => {
if (!valid) return false;
reportLossLoading.value = true;
ReportLossjYzb(reportLossForm.value)
.then((res) => {
proxy.$message({ type: "success", message: "报损成功" });
reportLossForm.value.sl = "";
reportLossForm.value.id = "";
reportLossDialog.value = false;
reportLossLoading.value = false;
handleFilter();
})
.catch(() => {
reportLossLoading.value = false;
});
});
}
// 处理回退
function handelRellBack(row) {
rellbackDialog.value = true;
DataRellback.value = [row];
RellbackData.value.sl = row.sl;
RellbackData.value.bss = row.bss;
RellbackData.value.xfs = row.xfs;
RellbackData.value.id = row.id;
}
// 处理回退提交
function okRellback() {
RellBackJyzb(RellbackData.value).then((res) => {
proxy.$message({ type: "success", message: "回退成功" });
rellbackDialog.value = false;
RellbackData.value.sl = "";
RellbackData.value.bss = "";
RellbackData.value.xfs = "";
RellbackData.value.id = "";
handleFilter();
});
}
onMounted(() => {
selectDeptPage({}).then((res) => {
depList.value = res.records;
});
getListData();
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
//生产日期限制
function disableCgrq(row) {
let time = new Date();
return time.getTime() <= row.getTime();
}
// 到期日期限制
function disableDqsj(row) {
if (form.value.cgrq) {
let time = new Date(form.value.cgrq);
return time.getTime() >= row.getTime();
} else {
return true;
}
}
function cgrqTs() {
if (!form.value.cgrq) {
proxy.$message({
message: "请先选择生产日期",
type: "warning"
});
}
}
const tableData = ref([]); //表单数据
const total = ref(0); //总数据
//新增表单对象
const form = ref({
sl: 1,
ssbmdm: "",
scode: "",
qxMc: "",
qxbh: "",
qxPch: "",
dqsj: "",
sccs: "",
cgrq: ""
});
//表单验证
const rules = reactive({
ssbmdm: [{ required: true, message: "请选择部门", trigger: "change" }],
scode: [{ required: true, message: "请选择器械类型", trigger: "change" }],
qxMc: [{ required: true, message: "请填写器械名称", trigger: "change" }],
qxbh: [{ required: true, message: "请填写器械型号", trigger: "blur" }],
qxPch: [{ required: true, message: "请输入录入批次", trigger: "change" }],
dqsj: [{ required: true, message: "请选择到期日期", trigger: "change" }],
cgrq: [{ required: true, message: "请选择生产日期", trigger: "change" }],
wxsl: [{ required: true, message: "器械数量", trigger: "change" }]
});
const handleFilter = () => {
listQuery.value.pageNo = 1;
getListData();
};
function update(id) {
infoJyqx(id).then((res) => {
disable.value = false;
chackadd.value = true;
diaTitle.value = "常用装备修改";
form.value = res;
form.value.ssbmdm = form.value.ssbmdm * 1;
dialogFormVisible.value = true;
imgUrl.value = res.tpid ? urlImg.value + res.tpid : "";
});
}
//重置表单
function formReset() {
form.value = {
sl: 1
};
}
function changCode(scode) {
let sname = "";
options.value.forEach((v) => {
if (v.scode === scode) {
sname = v.sname;
}
});
return sname;
}
function addLoad() {
chackipt.value = false;
formReset();
disable.value = false;
chackadd.value = false;
diaTitle.value = "新增常用装备";
dialogFormVisible.value = true;
}
//获取数据
const getListData = () => {
loadingTable.value = true;
const params = listQuery.value;
getJyqx(params)
.then((res) => {
if (res.records) {
res.records.forEach((item) => {
item.kc =
item.sl - item.bss - item.xfs < 0
? 0
: item.sl - item.bss - item.xfs;
});
tableData.value = res.records;
}
total.value = res.total;
loadingTable.value = false;
})
.catch(() => {
loadingTable.value = false;
});
};
const reset = () => {
listQuery.value = {
pageNo: 1,
pageSize: 20,
zbName: "",
zbCode: "",
xtZxbz: ""
};
getListData();
};
const elform = ref(null);
//提交
function submit() {
elform.value.validate((valid) => {
if (valid) {
btnLoading.value = true;
if (chackadd.value) {
putJyqx(form.value)
.then(() => {
proxy.$message({ type: "success", message: "修改成功" });
dialogFormVisible.value = false;
btnLoading.value = false;
getListData();
})
.catch(() => {
btnLoading.value = false;
});
} else {
addJyqx(form.value)
.then(() => {
proxy.$message({ type: "success", message: "新增成功" });
dialogFormVisible.value = false;
btnLoading.value = false;
getListData();
})
.catch(() => {
btnLoading.value = false;
});
}
}
});
}
function upImgFile(row) {}
function upImg(row) {
form.value.tpid = row.data;
imgUrl.value = urlImg.value + row.data;
}
function deletImg() {
imgUrl.value = "";
form.value.tpid = "";
}
//删除
function delDictItem(id) {
proxy
.$confirm("确定要删除", "警告", {
type: "warning"
})
.then(() => {
const ids = [id];
delJyqx(ids).then(() => {
proxy.$message({
type: "success",
message: "删除成功"
});
getListData();
});
})
.catch(() => {
proxy.$message.info("已取消");
});
}
//批量数据
const handleSelectionChange = (val) => {
multipleSelection.value = [];
if (val) {
val.forEach((item) => {
multipleSelection.value.push(item.id);
});
}
};
//批量删除
const deletList = () => {
proxy
.$confirm("确定要删除", "警告", {
type: "warning"
})
.then(() => {
const ids = multipleSelection.value;
delJyqx(ids).then(() => {
proxy.$message({
type: "success",
message: "删除成功"
});
getListData();
});
})
.catch(() => {
proxy.$message.info("已取消");
});
};
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageNo = currentPage;
getListData();
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.footerBtn {
text-align: right;
margin: 4px 0;
}
::v-deep .el-table thead.is-group th.el-table__cell {
background: #062d67;
}
::v-deep .el-radio-button__inner {
border: 1px solid #1446bc;
color: #fff;
}
::v-deep .el-radio-button:first-child .el-radio-button__inner {
border: 1px solid #1446bc;
}
.phone {
width: 95px;
height: 120px;
.el-image {
width: 95px;
max-height: 120px;
}
}
::v-deep .el-upload {
width: 90px;
height: 100px;
border: 1px dashed #e0e0e0;
margin-bottom: 14px;
.el-icon {
margin-top: 34px;
font-size: 26px;
}
.el-image {
width: 100%;
height: 100%;
}
}
</style>