This commit is contained in:
Zzc 2025-11-13 18:01:11 +08:00
commit 723e7ddf40
8 changed files with 338 additions and 149 deletions

View File

@ -153,9 +153,10 @@
:key="material.rid" :key="material.rid"
v-model="material.usageAmount" v-model="material.usageAmount"
type="number" type="number"
@input="checkMaterialAmount(material, index)"
:label="material.wzmc" :label="material.wzmc"
center center
placeholder="请输入数量" :placeholder="`余额: ${material.ye} `"
> >
<template #extra> <template #extra>
<span style="margin-right: 10px">{{ material.dw }}</span> <span style="margin-right: 10px">{{ material.dw }}</span>
@ -493,6 +494,7 @@ const addSelectedMaterials = () => {
wzmc: material.wzmc, wzmc: material.wzmc,
usageAmount: null, usageAmount: null,
dw: material.dw, dw: material.dw,
ye: material.ye,
}); });
} }
}); });
@ -500,6 +502,18 @@ const addSelectedMaterials = () => {
checked.value = []; checked.value = [];
}; };
//
const checkMaterialAmount = (material, index) => {
if (material.usageAmount > material.ye) {
showToast({
type: "fail",
message: "输入数量不能超过物资余额",
});
//
form.yhzMaterialList[index].usageAmount = material.ye;
}
};
// //
const getMaterialList = async (wzmc) => { const getMaterialList = async (wzmc) => {
try { try {

View File

@ -15,8 +15,8 @@
<slot></slot> <slot></slot>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="onCancel">取消</el-button> <el-button @click="onCancel"> {{ onCancelName }} </el-button>
<el-button type="primary" @click="onConfirm"> 确认 </el-button> <el-button type="primary" @click="onConfirm"> {{ onConfirmName }} </el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@ -58,6 +58,14 @@ const props = defineProps({
type: Function, type: Function,
default: () => {}, default: () => {},
}, },
onConfirmName: {
type: String,
default: "确认",
},
onCancelName: {
type: String,
default: "取消",
}
}); });
const normalizedComponent = computed(() => const normalizedComponent = computed(() =>

View File

@ -0,0 +1,3 @@
import MyDrawer from './index.vue'
export default MyDrawer

View File

@ -0,0 +1,100 @@
<template>
<el-drawer
:visible.sync="visible"
:title="title"
:size="size"
:direction="direction"
destroy-on-close
>
<component
v-if="dynamicComponent"
:is="dynamicComponent"
ref="dynamicComponentRef"
v-bind="componentProps"
@vue:mounted="handleComponentMount"
/>
<template #footer>
<div class="drawer-footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" @click="onConfirm">确认</el-button>
</div>
</template>
</el-drawer>
</template>
<script setup>
import { computed, ref, markRaw } from "vue";
const dynamicComponentRef = ref(null);
defineExpose({
dynamicComponentRef,
});
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
size: {
type: String,
default: "50%",
},
direction: {
type: String,
default: "rtl", // rtl/ltr/ttb/btt
validator: (v) => ["rtl", "ltr", "ttb", "btt"].includes(v),
},
title: {
type: String,
default: "",
},
dynamicComponent: {
type: [Object, Function],
default: null,
},
componentProps: {
type: Object,
default: () => ({}),
},
onConfirm: {
type: Function,
default: () => {},
},
onCancel: {
type: Function,
default: () => {},
},
});
const emit = defineEmits(["update:visible"]);
//
const normalizedComponent = computed(() =>
props.dynamicComponent ? markRaw(props.dynamicComponent) : null
);
//
const handleClose = () => {
emit("update:visible", false);
};
// /
const onConfirm = () => {
props.onConfirm();
handleClose();
};
const onCancel = () => {
props.onCancel();
handleClose();
};
</script>
<style scoped>
.drawer-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
</style>

View File

@ -6,49 +6,49 @@
label-width="150px" label-width="150px"
style="max-height: 60vh; overflow-y: auto; padding-right: 50px" style="max-height: 60vh; overflow-y: auto; padding-right: 50px"
> >
<el-row :gutter="20"> <el-form-item label="所属服务站:">
<el-col :span="12"> <span>{{ yhzData.rawName }}</span>
<el-form-item label="物资名称:"> </el-form-item>
<el-input v-model="form.wzmc" /> <el-form-item label="物资名称:">
</el-form-item> <el-input
<el-form-item label="入库日期:"> maxlength="20"
<el-date-picker show-word-limit
type="date" v-model="form.material.wzmc"
placeholder="选择日期" ></el-input>
v-model="form.rkrq" </el-form-item>
/> <el-form-item label="数量与单位:">
</el-form-item> <el-row :gutter="20">
<el-form-item label="入库单位:"> <el-col :span="16">
<el-input v-model="form.rkdw" /> <el-input
</el-form-item> v-model="form.material.sl"
<el-row :gutter="20"> type="number"
<el-col :span="12"> placeholder="请输入数量"
<el-form-item label="数量:"> ></el-input>
<el-input-number v-model="form.sl" controls-position="right" /> </el-col>
</el-form-item> <el-col :span="8">
</el-col> <el-select
<el-col :span="12"> v-model="form.material.dw"
<el-form-item label="单位:"> filterable
<el-input v-model="form.dw" /> allow-create
</el-form-item> clearable
</el-col> placeholder="选择单位"
</el-row> >
</el-col> <el-option label="个" value="个"></el-option>
<el-col :span="12"> <el-option label="包" value="包"></el-option>
<el-form-item label="存放地点:"> <el-option label="盒" value="盒"></el-option>
<el-input v-model="form.cfdd" /> <el-option label="桶" value="桶"></el-option>
</el-form-item> <el-option label="箱" value="箱"></el-option>
<el-form-item label="负责人:"> <el-option label="袋" value="袋"></el-option>
<el-input v-model="form.fzr" /> </el-select>
</el-form-item> </el-col>
<el-form-item label="联系电话:"> </el-row>
<el-input v-model="form.lxdh" /> </el-form-item>
</el-form-item> <el-form-item label="设备经度:">
<el-form-item label="区县名称:"> <span>{{ yhzData.jd }}</span>
<el-input v-model="form.qxmc" /> </el-form-item>
</el-form-item> <el-form-item label="设备纬度:">
</el-col> <span>{{ yhzData.wd }}</span>
</el-row> </el-form-item>
</el-form> </el-form>
</div> </div>
</template> </template>
@ -59,7 +59,7 @@ const formRef = ref(null);
defineExpose({ formRef }); defineExpose({ formRef });
const props = defineProps({ const props = defineProps({
detailData: { yhzData: {
type: Object, type: Object,
default: () => ({}), default: () => ({}),
}, },

View File

@ -1,52 +1,68 @@
<template> <template>
<div class="detail-container"> <div class="detail-container">
<el-form <el-card shadow="hover">
label-position="right"
label-width="150px"
style="max-height: 60vh; overflow-y: auto; padding-right: 50px"
>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="物资名称:"> <el-descriptions title="基础信息" column="1">
<el-input disabled v-model="detailData.wzmc" /> <el-descriptions-item label="物资名称: ">{{
</el-form-item> detailData.material?.wzmc
<el-form-item label="余量:"> }}</el-descriptions-item>
<el-input disabled v-model="detailData.ye" /> <el-descriptions-item label="余量: ">{{
</el-form-item> detailData.material?.ye + ' ' + detailData.material?.dw
<el-form-item label="入库日期:"> }}</el-descriptions-item>
<el-input disabled v-model="detailData.rkrq" /> <el-descriptions-item label="所属服务站: ">{{
</el-form-item> detailData.material?.yhzMc
<el-form-item label="入库单位:"> }}</el-descriptions-item>
<el-input disabled v-model="detailData.rkdw" /> <el-descriptions-item label="备注: ">{{
</el-form-item> detailData.material?.remark
<el-row :gutter="20"> }}</el-descriptions-item>
<el-col :span="12"> </el-descriptions>
<el-form-item label="数量:">
<el-input disabled v-model="detailData.sl"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单位:">
<el-input disabled v-model="detailData.dw" /> </el-form-item
></el-col>
</el-row>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12" style="position: relative">
<el-form-item label="存放地点:"> <el-image
<el-input disabled v-model="detailData.cfdd" /> style="
</el-form-item> max-width: 180px;
<el-form-item label="负责人:"> max-height: 180px;
<el-input disabled v-model="detailData.fzr" /> position: absolute;
</el-form-item> right: 0;
<el-form-item label="联系电话:"> "
<el-input disabled v-model="detailData.lxdh" /> :src="detailData.photos[0]?.photoUrl"
</el-form-item> :zoom-rate="1.2"
<el-form-item label="区县名称:"> :max-scale="7"
<el-input disabled v-model="detailData.qxmc" /> :min-scale="0.2"
</el-form-item> :preview-src-list="detailData.photos?.map((item) => item.photoUrl)"
show-progresss
fit="cover"
/>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-card>
<el-card shadow="hover">
<el-descriptions title="物资位置信息" column="3">
<el-descriptions-item label="区县名称: ">{{
detailData.material?.qxmc
}}</el-descriptions-item>
<el-descriptions-item label="物资经度: ">{{
detailData.material?.jd
}}</el-descriptions-item>
<el-descriptions-item label="物资纬度: ">{{
detailData.material?.wd
}}</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card shadow="hover">
<el-descriptions title="物资管理情况" column="3">
<el-descriptions-item label="负责人: ">{{
detailData.material?.fzr
}}</el-descriptions-item>
<el-descriptions-item label="入库人: ">{{
detailData.material?.rkrName
}}</el-descriptions-item>
<el-descriptions-item label="入库日期: ">{{
detailData.material?.rkrq?.slice(0, 10)
}}</el-descriptions-item>
</el-descriptions>
</el-card>
</div> </div>
</template> </template>
@ -60,4 +76,9 @@ const props = defineProps({
</script> </script>
<style> <style>
.detail-container {
display: flex;
flex-direction: column;
gap: 30px;
}
</style> </style>

View File

@ -16,6 +16,7 @@ const filterText = ref(''); // 树节点过滤条件
const tableData = ref([]); const tableData = ref([]);
const qxmc = ref(''); // 区县名称 const qxmc = ref(''); // 区县名称
const yhzid = ref(''); // 养护站id const yhzid = ref(''); // 养护站id
const yhzData = ref(); // 养护站信息
const filterData = reactive({ const filterData = reactive({
wzmc: '', wzmc: '',
}); // 表格过滤条件 }); // 表格过滤条件
@ -42,22 +43,53 @@ const model = reactive({
const dialogType = ref(''); // 弹窗类型 const dialogType = ref(''); // 弹窗类型
const dialogRef = ref(null); // 弹窗实例 const dialogRef = ref(null); // 弹窗实例
const drawerVisible = ref(false); // 抽屉显示状态
const drawer = reactive({
title: '',
content: null,
props: {},
onCancel: null,
onConfirm: null,
direction: 'rtl',
size: '50%'
}); // 抽屉内容
const drawerType = ref(''); // 抽屉类型
const drawerRef = ref(null); // 抽屉实例
const INIT_FORM = { const INIT_FORM = {
rkrq: "", material: {
rkdw: "", rkrq: "",
sl: "", rkdw: "",
dw: "", sl: "",
cfdd: "", dw: "",
fzr: "", cfdd: "",
lxdh: "", fzr: "",
ye: "", lxdh: "",
qxmc: "", ye: "",
wzmc: "", qxmc: "",
fzrid: "", wzmc: "",
yhzid: "", fzrid: "",
yhzid: "",
jd: "",
wd: "",
},
photos: [],
}; // 表单初始值 }; // 表单初始值
const form = reactive({ ...INIT_FORM }); // 表单 const form = reactive({ ...INIT_FORM }); // 表单
// 重置表单方法
const resetForm = () => {
// 深拷贝重置嵌套对象
form.material = { ...INIT_FORM.material };
form.photos = [...INIT_FORM.photos];
form.material.yhzid = yhzid.value;
form.material.jd = yhzData.value?.jd;
form.material.wd = yhzData.value?.wd;
};
// 节点过滤函数 // 节点过滤函数
@ -96,7 +128,10 @@ const getTreeData = async () => {
children: qx.yhzList.map(site => ({ children: qx.yhzList.map(site => ({
id: site.id, id: site.id,
name: `${site.mc}(${site.wzsl})`, name: `${site.mc}(${site.wzsl})`,
type: 'site' type: 'site',
rawName: site.mc, // 原始名称
jd: site.jd,
wd: site.wd,
})), })),
rawName: qx.qxmc, // 原始名称 rawName: qx.qxmc, // 原始名称
}) })
@ -116,18 +151,21 @@ const handleNodeClick = (data, node) => {
if (data.type === 'area' && node.expanded === false) { if (data.type === 'area' && node.expanded === false) {
console.log('树节点关闭', node.expanded) console.log('树节点关闭', node.expanded)
yhzid.value = ''; // 重置养护站id yhzid.value = ''; // 重置养护站id
yhzData.value = null; // 重置养护站信息
qxmc.value = ''; // 重置区县名称 qxmc.value = ''; // 重置区县名称
return; return;
} }
if (data.type === 'area') { if (data.type === 'area') {
console.log('你点击的是区县', data.id) console.log('你点击的是区县', data.id)
yhzid.value = ''; // 重置养护站id yhzid.value = ''; // 重置养护站id
yhzData.value = null; // 重置养护站信息
qxmc.value = data.id; // 保存区县名称 qxmc.value = data.id; // 保存区县名称
} }
if (data.type === 'site') { if (data.type === 'site') {
console.log('你点击的是站点', data.name) console.log('你点击的是站点', data.name)
yhzid.value = data.id; // 保存养护站id yhzid.value = data.id; // 保存养护站id
yhzData.value = data; // 保存养护站信息
qxmc.value = ''; // 重置区县名称 qxmc.value = ''; // 重置区县名称
} }
}; };
@ -170,37 +208,25 @@ const columns = [
prop: 'ye', prop: 'ye',
label: '余量', label: '余量',
}, },
{
prop: 'rkdw',
label: '入库单位',
},
{
prop: 'rkrq',
label: '入库日期',
},
{
prop: 'sl',
label: '数量',
},
{ {
prop: 'dw', prop: 'dw',
label: '单位', label: '单位',
}, },
{
prop: 'cfdd',
label: '存放地点',
},
{ {
prop: 'fzr', prop: 'fzr',
label: '负责人', label: '负责人',
}, },
{ {
prop: 'lxdh', prop: 'rkrName',
label: '联系电话', label: '入库人',
}, },
{ {
prop: 'qxmc', prop: 'rkrq',
label: '所属区县', label: '入库日期',
},
{
prop: 'yhzMc',
label: '所属服务站',
}, },
{ {
label: "操作", label: "操作",
@ -220,18 +246,18 @@ const columns = [
}, },
() => "详情" () => "详情"
), ),
h( // h(
ElButton, // ElButton,
{ // {
type: "primary", // type: "primary",
link: true, // link: true,
onClick: async () => { // onClick: async () => {
dialogType.value = 'edit' // dialogType.value = 'edit'
await getDetailData(row); // await getDetailData(row);
}, // },
}, // },
() => "编辑" // () => "编辑"
), // ),
h( h(
ElButton, ElButton,
{ {
@ -305,20 +331,20 @@ const getDetailData = async (row) => {
} }
if (res.code === '00000') { if (res.code === '00000') {
if (dialogType.value === 'detail') { if (dialogType.value === 'detail') {
model.title = `物资详情`; drawer.title = `物资详情`;
model.content = DetailDialog; drawer.content = DetailDialog;
model.props = { drawer.props = {
detailData: res.data.material, detailData: res.data,
}; };
model.onCancel = () => { drawer.onCancel = () => {
dialogType.value = ''; dialogType.value = '';
modelVisible.value = false; drawerVisible.value = false;
}; };
model.onConfirm = () => { drawer.onConfirm = () => {
dialogType.value = ''; dialogType.value = '';
modelVisible.value = false; drawerVisible.value = false;
}; };
modelVisible.value = true; drawerVisible.value = true;
} }
if (dialogType.value === 'edit') { if (dialogType.value === 'edit') {
model.title = `编辑物资`; model.title = `编辑物资`;
@ -352,9 +378,9 @@ const getDetailData = async (row) => {
const openAddModel = () => { const openAddModel = () => {
model.title = `新增物资`; model.title = `新增物资`;
model.content = AddDialog; model.content = AddDialog;
Object.assign(form, INIT_FORM); resetForm(); // 重置表单
model.props = { model.props = {
detailData: {}, yhzData: yhzData.value,
form: form, form: form,
}; };
model.onCancel = () => { model.onCancel = () => {
@ -382,6 +408,7 @@ const openAddModel = () => {
console.log('error', error) console.log('error', error)
} }
}; };
model.width = '40%';
modelVisible.value = true; modelVisible.value = true;
} }
@ -441,7 +468,7 @@ export default () => {
await getTreeData(); await getTreeData();
await getyhzwzList(); await getyhzwzList();
const rowData = (decodeURIComponent(route.params?.data)); const rowData = (decodeURIComponent(route.params?.data));
if (rowData !== 'undefined' && rowData!== 'null' && rowData !== '' ) { if (rowData !== 'undefined' && rowData !== 'null' && rowData !== '') {
const JSONData = JSON.parse(rowData); const JSONData = JSON.parse(rowData);
filterText.value = JSONData.mc; filterText.value = JSONData.mc;
}; };
@ -462,5 +489,9 @@ export default () => {
dialogRef, dialogRef,
model, model,
openAddModel, openAddModel,
drawerVisible,
drawer,
drawerRef,
yhzid,
} }
} }

View File

@ -28,7 +28,7 @@
</div> </div>
<div class="form-box"> <div class="form-box">
<div class="event-box"> <div class="event-box">
<el-button type="primary" size="large" @click="script.openAddModel" <el-button v-if="script.yhzid.value" type="primary" size="large" @click="script.openAddModel"
>新增物资</el-button >新增物资</el-button
> >
<el-button type="info" size="large" @click="script.handelExport" <el-button type="info" size="large" @click="script.handelExport"
@ -54,9 +54,20 @@
:onConfirm="script.model?.onConfirm" :onConfirm="script.model?.onConfirm"
:onCancel="script.model?.onCancel" :onCancel="script.model?.onCancel"
ref="dialogRef" ref="dialogRef"
width="60%" :width="script.model?.width"
> >
</MyDialog> </MyDialog>
<MyDrawer
v-model="script.drawerVisible.value"
:title="script.drawer?.title"
:dynamicComponent="script.drawer?.content"
:component-props="script.drawer?.props"
:onConfirm="script.drawer?.onConfirm"
:onCancel="script.drawer?.onCancel"
ref="drawerRef"
:direction="script.drawer?.direction"
:size="script.drawer?.size"
></MyDrawer>
</div> </div>
</div> </div>
</template> </template>
@ -65,9 +76,10 @@
import scriptFn from "./index.js"; import scriptFn from "./index.js";
import DynamicTable from "../../component/DynamicTable"; import DynamicTable from "../../component/DynamicTable";
import MyDialog from "../../component/MyDialog"; import MyDialog from "../../component/MyDialog";
import MyDrawer from "../../component/MyDrawer/index.js";
const script = scriptFn(); const script = scriptFn();
const { treeRef, dialogRef } = script; const { treeRef, dialogRef, drawerRef } = script;
</script> </script>
<style scoped> <style scoped>
.root { .root {