From 41c7dd199f1919a01dfc5e04f62359ca8bc3cb2c Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期六, 12 九月 2026 12:43:32 +0800
Subject: [PATCH] feat: 库存管理三表单与详情页签分组、采购台账分栏、油品联动与电话校验、冻结解冻修复
---
src/views/inventoryManagement/stockManagement/New.vue | 175 +-
src/views/procurementManagement/procurementLedger/index.vue | 297 +++++
src/api/basicData/oilDepot.js | 53 +
src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue | 225 ++++
src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue | 127 +-
src/views/inventoryManagement/stockManagement/OilStockInDialog.vue | 791 ++++++++++++++
src/views/inventoryManagement/stockManagement/OilStockOutDialog.vue | 759 ++++++++++++++
src/views/inventoryManagement/stockManagement/Record.vue | 31
src/views/basicData/oilDepot/index.vue | 297 +++++
src/api/basicData/tankInfo.js | 53 +
src/api/inventoryManagement/stockInventory.js | 9
src/views/basicData/tankInfo/index.vue | 324 ++++++
12 files changed, 2,968 insertions(+), 173 deletions(-)
diff --git a/src/api/basicData/oilDepot.js b/src/api/basicData/oilDepot.js
new file mode 100644
index 0000000..4a0b7bb
--- /dev/null
+++ b/src/api/basicData/oilDepot.js
@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 鍒嗛〉鏌ヨ娌瑰簱淇℃伅鍒楄〃
+export function listOilDepot(query) {
+ return request({
+ url: '/basic/oilDepot/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ鍏ㄩ儴娌瑰簱淇℃伅锛堜緵涓嬫媺閫夋嫨锛�
+export function allOilDepot() {
+ return request({
+ url: '/basic/oilDepot/all',
+ method: 'get'
+ })
+}
+
+// 鏌ヨ娌瑰簱淇℃伅璇︽儏
+export function getOilDepot(id) {
+ return request({
+ url: '/basic/oilDepot/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板娌瑰簱淇℃伅
+export function addOilDepot(data) {
+ return request({
+ url: '/basic/oilDepot/add',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼娌瑰簱淇℃伅
+export function updateOilDepot(data) {
+ return request({
+ url: '/basic/oilDepot/update',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鍒犻櫎娌瑰簱淇℃伅
+export function delOilDepot(ids) {
+ return request({
+ url: '/basic/oilDepot/del',
+ method: 'delete',
+ data: ids
+ })
+}
diff --git a/src/api/basicData/tankInfo.js b/src/api/basicData/tankInfo.js
new file mode 100644
index 0000000..ce086b3
--- /dev/null
+++ b/src/api/basicData/tankInfo.js
@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 鍒嗛〉鏌ヨ鍌ㄧ綈淇℃伅鍒楄〃
+export function listTankInfo(query) {
+ return request({
+ url: '/basic/tankInfo/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ鍏ㄩ儴鍌ㄧ綈淇℃伅锛堜緵涓嬫媺閫夋嫨锛�
+export function allTankInfo() {
+ return request({
+ url: '/basic/tankInfo/all',
+ method: 'get'
+ })
+}
+
+// 鏌ヨ鍌ㄧ綈淇℃伅璇︽儏
+export function getTankInfo(id) {
+ return request({
+ url: '/basic/tankInfo/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板鍌ㄧ綈淇℃伅
+export function addTankInfo(data) {
+ return request({
+ url: '/basic/tankInfo/add',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼鍌ㄧ綈淇℃伅
+export function updateTankInfo(data) {
+ return request({
+ url: '/basic/tankInfo/update',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鍒犻櫎鍌ㄧ綈淇℃伅
+export function delTankInfo(ids) {
+ return request({
+ url: '/basic/tankInfo/del',
+ method: 'delete',
+ data: ids
+ })
+}
diff --git a/src/api/inventoryManagement/stockInventory.js b/src/api/inventoryManagement/stockInventory.js
index 539eedc..44d28af 100644
--- a/src/api/inventoryManagement/stockInventory.js
+++ b/src/api/inventoryManagement/stockInventory.js
@@ -61,6 +61,15 @@
});
};
+// 鏂板娌瑰搧鍑哄簱璁板綍锛堟补鍝佸嚭搴撲笓鐢ㄨ〃鍗曪紝浠呭垱寤鸿褰曪紝涓嶈皟鏁村簱瀛橈級
+export const addOilOutRecordOnly = (params) => {
+ return request({
+ url: "/stockInventory/addOilOutRecordOnly",
+ method: "post",
+ data: params,
+ });
+};
+
export const getStockInventoryReportList = (params) => {
return request({
url: "/stockInventory/stockInventoryPage",
diff --git a/src/views/basicData/oilDepot/index.vue b/src/views/basicData/oilDepot/index.vue
new file mode 100644
index 0000000..697acbc
--- /dev/null
+++ b/src/views/basicData/oilDepot/index.vue
@@ -0,0 +1,297 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <el-form :model="searchForm"
+ :inline="true">
+ <el-form-item label="娌瑰簱鍚嶇О锛�">
+ <el-input v-model="searchForm.depotName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
+ </el-form-item>
+ <el-form-item label="鎵�灞炲叕鍙革細">
+ <el-input v-model="searchForm.company"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary"
+ @click="handleQuery"> 鎼滅储
+ </el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ </div>
+ <div class="table_list">
+ <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
+ <el-button type="primary"
+ @click="openForm('add')">鏂板娌瑰簱</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎
+ </el-button>
+ </div>
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange">
+ <el-table-column align="center"
+ type="selection"
+ width="55" />
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="娌瑰簱鍚嶇О"
+ prop="depotName"
+ show-overflow-tooltip />
+ <el-table-column label="璐熻矗浜�"
+ prop="chargePerson"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="鑱旂郴鐢佃瘽"
+ prop="phone"
+ width="140" />
+ <el-table-column label="鍚敤鏃ユ湡"
+ prop="enableDate"
+ width="120" />
+ <el-table-column label="鎵�灞炲叕鍙�"
+ prop="company"
+ show-overflow-tooltip />
+ <el-table-column label="鍒涘缓鏃堕棿"
+ prop="createTime"
+ width="180">
+ <template #default="scope">
+ {{ scope.row.createTime ? scope.row.createTime.replace('T', ' ').slice(0, 19) : '--' }}
+ </template>
+ </el-table-column>
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ width="120"
+ align="center">
+ <template #default="scope">
+ <el-button link
+ type="primary"
+ @click="openForm('edit', scope.row)">缂栬緫
+ </el-button>
+ <el-button link
+ type="danger"
+ @click="handleDelete([scope.row])">鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
+ </div>
+ <FormDialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板娌瑰簱' : '缂栬緫娌瑰簱'"
+ :width="'40%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia">
+ <el-form :model="form"
+ label-width="120px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef">
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="娌瑰簱鍚嶇О锛�"
+ prop="depotName">
+ <el-input v-model="form.depotName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="璐熻矗浜猴細"
+ prop="chargePerson">
+ <el-input v-model="form.chargePerson"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴鐢佃瘽锛�"
+ prop="phone">
+ <el-input v-model="form.phone"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚敤鏃ユ湡锛�"
+ prop="enableDate">
+ <el-date-picker style="width: 100%"
+ v-model="form.enableDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎵�灞炲叕鍙革細"
+ prop="company">
+ <el-input v-model="form.company"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ </FormDialog>
+ </div>
+</template>
+
+<script setup>
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import { ref, reactive, toRefs, getCurrentInstance } from "vue";
+ import { Search } from "@element-plus/icons-vue";
+ import { ElMessageBox } from "element-plus";
+ import {
+ listOilDepot,
+ addOilDepot,
+ updateOilDepot,
+ delOilDepot,
+ } from "@/api/basicData/oilDepot.js";
+
+ const { proxy } = getCurrentInstance();
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const tableLoading = ref(false);
+ const dialogFormVisible = ref(false);
+ const operationType = ref("");
+ const page = reactive({
+ current: 1,
+ size: 10,
+ });
+ const total = ref(0);
+
+ const data = reactive({
+ searchForm: {
+ depotName: "",
+ company: "",
+ },
+ form: {
+ id: null,
+ depotName: "",
+ chargePerson: "",
+ phone: "",
+ enableDate: "",
+ company: "",
+ },
+ rules: {
+ depotName: [{ required: true, message: "璇疯緭鍏ユ补搴撳悕绉�", trigger: "blur" }],
+ company: [{ required: true, message: "璇疯緭鍏ユ墍灞炲叕鍙�", trigger: "blur" }],
+ },
+ });
+ const { searchForm, form, rules } = toRefs(data);
+
+ const getList = () => {
+ tableLoading.value = true;
+ listOilDepot({ ...searchForm.value, ...page })
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records || [];
+ total.value = res.data.total || 0;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
+ };
+
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+
+ const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
+
+ const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = true;
+ if (type === "edit" && row) {
+ const { id, depotName, chargePerson, phone, enableDate, company } = row;
+ form.value = { id, depotName, chargePerson, phone, enableDate, company };
+ }
+ };
+
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ const api = form.value.id ? updateOilDepot : addOilDepot;
+ api(form.value).then(() => {
+ proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
+ closeDia();
+ getList();
+ });
+ }
+ });
+ };
+
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
+
+ const handleDelete = rows => {
+ let ids = [];
+ if (rows) {
+ ids = rows.map(item => item.id);
+ } else if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delOilDepot(ids).then(() => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ getList();
+</script>
+
+<style scoped lang="scss">
+ .search_form {
+ margin-bottom: 16px;
+ }
+</style>
diff --git a/src/views/basicData/tankInfo/index.vue b/src/views/basicData/tankInfo/index.vue
new file mode 100644
index 0000000..e748b66
--- /dev/null
+++ b/src/views/basicData/tankInfo/index.vue
@@ -0,0 +1,324 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <el-form :model="searchForm"
+ :inline="true">
+ <el-form-item label="鍌ㄧ綈鍙凤細">
+ <el-input v-model="searchForm.tankNo"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
+ </el-form-item>
+ <el-form-item label="澶х被锛�">
+ <el-input v-model="searchForm.category"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary"
+ @click="handleQuery"> 鎼滅储
+ </el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ </div>
+ <div class="table_list">
+ <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
+ <el-button type="primary"
+ @click="openForm('add')">鏂板鍌ㄧ綈</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete()">鍒犻櫎
+ </el-button>
+ </div>
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange">
+ <el-table-column align="center"
+ type="selection"
+ width="55" />
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="鍌ㄧ綈鍙�"
+ prop="tankNo"
+ min-width="140"
+ show-overflow-tooltip />
+ <el-table-column label="澶х被"
+ prop="category"
+ min-width="120"
+ show-overflow-tooltip />
+ <el-table-column label="娌瑰搧"
+ prop="oilProduct"
+ min-width="120"
+ show-overflow-tooltip />
+ <el-table-column label="缃愬"
+ prop="capacity"
+ min-width="120" />
+ <el-table-column label="搴撳瓨浣欓噺(m鲁)"
+ prop="remaining"
+ min-width="140" />
+ <el-table-column label="绉熷淇℃伅"
+ prop="tenantInfo"
+ min-width="160"
+ show-overflow-tooltip />
+ <el-table-column label="鍒涘缓鏃堕棿"
+ prop="createTime"
+ min-width="180">
+ <template #default="scope">
+ {{ scope.row.createTime ? scope.row.createTime.replace('T', ' ').slice(0, 19) : '--' }}
+ </template>
+ </el-table-column>
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ width="120"
+ align="center">
+ <template #default="scope">
+ <el-button link
+ type="primary"
+ @click="openForm('edit', scope.row)">缂栬緫
+ </el-button>
+ <el-button link
+ type="danger"
+ @click="handleDelete([scope.row])">鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
+ </div>
+ <FormDialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鍌ㄧ綈' : '缂栬緫鍌ㄧ綈'"
+ :width="'40%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia">
+ <el-form :model="form"
+ label-width="120px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍌ㄧ綈鍙凤細"
+ prop="tankNo">
+ <el-input v-model="form.tankNo"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="澶х被锛�"
+ prop="category">
+ <el-input v-model="form.category"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="娌瑰搧锛�"
+ prop="oilProduct">
+ <el-select v-model="form.oilProduct"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="姹�#92"
+ value="姹�#92" />
+ <el-option label="姹�#95"
+ value="姹�#95" />
+ <el-option label="鏌�#0"
+ value="鏌�#0" />
+ <el-option label="鏌�#-35"
+ value="鏌�#-35" />
+ <el-option label="鍘熸补"
+ value="鍘熸补" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缃愬锛�"
+ prop="capacity">
+ <el-input-number v-model="form.capacity"
+ :precision="2"
+ :step="1"
+ :min="0"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="搴撳瓨浣欓噺(m鲁)锛�"
+ prop="remaining">
+ <el-input-number v-model="form.remaining"
+ :precision="2"
+ :step="1"
+ :min="0"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绉熷淇℃伅锛�"
+ prop="tenantInfo">
+ <el-input v-model="form.tenantInfo"
+ placeholder="璇疯緭鍏ョ瀹俊鎭�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ </FormDialog>
+ </div>
+</template>
+
+<script setup>
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import { ref, reactive, toRefs, getCurrentInstance } from "vue";
+ import { Search } from "@element-plus/icons-vue";
+ import { ElMessageBox } from "element-plus";
+ import {
+ listTankInfo,
+ addTankInfo,
+ updateTankInfo,
+ delTankInfo,
+ } from "@/api/basicData/tankInfo.js";
+
+ const { proxy } = getCurrentInstance();
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const tableLoading = ref(false);
+ const dialogFormVisible = ref(false);
+ const operationType = ref("");
+ const page = reactive({
+ current: 1,
+ size: 10,
+ });
+ const total = ref(0);
+
+ const data = reactive({
+ searchForm: {
+ tankNo: "",
+ category: "",
+ },
+ form: {
+ id: null,
+ tankNo: "",
+ category: "",
+ oilProduct: "",
+ capacity: null,
+ remaining: null,
+ tenantInfo: "",
+ },
+ rules: {
+ tankNo: [{ required: true, message: "璇疯緭鍏ュ偍缃愬彿", trigger: "blur" }],
+ category: [{ required: true, message: "璇疯緭鍏ュぇ绫�", trigger: "blur" }],
+ },
+ });
+ const { searchForm, form, rules } = toRefs(data);
+
+ const getList = () => {
+ tableLoading.value = true;
+ listTankInfo({ ...searchForm.value, ...page })
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records || [];
+ total.value = res.data.total || 0;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
+ };
+
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+
+ const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
+
+ const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = true;
+ if (type === "edit" && row) {
+ const { id, tankNo, category, oilProduct, capacity, remaining, tenantInfo } = row;
+ form.value = { id, tankNo, category, oilProduct, capacity, remaining, tenantInfo };
+ }
+ };
+
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ const api = form.value.id ? updateTankInfo : addTankInfo;
+ api(form.value).then(() => {
+ proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
+ closeDia();
+ getList();
+ });
+ }
+ });
+ };
+
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
+
+ const handleDelete = rows => {
+ let ids = [];
+ if (rows) {
+ ids = rows.map(item => item.id);
+ } else if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delTankInfo(ids).then(() => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ getList();
+</script>
+
+<style scoped lang="scss">
+ .search_form {
+ margin-bottom: 16px;
+ }
+</style>
diff --git a/src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue b/src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue
index a835ef4..c131ec2 100644
--- a/src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue
+++ b/src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue
@@ -9,13 +9,17 @@
>
<div class="detail-content">
<div class="detail-table-wrapper">
- <el-table
- :data="tableData"
- border
- v-loading="tableLoading"
- style="width: 100%"
- height="100%"
- >
+ <el-tabs v-model="detailTab"
+ class="detail-tabs">
+ <el-tab-pane label="搴撳瓨淇℃伅"
+ name="main">
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ style="width: 100%"
+ height="100%"
+ >
<el-table-column
label="浜у搧鍚嶇О"
prop="productName"
@@ -93,7 +97,161 @@
>
</template>
</el-table-column>
- </el-table>
+ </el-table>
+ </el-tab-pane>
+ <el-tab-pane label="鍏ュ簱淇℃伅"
+ name="in">
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ style="width: 100%"
+ height="100%"
+ >
+ <el-table-column label="鍏ュ簱淇℃伅"
+ align="center"
+ :header-cell-style="groupHeaderStyle">
+ <el-table-column label="娌瑰搧" prop="oilProduct" min-width="90" show-overflow-tooltip />
+ <el-table-column label="鍏ュ簱鍚嶇О" prop="oilDepotName" min-width="130" show-overflow-tooltip />
+ <el-table-column label="鍏ュ簱绫诲埆" prop="inboundCategory" min-width="100" show-overflow-tooltip />
+ <el-table-column label="鍌ㄧ綈鍙�" prop="tankNo" min-width="100" show-overflow-tooltip />
+ <el-table-column label="鍏ュ簱鏃堕棿" prop="inboundTime" min-width="160" show-overflow-tooltip />
+ <el-table-column label="鍘熷嚭鍘傛暟閲�(鍚�)" prop="originalQuantity" min-width="120" show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" min-width="120" show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛瀵规帴浜�" prop="contactPerson" min-width="100" show-overflow-tooltip />
+ <el-table-column label="瀵规帴浜虹數璇�" prop="contactPhone" min-width="120" show-overflow-tooltip />
+ </el-table-column>
+ <el-table-column label="鐗╂祦淇℃伅"
+ align="center"
+ :header-cell-style="groupHeaderStyle">
+ <el-table-column label="鍙告満濮撳悕" prop="driverName" min-width="100" show-overflow-tooltip />
+ <el-table-column label="鍙告満鐢佃瘽" prop="driverPhone" min-width="120" show-overflow-tooltip />
+ <el-table-column label="鎶艰繍鍛樺鍚�" prop="escortName" min-width="100" show-overflow-tooltip />
+ <el-table-column label="鎶艰繍鍛樼數璇�" prop="escortPhone" min-width="120" show-overflow-tooltip />
+ <el-table-column label="杞︾墝鍙�" prop="truckPlateNo" min-width="110" show-overflow-tooltip />
+ <el-table-column label="杞︽寕鐗屽彿" prop="trailerPlateNo" min-width="110" show-overflow-tooltip />
+ </el-table-column>
+ <el-table-column label="鍗告补鎿嶄綔淇℃伅"
+ align="center"
+ :header-cell-style="groupHeaderStyle">
+ <el-table-column label="杞︿綋/閾呭皝妫�楠�" prop="tankInspectionStatus" min-width="120" show-overflow-tooltip />
+ <el-table-column label="鍗歌溅楣や綅" prop="unloadingCranePosition" min-width="100" show-overflow-tooltip />
+ <el-table-column label="瀵嗗害" prop="density" min-width="80" show-overflow-tooltip />
+ <el-table-column label="鍗告补鎷嶇収" prop="unloadPhotos" align="center" min-width="90">
+ <template #default="scope">
+ <el-image
+ v-if="toPhotoArray(scope.row.unloadPhotos).length"
+ :src="getPhotoUrl(toPhotoArray(scope.row.unloadPhotos)[0])"
+ :preview-src-list="getPhotoUrls(scope.row.unloadPhotos)"
+ preview-teleported
+ fit="cover"
+ style="width: 40px; height: 40px; border-radius: 4px"
+ />
+ <span v-else>--</span>
+ </template>
+ </el-table-column>
+ </el-table-column>
+ <el-table-column label="杩囩鏁版嵁"
+ align="center"
+ :header-cell-style="groupHeaderStyle">
+ <el-table-column label="姣涢噸(鍚�)" prop="grossWeight" min-width="90" show-overflow-tooltip />
+ <el-table-column label="鐨噸(鍚�)" prop="tareWeight" min-width="90" show-overflow-tooltip />
+ <el-table-column label="鍑�閲�(鍚�)" prop="netWeight" min-width="90" show-overflow-tooltip />
+ <el-table-column label="浜忛噺(鍚�)" prop="lossQuantity" min-width="90" show-overflow-tooltip />
+ <el-table-column label="瀹為檯鍏ュ簱浣撶Н(鍗�)" prop="actualVolume" min-width="130" show-overflow-tooltip />
+ <el-table-column label="纾呭崟" prop="poundPhotos" align="center" min-width="90">
+ <template #default="scope">
+ <el-image
+ v-if="toPhotoArray(scope.row.poundPhotos).length"
+ :src="getPhotoUrl(toPhotoArray(scope.row.poundPhotos)[0])"
+ :preview-src-list="getPhotoUrls(scope.row.poundPhotos)"
+ preview-teleported
+ fit="cover"
+ style="width: 40px; height: 40px; border-radius: 4px"
+ />
+ <span v-else>--</span>
+ </template>
+ </el-table-column>
+ </el-table-column>
+ </el-table>
+ </el-tab-pane>
+ <el-tab-pane label="鍑哄簱淇℃伅"
+ name="out">
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ style="width: 100%"
+ height="100%"
+ >
+ <el-table-column label="鍑哄簱淇℃伅"
+ align="center"
+ :header-cell-style="groupHeaderStyle">
+ <el-table-column label="鍑哄簱绫诲埆" prop="outCategory" min-width="90" show-overflow-tooltip />
+ <el-table-column label="鍌ㄥ簱鍚嶇О" prop="outOilDepotName" min-width="130" show-overflow-tooltip />
+ <el-table-column label="鍌ㄧ綈鍙�" prop="outTankNo" min-width="100" show-overflow-tooltip />
+ <el-table-column label="鍑哄簱鏃ユ湡" prop="outDate" min-width="110" show-overflow-tooltip />
+ <el-table-column label="娌瑰搧" prop="outOilProduct" min-width="90" show-overflow-tooltip />
+ <el-table-column label="鍑哄簱鍚ㄤ綅(鍚�)" prop="outTonnage" min-width="110" show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛鍚嶇О" prop="outCustomerName" min-width="120" show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛瀵规帴浜�" prop="outContactPerson" min-width="100" show-overflow-tooltip />
+ <el-table-column label="瀵规帴浜虹數璇�" prop="outContactPhone" min-width="120" show-overflow-tooltip />
+ </el-table-column>
+ <el-table-column label="瑁呮补鎿嶄綔淇℃伅"
+ align="center"
+ :header-cell-style="groupHeaderStyle">
+ <el-table-column label="瑁呮补妫�楠�" prop="loadingInspectionStatus" min-width="90" show-overflow-tooltip />
+ <el-table-column label="瑁呰溅楣や綅" prop="loadingCranePosition" min-width="100" show-overflow-tooltip />
+ <el-table-column label="瀵嗗害" prop="outDensity" min-width="80" show-overflow-tooltip />
+ <el-table-column label="瑁呮补鎷嶇収" prop="loadingPhotos" align="center" min-width="90">
+ <template #default="scope">
+ <el-image
+ v-if="toPhotoArray(scope.row.loadingPhotos).length"
+ :src="getPhotoUrl(toPhotoArray(scope.row.loadingPhotos)[0])"
+ :preview-src-list="getPhotoUrls(scope.row.loadingPhotos)"
+ preview-teleported
+ fit="cover"
+ style="width: 40px; height: 40px; border-radius: 4px"
+ />
+ <span v-else>--</span>
+ </template>
+ </el-table-column>
+ </el-table-column>
+ <el-table-column label="鍑哄簱杩囩鏁版嵁"
+ align="center"
+ :header-cell-style="groupHeaderStyle">
+ <el-table-column label="姣涢噸(鍚�)" prop="outGrossWeight" min-width="90" show-overflow-tooltip />
+ <el-table-column label="鐨噸(鍚�)" prop="outTareWeight" min-width="90" show-overflow-tooltip />
+ <el-table-column label="鍑�閲�(鍚�)" prop="outNetWeight" min-width="90" show-overflow-tooltip />
+ <el-table-column label="浜忛噺(鍚�)" prop="outLossQuantity" min-width="90" show-overflow-tooltip />
+ <el-table-column label="瀹為檯鍏ュ簱浣撶Н(鍗�)" prop="outActualVolume" min-width="130" show-overflow-tooltip />
+ <el-table-column label="纾呭崟" prop="outPoundPhotos" align="center" min-width="90">
+ <template #default="scope">
+ <el-image
+ v-if="toPhotoArray(scope.row.outPoundPhotos).length"
+ :src="getPhotoUrl(toPhotoArray(scope.row.outPoundPhotos)[0])"
+ :preview-src-list="getPhotoUrls(scope.row.outPoundPhotos)"
+ preview-teleported
+ fit="cover"
+ style="width: 40px; height: 40px; border-radius: 4px"
+ />
+ <span v-else>--</span>
+ </template>
+ </el-table-column>
+ </el-table-column>
+ <el-table-column label="鍑哄簱鐗╂祦淇℃伅"
+ align="center"
+ :header-cell-style="groupHeaderStyle">
+ <el-table-column label="鍙告満濮撳悕" prop="outDriverName" min-width="100" show-overflow-tooltip />
+ <el-table-column label="鍙告満鐢佃瘽" prop="outDriverPhone" min-width="120" show-overflow-tooltip />
+ <el-table-column label="鎶艰繍鍛樺鍚�" prop="outEscortName" min-width="100" show-overflow-tooltip />
+ <el-table-column label="鎶艰繍鍛樼數璇�" prop="outEscortPhone" min-width="120" show-overflow-tooltip />
+ <el-table-column label="杞︾墝鍙�" prop="outTruckPlateNo" min-width="110" show-overflow-tooltip />
+ <el-table-column label="杞︽寕鐗屽彿" prop="outTrailerPlateNo" min-width="110" show-overflow-tooltip />
+ </el-table-column>
+ </el-table>
+ </el-tab-pane>
+ </el-tabs>
</div>
<pagination
v-show="total > 0"
@@ -137,6 +295,7 @@
const tableData = ref([]);
const tableLoading = ref(false);
const total = ref(0);
+const detailTab = ref("main");
const page = reactive({
current: 1,
size: 20,
@@ -163,6 +322,41 @@
.finally(() => {
tableLoading.value = false;
});
+};
+
+// 鍥剧墖鍒楋細鍚庣杩斿洖涓� JSON 瀛楃涓诧紝鍏煎鏁扮粍/瀛楃涓蹭袱绉嶅舰鎬�
+const toPhotoArray = (value) => {
+ if (!value) {
+ return [];
+ }
+ if (Array.isArray(value)) {
+ return value;
+ }
+ if (typeof value === "string") {
+ try {
+ const parsed = JSON.parse(value);
+ return Array.isArray(parsed) ? parsed : [];
+ } catch (e) {
+ return [];
+ }
+ }
+ return [];
+};
+
+// 鍥剧墖鍒楋細鍙栧崟寮犲湴鍧�锛堟敮鎸佸瓧绗︿覆鎴� {url} 瀵硅薄锛�
+const getPhotoUrl = (photo) =>
+ typeof photo === "string" ? photo : photo?.url || photo?.previewURL || "";
+
+// 鍥剧墖鍒楋細鍙栧叏閮ㄥ湴鍧�鐢ㄤ簬棰勮
+const getPhotoUrls = (photos) =>
+ toPhotoArray(photos).map(getPhotoUrl).filter(Boolean);
+
+// 鍒嗙粍鐖惰〃澶存牱寮忥細鍖哄垎鍚勫垎绫�
+const groupHeaderStyle = {
+ background: "#e8f3ff",
+ color: "#1d6fd8",
+ fontWeight: "700",
+ fontSize: "13px",
};
const paginationChange = (obj) => {
@@ -217,6 +411,21 @@
min-height: 0;
}
+.detail-tabs {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+:deep(.detail-tabs .el-tabs__content) {
+ flex: 1;
+ min-height: 0;
+}
+
+:deep(.detail-tabs .el-tab-pane) {
+ height: 100%;
+}
+
:deep(.batch-no-qty-detail-dialog .el-dialog) {
max-width: calc(100vw - 48px);
}
diff --git a/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue b/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue
index a7a9400..1ee1fc6 100644
--- a/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue
+++ b/src/views/inventoryManagement/stockManagement/FrozenAndThaw.vue
@@ -28,7 +28,7 @@
:label="operationType === 'frozen' ? '鍐荤粨鏁伴噺锛�' : '瑙e喕鏁伴噺锛�'"
prop="lockedQuantity"
>
- <el-input-number v-model="formState.lockedQuantity" :step="1" :min="maxCount > 0 ? 1 : 0" precision="0" style="width: 100%" :max="maxCount" :disabled="maxCount < 1" />
+ <el-input-number v-model="formState.lockedQuantity" :step="0.01" :min="0" precision="2" style="width: 100%" :max="maxCount" :disabled="maxCount < 1" />
</el-form-item>
</el-form>
@@ -43,7 +43,7 @@
</template>
<script setup>
-import {ref, computed, getCurrentInstance, onMounted} from "vue";
+import {ref, computed, watch, getCurrentInstance, onMounted} from "vue";
import {frozenStockInventory, thawStockInventory} from "@/api/inventoryManagement/stockInventory.js";
import {frozenStockUninventory, thawStockUninventory} from "@/api/inventoryManagement/stockUninventory.js";
@@ -73,15 +73,21 @@
lockedQuantity: undefined,
});
-const isShow = computed({
- get() {
- return props.visible;
- },
- set(val) {
- emit('update:visible', val);
- },
-});
+// 寮圭獥寮�鍏崇敤鏈湴鐘舵�佺鐞嗭細鐖剁骇鎵撳紑鏃跺悓姝ヤ负 true锛屾湰鍦板叧闂悗閫氱煡鐖剁骇
+const isShow = ref(false);
+watch(
+ () => props.visible,
+ val => {
+ isShow.value = val;
+ },
+ { immediate: true }
+);
+
+const requestClose = () => {
+ isShow.value = false;
+ emit('update:visible', false);
+};
let { proxy } = getCurrentInstance()
@@ -91,7 +97,7 @@
lockedQuantity: undefined,
type: undefined,
};
- isShow.value = false;
+ requestClose();
};
const maxCount = computed(() => {
@@ -118,67 +124,48 @@
}
const handleSubmit = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- const data = Object.assign({}, formState.value);
- if (formState.value.type === 'qualified') {
- data.id = props.record.qualifiedId;
- // 鍐荤粨
- if (props.operationType === 'frozen') {
- frozenStockInventory(data).then(res => {
- if (res.code === 200) {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- }
- })
- } else {
- thawStockInventory(data).then(res => {
- if (res.code === 200) {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- }
- })
- }
+ // 涓嶄緷璧栬〃鍗曞紩鐢紝鐩存帴鎵嬪姩鏍¢獙
+ if (!formState.value.type) {
+ proxy.$modal.msgError("璇烽�夋嫨搴撳瓨绫诲瀷");
+ return;
+ }
+ const qty = Number(formState.value.lockedQuantity);
+ if (!formState.value.lockedQuantity || qty <= 0) {
+ proxy.$modal.msgError(
+ `璇疯緭鍏�${props.operationType === 'frozen' ? '鍐荤粨' : '瑙e喕'}鏁伴噺`
+ );
+ return;
+ }
+ if (qty > maxCount.value) {
+ proxy.$modal.msgError(`鏁伴噺涓嶈兘瓒呰繃${maxCount.value}`);
+ return;
+ }
+
+ const data = Object.assign({}, formState.value);
+ const doSubmit = (api, id) => {
+ data.id = id;
+ api(data).then(res => {
+ if (res.code === 200) {
+ requestClose();
+ emit('completed');
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
} else {
- data.id = props.record.unQualifiedId;
- if (props.operationType === 'frozen') {
- frozenStockUninventory(data).then(res => {
- if (res.code === 200) {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- }
- })
- } else {
- thawStockUninventory(data).then(res => {
- if (res.code === 200) {
- // 鍏抽棴妯℃�佹
- isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
- emit('completed');
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- }
- })
- }
+ proxy.$modal.msgError(res.msg);
}
- }
- })
+ });
+ };
+
+ if (formState.value.type === 'qualified') {
+ doSubmit(
+ props.operationType === 'frozen' ? frozenStockInventory : thawStockInventory,
+ props.record.qualifiedId
+ );
+ } else {
+ doSubmit(
+ props.operationType === 'frozen' ? frozenStockUninventory : thawStockUninventory,
+ props.record.unQualifiedId
+ );
+ }
};
onMounted(() => {
diff --git a/src/views/inventoryManagement/stockManagement/New.vue b/src/views/inventoryManagement/stockManagement/New.vue
index e55de75..a5afaba 100644
--- a/src/views/inventoryManagement/stockManagement/New.vue
+++ b/src/views/inventoryManagement/stockManagement/New.vue
@@ -2,81 +2,110 @@
<div>
<el-dialog v-model="isShow"
title="鏂板搴撳瓨"
- width="800"
+ width="60%"
@close="closeModal">
<el-form label-width="140px"
:model="formState"
label-position="top"
ref="formRef">
- <el-form-item label="浜у搧鍚嶇О"
- prop="productModelId"
- :rules="[
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[
{
required: true,
message: '璇烽�夋嫨浜у搧',
trigger: 'change',
}
]">
- <el-button type="primary"
- @click="showProductSelectDialog = true">
- {{ formState.productName ? formState.productName : '閫夋嫨浜у搧' }}
- </el-button>
- </el-form-item>
- <el-form-item label="瑙勬牸"
- prop="productModelName">
- <el-input v-model="formState.productModelName"
- disabled />
- </el-form-item>
- <el-form-item label="鍗曚綅"
- prop="unit">
- <el-input v-model="formState.unit"
- disabled />
- </el-form-item>
- <el-form-item label="搴撳瓨绫诲瀷"
- prop="type"
- :rules="[
+ <el-button type="primary"
+ @click="showProductSelectDialog = true">
+ {{ formState.productName ? formState.productName : '閫夋嫨浜у搧' }}
+ </el-button>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸"
+ prop="productModelName">
+ <el-input v-model="formState.productModelName"
+ disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="formState.unit"
+ disabled />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="搴撳瓨绫诲瀷"
+ prop="type"
+ :rules="[
{
required: true,
message: '璇烽�夋嫨搴撳瓨绫诲瀷',
trigger: 'change',
}
]">
- <el-select v-model="formState.type"
- placeholder="璇烽�夋嫨搴撳瓨绫诲瀷">
- <el-option label="鍚堟牸搴撳瓨"
- value="qualified" />
- <el-option label="涓嶅悎鏍煎簱瀛�"
- value="unqualified" />
- </el-select>
- </el-form-item>
- <el-form-item label="搴撳瓨鏁伴噺"
- prop="qualitity">
- <el-input-number v-model="formState.qualitity"
- :step="0.01"
- :min="0.01"
- :precision="2"
- style="width: 100%" />
- </el-form-item>
- <el-form-item label="鎵瑰彿"
- prop="batchNo">
- <el-input v-model="formState.batchNo"
- placeholder="璇疯緭鍏ユ壒鍙�" />
- </el-form-item>
- <el-form-item v-if="formState.type === 'qualified'"
- label="搴撳瓨棰勮鏁伴噺"
- prop="warnNum">
- <el-input-number v-model="formState.warnNum"
- :step="0.01"
- :min="0"
- :max="formState.qualitity"
- :precision="2"
- style="width: 100%" />
- </el-form-item>
- <el-form-item label="澶囨敞"
- prop="remark">
- <el-input v-model="formState.remark"
- type="textarea" />
- </el-form-item>
+ <el-select v-model="formState.type"
+ placeholder="璇烽�夋嫨搴撳瓨绫诲瀷"
+ style="width: 100%">
+ <el-option label="鍚堟牸搴撳瓨"
+ value="qualified" />
+ <el-option label="涓嶅悎鏍煎簱瀛�"
+ value="unqualified" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="搴撳瓨鏁伴噺"
+ prop="qualitity">
+ <el-input-number v-model="formState.qualitity"
+ :step="0.01"
+ :min="0.01"
+ :precision="2"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col v-if="formState.type === 'qualified'"
+ :span="12">
+ <el-form-item label="搴撳瓨棰勮鏁伴噺"
+ prop="warnNum">
+ <el-input-number v-model="formState.warnNum"
+ :step="0.01"
+ :min="0"
+ :max="formState.qualitity"
+ :precision="2"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="formState.type === 'qualified' ? 12 : 24">
+ <el-form-item label="鎵瑰彿"
+ prop="batchNo">
+ <el-input v-model="formState.batchNo"
+ placeholder="璇疯緭鍏ユ壒鍙�"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="formState.remark"
+ type="textarea"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
</el-form>
<!-- 浜у搧閫夋嫨寮圭獥 -->
<ProductSelectDialog v-model="showProductSelectDialog"
@@ -114,8 +143,7 @@
const emit = defineEmits(["update:visible", "completed"]);
- // 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
- const formState = ref({
+ const buildEmptyForm = () => ({
productId: undefined,
productModelId: undefined,
productName: "",
@@ -127,6 +155,8 @@
warnNum: 0,
remark: "",
});
+
+ const formState = ref(buildEmptyForm());
const isShow = computed({
get() {
@@ -152,19 +182,8 @@
let { proxy } = getCurrentInstance();
const closeModal = () => {
- // 閲嶇疆琛ㄥ崟鏁版嵁
- formState.value = {
- productId: undefined,
- productModelId: undefined,
- productName: "",
- productModelName: "",
- unit: "",
- type: undefined,
- qualitity: 0,
- batchNo: null,
- warnNum: 0,
- remark: "",
- };
+ proxy.resetForm("formRef");
+ formState.value = buildEmptyForm();
isShow.value = false;
};
@@ -186,29 +205,21 @@
const handleSubmit = () => {
proxy.$refs["formRef"].validate(valid => {
if (valid) {
- // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰瑙勬牸
+ // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝�
if (!formState.value.productModelId) {
proxy.$modal.msgError("璇烽�夋嫨浜у搧");
return;
}
- if (!formState.value.productModelId) {
- proxy.$modal.msgError("璇烽�夋嫨瑙勬牸");
- return;
- }
if (formState.value.type === "qualified") {
addStockInRecordOnly(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
emit("completed");
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
});
} else {
formState.value.warnNum = 0;
createStockUnInventory(formState.value).then(res => {
- // 鍏抽棴妯℃�佹
isShow.value = false;
- // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
emit("completed");
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
});
diff --git a/src/views/inventoryManagement/stockManagement/OilStockInDialog.vue b/src/views/inventoryManagement/stockManagement/OilStockInDialog.vue
new file mode 100644
index 0000000..8433960
--- /dev/null
+++ b/src/views/inventoryManagement/stockManagement/OilStockInDialog.vue
@@ -0,0 +1,791 @@
+<template>
+ <div>
+ <el-dialog v-model="isShow"
+ title="鏂板娌瑰搧鍏ュ簱"
+ width="60%"
+ @close="closeModal">
+ <el-form label-width="140px"
+ :model="formState"
+ label-position="top"
+ ref="formRef">
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧',
+ trigger: 'change',
+ }
+ ]">
+ <el-button type="primary"
+ @click="showProductSelectDialog = true">
+ {{ formState.productName ? formState.productName : '閫夋嫨浜у搧' }}
+ </el-button>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸"
+ prop="productModelName">
+ <el-input v-model="formState.productModelName"
+ disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="formState.unit"
+ disabled />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">鍏ュ簱淇℃伅</div>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍏ュ簱鍚嶇О"
+ prop="oilDepotId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨鍏ュ簱鍚嶇О',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.oilDepotId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ popper-class="oil-depot-select-popper"
+ style="width: 100%">
+ <el-option v-for="item in oilDepotList"
+ :key="item.id"
+ :label="item.depotName"
+ :value="item.id">
+ <div class="oil-depot-option">
+ <div class="oil-depot-option-title">{{ item.depotName }}</div>
+ <div class="oil-depot-option-line">璐熻矗浜猴細{{ item.chargePerson }}</div>
+ <div class="oil-depot-option-line">鑱旂郴鐢佃瘽锛歿{ item.phone }}</div>
+ <div class="oil-depot-option-line">鎵�灞炲叕鍙革細{{ item.company }}</div>
+ <div class="oil-depot-option-line">鍚敤鏃ユ湡锛歿{ item.enableDate }}</div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏ュ簱绫诲埆"
+ prop="inboundCategory"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨鍏ュ簱绫诲埆',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.inboundCategory"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="鑷喘鍏ュ簱"
+ value="鑷喘鍏ュ簱" />
+ <el-option label="浠e偍鍏ュ簱"
+ value="浠e偍鍏ュ簱" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍌ㄧ綈鍙�"
+ prop="tankId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨鍌ㄧ綈鍙�',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.tankId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ popper-class="tank-select-popper"
+ style="width: 100%">
+ <el-option v-for="item in tankList"
+ :key="item.id"
+ :label="item.tankNo"
+ :value="item.id">
+ <div class="tank-option">
+ <div class="tank-option-title">{{ item.tankNo }}</div>
+ <div class="tank-option-line">澶х被锛歿{ item.category }}</div>
+ <div class="tank-option-line">娌瑰搧锛歿{ item.oilProduct }}</div>
+ <div class="tank-option-line">缃愬锛歿{ item.capacity }}</div>
+ <div class="tank-option-line">搴撳瓨浣欓噺(m鲁)锛歿{ item.remaining }}</div>
+ <div class="tank-option-line">绉熷淇℃伅锛歿{ item.tenantInfo || '--' }}</div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏ュ簱鏃堕棿"
+ prop="inboundTime"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨鍏ュ簱鏃堕棿',
+ trigger: 'change',
+ }
+ ]">
+ <el-date-picker v-model="formState.inboundTime"
+ type="datetime"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ format="YYYY-MM-DD HH:mm:ss"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="娌瑰搧"
+ prop="oilProduct"
+ :rules="isOilProduct ? [
+ {
+ required: true,
+ message: '璇烽�夋嫨娌瑰搧',
+ trigger: 'change',
+ }
+ ] : []">
+ <el-input v-if="isOilProduct"
+ :model-value="formState.oilProduct"
+ readonly
+ placeholder="--" />
+ <el-select v-else
+ v-model="formState.oilProduct"
+ placeholder="璇烽�夋嫨"
+ disabled
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍘熷嚭鍘傛暟閲�(鍚�)"
+ prop="originalQuantity"
+ :rules="[
+ {
+ required: true,
+ message: '璇疯緭鍏ュ師鍑哄巶鏁伴噺',
+ trigger: 'change',
+ }
+ ]">
+ <el-input-number v-model="formState.originalQuantity"
+ :precision="2"
+ :step="1"
+ :min="0"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="8">
+ <el-form-item label="瀹㈡埛鍚嶇О"
+ prop="customerId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨瀹㈡埛鍚嶇О',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.customerId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ filterable
+ popper-class="customer-select-popper"
+ style="width: 100%"
+ @change="customerChange">
+ <el-option v-for="item in customerList"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.id">
+ <div class="customer-option">
+ <div class="customer-option-title">{{ item.customerName }}</div>
+ <div class="customer-option-line">寮�鎴疯鍚嶇О锛歿{ item.basicBankAccount }}</div>
+ <div class="customer-option-line">閾惰璐︽埛锛歿{ item.bankAccount }}</div>
+ <div class="customer-option-line">鍦板潃锛歿{ item.addressPhone }}</div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀹㈡埛瀵规帴浜�"
+ prop="contactPerson"
+ :rules="[
+ {
+ required: true,
+ message: '璇疯緭鍏ュ鎴峰鎺ヤ汉',
+ trigger: 'blur',
+ }
+ ]">
+ <el-input v-model="formState.contactPerson"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀵规帴浜虹數璇�"
+ prop="contactPhone"
+ :rules="[
+ {
+ required: true,
+ message: '璇疯緭鍏ュ鎺ヤ汉鐢佃瘽',
+ trigger: 'blur',
+ },
+ {
+ pattern: /^1[3-9]\d{9}$/,
+ message: '璇疯緭鍏ユ湁鏁堢殑11浣嶆墜鏈哄彿鐮�',
+ trigger: 'blur',
+ }
+ ]">
+ <el-input v-model="formState.contactPhone"
+ placeholder="璇疯緭鍏�11浣嶆暟瀛�"
+ maxlength="11"
+ @input="phoneInput('contactPhone')"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">鐗╂祦淇℃伅</div>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍙告満濮撳悕"
+ prop="driverName"
+ :rules="[{ required: true, message: '璇疯緭鍏ュ徃鏈哄鍚�', trigger: 'blur' }]">
+ <el-input v-model="formState.driverName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍙告満鐢佃瘽"
+ prop="driverPhone"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ュ徃鏈虹數璇�', trigger: 'blur' },
+ { pattern: /^1[3-9]\d{9}$/, message: '璇疯緭鍏ユ湁鏁堢殑11浣嶆墜鏈哄彿鐮�', trigger: 'blur' }
+ ]">
+ <el-input v-model="formState.driverPhone"
+ placeholder="璇疯緭鍏�11浣嶆暟瀛�"
+ maxlength="11"
+ @input="phoneInput('driverPhone')"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鎶艰繍鍛樺鍚�"
+ prop="escortName"
+ :rules="[{ required: true, message: '璇疯緭鍏ユ娂杩愬憳濮撳悕', trigger: 'blur' }]">
+ <el-input v-model="formState.escortName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎶艰繍鍛樼數璇�"
+ prop="escortPhone"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ユ娂杩愬憳鐢佃瘽', trigger: 'blur' },
+ { pattern: /^1[3-9]\d{9}$/, message: '璇疯緭鍏ユ湁鏁堢殑11浣嶆墜鏈哄彿鐮�', trigger: 'blur' }
+ ]">
+ <el-input v-model="formState.escortPhone"
+ placeholder="璇疯緭鍏�11浣嶆暟瀛�"
+ maxlength="11"
+ @input="phoneInput('escortPhone')"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="杞︾墝鍙�"
+ prop="truckPlateNo"
+ :rules="[{ required: true, message: '璇疯緭鍏ヨ溅鐗屽彿', trigger: 'blur' }]">
+ <el-input v-model="formState.truckPlateNo"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="杞︽寕鐗屽彿"
+ prop="trailerPlateNo"
+ :rules="[{ required: true, message: '璇疯緭鍏ヨ溅鎸傜墝鍙�', trigger: 'blur' }]">
+ <el-input v-model="formState.trailerPlateNo"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">鍗告补鎿嶄綔淇℃伅</div>
+ <el-row :gutter="30">
+ <el-col :span="8">
+ <el-form-item label="杞︿綋/閾呭皝妫�楠屾槸鍚︽甯�"
+ prop="tankInspectionStatus"
+ :rules="[{ required: true, message: '璇烽�夋嫨杞︿綋/閾呭皝妫�楠屾槸鍚︽甯�', trigger: 'change' }]">
+ <el-radio-group v-model="formState.tankInspectionStatus">
+ <el-radio value="姝e父">姝e父</el-radio>
+ <el-radio value="寮傚父">寮傚父</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鍗歌溅楣や綅"
+ prop="unloadingCranePosition"
+ :rules="[{ required: true, message: '璇烽�夋嫨鍗歌溅楣や綅', trigger: 'change' }]">
+ <el-select v-model="formState.unloadingCranePosition"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="1#鎾"
+ value="1#鎾" />
+ <el-option label="2#鎾"
+ value="2#鎾" />
+ <el-option label="涓存椂娉�"
+ value="涓存椂娉�" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀵嗗害"
+ prop="density"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ュ瘑搴�', trigger: 'blur' },
+ { pattern: /^\d+(\.\d{1,2})?$/, message: '璇疯緭鍏ユ暟瀛楋紝鏈�澶氫繚鐣欎袱浣嶅皬鏁�', trigger: 'blur' },
+ ]">
+ <el-input v-model="formState.density"
+ placeholder="璇疯緭鍏ユ暟瀛楋紝鏈�澶氫繚鐣欎袱浣嶅皬鏁�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鍗告补鍏抽敭鐜妭涓庤溅杈嗗叧閿綅缃媿鐓�"
+ prop="unloadPhotos"
+ :rules="[{ required: true, message: '璇蜂笂浼犲嵏娌瑰叧閿幆鑺備笌杞﹁締鍏抽敭浣嶇疆鎷嶇収', trigger: 'change' }]">
+ <ImageUpload v-model:file-list="formState.unloadPhotos"
+ :limit="10" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">杩囩鏁版嵁</div>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="姣涢噸(鍚�)"
+ prop="grossWeight"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ユ瘺閲�', trigger: 'blur' },
+ { pattern: /^\d+$/, message: '鍙兘杈撳叆鏁存暟鏁板瓧', trigger: 'blur' },
+ ]">
+ <el-input v-model="formState.grossWeight"
+ placeholder="璇疯緭鍏ユ暣鏁版暟瀛�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐨噸(鍚�)"
+ prop="tareWeight"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ョ毊閲�', trigger: 'blur' },
+ { pattern: /^\d+$/, message: '鍙兘杈撳叆鏁存暟鏁板瓧', trigger: 'blur' },
+ ]">
+ <el-input v-model="formState.tareWeight"
+ placeholder="璇疯緭鍏ユ暣鏁版暟瀛�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="8">
+ <el-form-item label="鍑�閲�(鍚�)">
+ <el-input :model-value="netWeight === null ? '--' : netWeight"
+ readonly />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="浜忛噺(鍚�)">
+ <el-input :model-value="lossQuantity === null ? '--' : lossQuantity"
+ readonly />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀹為檯鍏ュ簱浣撶Н(鍗�)">
+ <el-input :model-value="actualVolume"
+ readonly />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="纾呭崟涓婁紶"
+ prop="poundPhotos"
+ :rules="[{ required: true, message: '璇蜂笂浼犵鍗�', trigger: 'change' }]">
+ <ImageUpload v-model:file-list="formState.poundPhotos"
+ :limit="10" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <!-- 浜у搧閫夋嫨寮圭獥 -->
+ <ProductSelectDialog v-model="showProductSelectDialog"
+ @confirm="handleProductSelect"
+ single />
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="handleSubmit">纭</el-button>
+ <el-button @click="closeModal">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+ import { ref, computed, getCurrentInstance, onMounted } from "vue";
+ import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+ import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
+ import { addStockInRecordOnly } from "@/api/inventoryManagement/stockInventory.js";
+ import { allOilDepot } from "@/api/basicData/oilDepot.js";
+ import { allTankInfo } from "@/api/basicData/tankInfo.js";
+ import { listCustomer } from "@/api/basicData/customer.js";
+ import { productTreeList } from "@/api/basicData/product.js";
+
+ const props = defineProps({
+ visible: {
+ type: Boolean,
+ required: true,
+ },
+ });
+
+ const emit = defineEmits(["update:visible", "completed"]);
+
+ const buildEmptyForm = () => ({
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ productModelName: "",
+ unit: "",
+ oilDepotId: undefined,
+ inboundCategory: undefined,
+ tankId: undefined,
+ inboundTime: "",
+ oilProduct: undefined,
+ originalQuantity: undefined,
+ customerId: undefined,
+ contactPerson: "",
+ contactPhone: "",
+ driverName: "",
+ driverPhone: "",
+ escortName: "",
+ escortPhone: "",
+ truckPlateNo: "",
+ trailerPlateNo: "",
+ tankInspectionStatus: undefined,
+ unloadingCranePosition: undefined,
+ density: undefined,
+ unloadPhotos: [],
+ grossWeight: undefined,
+ tareWeight: undefined,
+ poundPhotos: [],
+ });
+
+ const formState = ref(buildEmptyForm());
+
+ const oilDepotList = ref([]);
+ const tankList = ref([]);
+ const customerList = ref([]);
+ const oilProductOptions = ref([]);
+
+ const isShow = computed({
+ get() {
+ return props.visible;
+ },
+ set(val) {
+ emit("update:visible", val);
+ },
+ });
+
+ // 鍦ㄤ骇鍝佹爲涓煡鎵�"娌瑰搧"鍒嗙被鑺傜偣
+ const findOilNode = nodes => {
+ for (const node of nodes || []) {
+ if (node.productName === "娌瑰搧") {
+ return node;
+ }
+ if (node.children && node.children.length) {
+ const found = findOilNode(node.children);
+ if (found) {
+ return found;
+ }
+ }
+ }
+ return null;
+ };
+
+ // 鎵�閫夊晢鍝佸悕绉板懡涓殑娌瑰搧閫夐」锛堟补鍝佽妭鐐瑰瓙椤癸紝鏉ヨ嚜浜у搧缁存姢妯″潡锛�
+ const matchedOilOption = computed(() =>
+ oilProductOptions.value.find(
+ item => item.productName === formState.value.productName
+ )
+ );
+
+ // 鍙湁閫変腑娌瑰搧瀛楁閫夐」閲屾湁鐨勫叿浣撴补鍝佹墠鍚敤娌瑰搧瀛楁锛�"娌瑰搧"澶х被鏈韩涓嶅惎鐢�
+ const isOilProduct = computed(() => !!matchedOilOption.value);
+
+ // 鍑�閲�(鍚�) = 姣涢噸 - 鐨噸
+ const netWeight = computed(() => {
+ const g = formState.value.grossWeight;
+ const t = formState.value.tareWeight;
+ if ([g, t].some(v => v === null || v === undefined || v === "")) {
+ return null;
+ }
+ return Number(g) - Number(t);
+ });
+
+ // 浜忛噺(鍚�) = 鍑�閲嶇殑璐熸暟
+ const lossQuantity = computed(() => {
+ if (netWeight.value === null) {
+ return null;
+ }
+ return -netWeight.value;
+ });
+
+ // 瀹為檯鍏ュ簱浣撶Н(鍗�) = 瀹為檯鍑�閲�(kg) 梅 瀵嗗害(kg/L)锛屽噣閲嶅惃 脳 1000 杞� kg
+ const actualVolume = computed(() => {
+ const d = formState.value.density;
+ if (netWeight.value === null || d === null || d === undefined || d === "" || Number(d) <= 0) {
+ return 0;
+ }
+ return Math.round(((netWeight.value * 1000) / Number(d)) * 100) / 100;
+ });
+
+ const showProductSelectDialog = ref(false);
+
+ let { proxy } = getCurrentInstance();
+
+ const closeModal = () => {
+ proxy.resetForm("formRef");
+ formState.value = buildEmptyForm();
+ isShow.value = false;
+ };
+
+ // 鐢佃瘽杈撳叆闄愬埗锛氬彧鍏佽鏁板瓧锛屾渶澶�11浣�
+ const phoneInput = field => {
+ formState.value[field] = String(formState.value[field] ?? "")
+ .replace(/\D/g, "")
+ .slice(0, 11);
+ };
+
+ // 瀹㈡埛閫夋嫨鏀瑰彉锛氱粦瀹氬鎴蜂俊鎭〃锛岃嚜鍔ㄥ甫鍑哄鎺ヤ汉涓庡鎺ョ數璇�
+ const customerChange = id => {
+ const customer = customerList.value.find(item => item.id === id);
+ if (customer) {
+ formState.value.contactPerson = customer.contactPerson || "";
+ formState.value.contactPhone = customer.contactPhone || "";
+ } else {
+ formState.value.contactPerson = "";
+ formState.value.contactPhone = "";
+ }
+ };
+
+ // 浜у搧閫夋嫨澶勭悊
+ const handleProductSelect = async products => {
+ if (products && products.length > 0) {
+ const product = products[0];
+ formState.value.productId = product.productId;
+ formState.value.productName = product.productName;
+ formState.value.productModelName = product.model;
+ formState.value.productModelId = product.id;
+ formState.value.unit = product.unit;
+ // 娌瑰搧閫夐」涓庡晢鍝佸悕绉板悓姝ワ細鍛戒腑娌瑰搧閫夐」鍒欒嚜鍔ㄥ甫鍑鸿娌瑰搧锛屾湭鍛戒腑鍒欐竻绌哄苟绂佺敤
+ formState.value.oilProduct = matchedOilOption.value
+ ? product.productName
+ : undefined;
+ showProductSelectDialog.value = false;
+ // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+ proxy.$refs["formRef"]?.validateField("productModelId");
+ }
+ };
+
+ const handleSubmit = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (!formState.value.productModelId) {
+ proxy.$modal.msgError("璇烽�夋嫨浜у搧");
+ return;
+ }
+ // 璁$畻缁撴灉闅忚〃鍗曟彁浜わ細娌瑰搧鍏ュ簱鍥哄畾涓哄悎鏍煎簱瀛橈紝搴撳瓨鏁伴噺鍙栧噣閲�
+ formState.value.type = "qualified";
+ formState.value.warnNum = 0;
+ formState.value.qualitity = netWeight.value;
+ formState.value.netWeight = netWeight.value;
+ formState.value.lossQuantity = lossQuantity.value;
+ formState.value.actualVolume = actualVolume.value;
+
+ addStockInRecordOnly(formState.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeModal();
+ emit("completed");
+ });
+ }
+ });
+ };
+
+ onMounted(() => {
+ allOilDepot().then(res => {
+ oilDepotList.value = res?.data || [];
+ });
+ allTankInfo().then(res => {
+ tankList.value = res?.data || [];
+ });
+ listCustomer({ current: 1, size: 1000, type: 0 }).then(res => {
+ customerList.value = res?.data?.records || [];
+ });
+ productTreeList().then(res => {
+ const oilNode = findOilNode(res);
+ oilProductOptions.value = oilNode?.children || [];
+ });
+ });
+</script>
+
+<style scoped lang="scss">
+ // 琛ㄥ崟鍒嗘爮鏍囬锛氳摑鑹茬珫鏉� + 娴呰摑搴曡壊锛岀獊鍑哄垎鍖�
+ .form-section-title {
+ margin: 18px 0 14px;
+ padding: 8px 14px;
+ font-size: 15px;
+ font-weight: 600;
+ color: #1d6fd8;
+ background: linear-gradient(90deg, rgba(64, 158, 255, 0.14), rgba(64, 158, 255, 0.02));
+ border-left: 4px solid #409eff;
+ border-radius: 3px;
+ }
+
+ // 鍏ュ簱鍚嶇О涓嬫媺閫夐」锛氬皬鍗$墖鏍峰紡
+ .oil-depot-option {
+ padding: 8px 10px;
+
+ .oil-depot-option-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+ }
+
+ .oil-depot-option-line {
+ font-size: 12px;
+ color: #909399;
+ line-height: 1.8;
+ }
+ }
+
+ // 鍌ㄧ綈鍙蜂笅鎷夐�夐」锛氬皬鍗$墖鏍峰紡
+ .tank-option {
+ padding: 8px 10px;
+
+ .tank-option-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+ }
+
+ .tank-option-line {
+ font-size: 12px;
+ color: #909399;
+ line-height: 1.8;
+ }
+ }
+
+ // 瀹㈡埛鍚嶇О涓嬫媺閫夐」锛氬皬鍗$墖鏍峰紡
+ .customer-option {
+ padding: 8px 10px;
+
+ .customer-option-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+ }
+
+ .customer-option-line {
+ font-size: 12px;
+ color: #909399;
+ line-height: 1.8;
+ }
+ }
+</style>
+
+<style lang="scss">
+ // 涓嬫媺闈㈡澘娓叉煋鍦� body 涓嬶紝闇�鍏ㄥ眬鏍峰紡
+ .oil-depot-select-popper {
+ .el-select-dropdown__item {
+ height: auto;
+ line-height: normal;
+ padding: 4px 0;
+ }
+
+ .oil-depot-option {
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ background-color: #fafbfc;
+
+ &:hover {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+ }
+ }
+ }
+
+ // 鍌ㄧ綈鍙蜂笅鎷夐潰鏉匡紙body 涓嬶紝闇�鍏ㄥ眬鏍峰紡锛�
+ .tank-select-popper {
+ .el-select-dropdown__item {
+ height: auto;
+ line-height: normal;
+ padding: 4px 0;
+ }
+
+ .tank-option {
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ background-color: #fafbfc;
+
+ &:hover {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+ }
+ }
+ }
+
+ // 瀹㈡埛鍚嶇О涓嬫媺闈㈡澘锛坆ody 涓嬶紝闇�鍏ㄥ眬鏍峰紡锛�
+ .customer-select-popper {
+ .el-select-dropdown__item {
+ height: auto;
+ line-height: normal;
+ padding: 4px 0;
+ }
+
+ .customer-option {
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ background-color: #fafbfc;
+
+ &:hover {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+ }
+ }
+ }
+</style>
diff --git a/src/views/inventoryManagement/stockManagement/OilStockOutDialog.vue b/src/views/inventoryManagement/stockManagement/OilStockOutDialog.vue
new file mode 100644
index 0000000..c3a7865
--- /dev/null
+++ b/src/views/inventoryManagement/stockManagement/OilStockOutDialog.vue
@@ -0,0 +1,759 @@
+<template>
+ <div>
+ <el-dialog v-model="isShow"
+ title="鏂板娌瑰搧鍑哄簱"
+ width="60%"
+ @close="closeModal">
+ <el-form label-width="140px"
+ :model="formState"
+ label-position="top"
+ ref="formRef">
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productModelId"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧',
+ trigger: 'change',
+ }
+ ]">
+ <el-button type="primary"
+ @click="showProductSelectDialog = true">
+ {{ formState.productName ? formState.productName : '閫夋嫨浜у搧' }}
+ </el-button>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="瑙勬牸"
+ prop="model">
+ <el-input v-model="formState.model"
+ disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="formState.unit"
+ disabled />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">鍑哄簱淇℃伅</div>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍑哄簱绫诲埆"
+ prop="outCategory"
+ :rules="[{ required: true, message: '璇烽�夋嫨鍑哄簱绫诲埆', trigger: 'change' }]">
+ <el-select v-model="formState.outCategory"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="瀹㈠瓨"
+ value="瀹㈠瓨" />
+ <el-option label="浠e偍"
+ value="浠e偍" />
+ <el-option label="閿�鍞�"
+ value="閿�鍞�" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍌ㄥ簱鍚嶇О"
+ prop="oilDepotId"
+ :rules="[{ required: true, message: '璇烽�夋嫨鍌ㄥ簱鍚嶇О', trigger: 'change' }]">
+ <el-select v-model="formState.oilDepotId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ popper-class="oil-depot-select-popper"
+ style="width: 100%"
+ @change="depotChange">
+ <el-option v-for="item in oilDepotList"
+ :key="item.id"
+ :label="`${item.depotName}-${item.company || ''}`"
+ :value="item.id">
+ <div class="oil-depot-option">
+ <div class="oil-depot-option-title">{{ item.depotName }}-{{ item.company }}</div>
+ <div class="oil-depot-option-line">璐熻矗浜猴細{{ item.chargePerson }}</div>
+ <div class="oil-depot-option-line">鑱旂郴鐢佃瘽锛歿{ item.phone }}</div>
+ <div class="oil-depot-option-line">鍚敤鏃ユ湡锛歿{ item.enableDate }}</div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍌ㄧ綈鍙�"
+ prop="tankId"
+ :rules="[{ required: true, message: '璇烽�夋嫨鍌ㄧ綈鍙�', trigger: 'change' }]">
+ <el-select v-model="formState.tankId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ popper-class="tank-select-popper"
+ style="width: 100%"
+ @change="tankChange">
+ <el-option v-for="item in tankList"
+ :key="item.id"
+ :label="item.tankNo"
+ :value="item.id">
+ <div class="tank-option">
+ <div class="tank-option-title">{{ item.tankNo }}</div>
+ <div class="tank-option-line">澶х被锛歿{ item.category }}</div>
+ <div class="tank-option-line">娌瑰搧锛歿{ item.oilProduct }}</div>
+ <div class="tank-option-line">缃愬锛歿{ item.capacity }}</div>
+ <div class="tank-option-line">搴撳瓨浣欓噺(m鲁)锛歿{ item.remaining }}</div>
+ <div class="tank-option-line">绉熷淇℃伅锛歿{ item.tenantInfo || '--' }}</div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍑哄簱鏃ユ湡"
+ prop="outDate"
+ :rules="[{ required: true, message: '璇烽�夋嫨鍑哄簱鏃ユ湡', trigger: 'change' }]">
+ <el-date-picker v-model="formState.outDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="娌瑰搧"
+ prop="oilProduct"
+ :rules="isOilProduct ? [
+ {
+ required: true,
+ message: '璇烽�夋嫨娌瑰搧',
+ trigger: 'change',
+ }
+ ] : []">
+ <el-input v-if="isOilProduct"
+ :model-value="formState.oilProduct"
+ readonly
+ placeholder="--" />
+ <el-select v-else
+ v-model="formState.oilProduct"
+ placeholder="璇烽�夋嫨"
+ disabled
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍑哄簱鍚ㄤ綅(鍚�)">
+ <el-input :model-value="outTonnage === null ? '--' : outTonnage"
+ readonly />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="8">
+ <el-form-item label="瀹㈡埛鍚嶇О"
+ prop="customerId"
+ :rules="[{ required: true, message: '璇烽�夋嫨瀹㈡埛鍚嶇О', trigger: 'change' }]">
+ <el-select v-model="formState.customerId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ filterable
+ popper-class="customer-select-popper"
+ style="width: 100%"
+ @change="customerChange">
+ <el-option v-for="item in customerList"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.id">
+ <div class="customer-option">
+ <div class="customer-option-title">{{ item.customerName }}</div>
+ <div class="customer-option-line">閾惰鍩烘湰鎴凤細{{ item.basicBankAccount }}</div>
+ <div class="customer-option-line">閾惰璐﹀彿锛歿{ item.bankAccount }}</div>
+ <div class="customer-option-line">鍦板潃鍙婅仈绯绘柟寮忥細{{ item.addressPhone }}</div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀹㈡埛瀵规帴浜�"
+ prop="contactPerson"
+ :rules="[{ required: true, message: '璇疯緭鍏ュ鎴峰鎺ヤ汉', trigger: 'blur' }]">
+ <el-input v-model="formState.contactPerson"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀵规帴浜虹數璇�"
+ prop="contactPhone"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ュ鎺ヤ汉鐢佃瘽', trigger: 'blur' },
+ { pattern: /^1[3-9]\d{9}$/, message: '璇疯緭鍏ユ湁鏁堢殑11浣嶆墜鏈哄彿鐮�', trigger: 'blur' }
+ ]">
+ <el-input v-model="formState.contactPhone"
+ placeholder="璇疯緭鍏�11浣嶆暟瀛�"
+ maxlength="11"
+ @input="phoneInput('contactPhone')"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">瑁呮补鎿嶄綔淇℃伅</div>
+ <el-row :gutter="30">
+ <el-col :span="8">
+ <el-form-item label="杞︿綋/閾呭皝妫�楠屾槸鍚︽甯�"
+ prop="loadingInspectionStatus"
+ :rules="[{ required: true, message: '璇烽�夋嫨杞︿綋/閾呭皝妫�楠屾槸鍚︽甯�', trigger: 'change' }]">
+ <el-radio-group v-model="formState.loadingInspectionStatus">
+ <el-radio value="姝e父">姝e父</el-radio>
+ <el-radio value="寮傚父">寮傚父</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瑁呰溅楣や綅"
+ prop="loadingCranePosition"
+ :rules="[{ required: true, message: '璇烽�夋嫨瑁呰溅楣や綅', trigger: 'change' }]">
+ <el-select v-model="formState.loadingCranePosition"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="1#鎾"
+ value="1#鎾" />
+ <el-option label="2#鎾"
+ value="2#鎾" />
+ <el-option label="涓存椂娉�"
+ value="涓存椂娉�" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀵嗗害"
+ prop="density"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ュ瘑搴�', trigger: 'blur' },
+ { pattern: /^\d+(\.\d{1,2})?$/, message: '璇疯緭鍏ユ暟瀛楋紝鏈�澶氫繚鐣欎袱浣嶅皬鏁�', trigger: 'blur' },
+ ]">
+ <el-input v-model="formState.density"
+ placeholder="璇疯緭鍏ユ暟瀛楋紝鏈�澶氫繚鐣欎袱浣嶅皬鏁�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="瑁呮补鍏抽敭鐜妭涓庤溅杈嗗叧閿綅缃媿鐓�"
+ prop="loadingPhotos"
+ :rules="[{ required: true, message: '璇蜂笂浼犺娌瑰叧閿幆鑺備笌杞﹁締鍏抽敭浣嶇疆鎷嶇収', trigger: 'change' }]">
+ <ImageUpload v-model:file-list="formState.loadingPhotos"
+ :limit="10" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">杩囩鏁版嵁</div>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="姣涢噸(鍚�)"
+ prop="grossWeight"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ユ瘺閲�', trigger: 'blur' },
+ { pattern: /^\d+$/, message: '鍙兘杈撳叆鏁存暟鏁板瓧', trigger: 'blur' },
+ ]">
+ <el-input v-model="formState.grossWeight"
+ placeholder="璇疯緭鍏ユ暣鏁版暟瀛�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐨噸(鍚�)"
+ prop="tareWeight"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ョ毊閲�', trigger: 'blur' },
+ { pattern: /^\d+$/, message: '鍙兘杈撳叆鏁存暟鏁板瓧', trigger: 'blur' },
+ ]">
+ <el-input v-model="formState.tareWeight"
+ placeholder="璇疯緭鍏ユ暣鏁版暟瀛�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="8">
+ <el-form-item label="鍑�閲�(鍚�)">
+ <el-input :model-value="netWeight === null ? '--' : netWeight"
+ readonly />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="浜忛噺(鍚�)">
+ <el-input :model-value="lossQuantity === null ? '--' : lossQuantity"
+ readonly />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀹為檯鍏ュ簱浣撶Н(鍗�)">
+ <el-input :model-value="actualVolume"
+ readonly />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="纾呭崟涓婁紶"
+ prop="poundPhotos"
+ :rules="[{ required: true, message: '璇蜂笂浼犵鍗�', trigger: 'change' }]">
+ <ImageUpload v-model:file-list="formState.poundPhotos"
+ :limit="10" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">鐗╂祦淇℃伅</div>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍙告満濮撳悕"
+ prop="driverName"
+ :rules="[{ required: true, message: '璇疯緭鍏ュ徃鏈哄鍚�', trigger: 'blur' }]">
+ <el-input v-model="formState.driverName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍙告満鐢佃瘽"
+ prop="driverPhone"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ュ徃鏈虹數璇�', trigger: 'blur' },
+ { pattern: /^1[3-9]\d{9}$/, message: '璇疯緭鍏ユ湁鏁堢殑11浣嶆墜鏈哄彿鐮�', trigger: 'blur' }
+ ]">
+ <el-input v-model="formState.driverPhone"
+ placeholder="璇疯緭鍏�11浣嶆暟瀛�"
+ maxlength="11"
+ @input="phoneInput('driverPhone')"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鎶艰繍鍛樺鍚�"
+ prop="escortName"
+ :rules="[{ required: true, message: '璇疯緭鍏ユ娂杩愬憳濮撳悕', trigger: 'blur' }]">
+ <el-input v-model="formState.escortName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎶艰繍鍛樼數璇�"
+ prop="escortPhone"
+ :rules="[
+ { required: true, message: '璇疯緭鍏ユ娂杩愬憳鐢佃瘽', trigger: 'blur' },
+ { pattern: /^1[3-9]\d{9}$/, message: '璇疯緭鍏ユ湁鏁堢殑11浣嶆墜鏈哄彿鐮�', trigger: 'blur' }
+ ]">
+ <el-input v-model="formState.escortPhone"
+ placeholder="璇疯緭鍏�11浣嶆暟瀛�"
+ maxlength="11"
+ @input="phoneInput('escortPhone')"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="杞︾墝鍙�"
+ prop="truckPlateNo"
+ :rules="[{ required: true, message: '璇疯緭鍏ヨ溅鐗屽彿', trigger: 'blur' }]">
+ <el-input v-model="formState.truckPlateNo"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="杞︽寕鐗屽彿"
+ prop="trailerPlateNo"
+ :rules="[{ required: true, message: '璇疯緭鍏ヨ溅鎸傜墝鍙�', trigger: 'blur' }]">
+ <el-input v-model="formState.trailerPlateNo"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="handleSubmit">纭</el-button>
+ <el-button @click="closeModal">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <!-- 浜у搧閫夋嫨寮圭獥 -->
+ <ProductSelectDialog v-model="showProductSelectDialog"
+ @confirm="handleProductSelect"
+ single />
+ </div>
+</template>
+
+<script setup>
+ import { ref, computed, getCurrentInstance, onMounted } from "vue";
+ import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+ import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
+ import { addOilOutRecordOnly } from "@/api/inventoryManagement/stockInventory.js";
+ import { allOilDepot } from "@/api/basicData/oilDepot.js";
+ import { allTankInfo } from "@/api/basicData/tankInfo.js";
+ import { listCustomer } from "@/api/basicData/customer.js";
+ import { productTreeList } from "@/api/basicData/product.js";
+
+ const props = defineProps({
+ visible: {
+ type: Boolean,
+ required: true,
+ },
+ });
+
+ const emit = defineEmits(["update:visible", "completed"]);
+
+ const buildEmptyForm = () => ({
+ productId: undefined,
+ productModelId: undefined,
+ productName: "",
+ model: "",
+ unit: "",
+ outCategory: undefined,
+ oilDepotId: undefined,
+ oilDepotName: "",
+ tankId: undefined,
+ tankNo: "",
+ outDate: "",
+ oilProduct: undefined,
+ customerId: undefined,
+ customerName: "",
+ contactPerson: "",
+ contactPhone: "",
+ loadingInspectionStatus: undefined,
+ loadingCranePosition: undefined,
+ loadingPhotos: [],
+ density: undefined,
+ grossWeight: undefined,
+ tareWeight: undefined,
+ poundPhotos: [],
+ driverName: "",
+ driverPhone: "",
+ escortName: "",
+ escortPhone: "",
+ truckPlateNo: "",
+ trailerPlateNo: "",
+ });
+
+ const formState = ref(buildEmptyForm());
+
+ const oilDepotList = ref([]);
+ const tankList = ref([]);
+ const customerList = ref([]);
+ const oilProductOptions = ref([]);
+ const showProductSelectDialog = ref(false);
+
+ // 鍦ㄤ骇鍝佹爲涓煡鎵�"娌瑰搧"鍒嗙被鑺傜偣
+ const findOilNode = nodes => {
+ for (const node of nodes || []) {
+ if (node.productName === "娌瑰搧") {
+ return node;
+ }
+ if (node.children && node.children.length) {
+ const found = findOilNode(node.children);
+ if (found) {
+ return found;
+ }
+ }
+ }
+ return null;
+ };
+
+ // 鎵�閫夊晢鍝佸悕绉板懡涓殑娌瑰搧閫夐」锛堟补鍝佽妭鐐瑰瓙椤癸紝鏉ヨ嚜浜у搧缁存姢妯″潡锛�
+ const matchedOilOption = computed(() =>
+ oilProductOptions.value.find(
+ item => item.productName === formState.value.productName
+ )
+ );
+
+ // 鍙湁閫変腑娌瑰搧瀛楁閫夐」閲屾湁鐨勫叿浣撴补鍝佹墠鍚敤娌瑰搧瀛楁锛�"娌瑰搧"澶х被鏈韩涓嶅惎鐢�
+ const isOilProduct = computed(() => !!matchedOilOption.value);
+
+ const isShow = computed({
+ get() {
+ return props.visible;
+ },
+ set(val) {
+ emit("update:visible", val);
+ },
+ });
+
+ // 鍑�閲�(鍚�) = 姣涢噸 - 鐨噸
+ const netWeight = computed(() => {
+ const g = formState.value.grossWeight;
+ const t = formState.value.tareWeight;
+ if ([g, t].some(v => v === null || v === undefined || v === "")) {
+ return null;
+ }
+ return Number(g) - Number(t);
+ });
+
+ // 浜忛噺(鍚�) = 鍑�閲嶇殑璐熸暟
+ const lossQuantity = computed(() => {
+ if (netWeight.value === null) {
+ return null;
+ }
+ return -netWeight.value;
+ });
+
+ // 瀹為檯鍏ュ簱浣撶Н(鍗�) = 瀹為檯鍑�閲�(kg) 梅 瀵嗗害(kg/L)锛屽噣閲嶅惃 脳 1000 杞� kg
+ const actualVolume = computed(() => {
+ const d = formState.value.density;
+ if (netWeight.value === null || d === null || d === undefined || d === "" || Number(d) <= 0) {
+ return 0;
+ }
+ return Math.round(((netWeight.value * 1000) / Number(d)) * 100) / 100;
+ });
+
+ // 鍑哄簱鍚ㄤ綅(鍚�) = 鍑�閲嶏紙闇�姹傛湭缁欏叕寮忥紝鏆傛寜鍑�閲嶅甫鍑猴級
+ const outTonnage = computed(() => netWeight.value);
+
+ let { proxy } = getCurrentInstance();
+
+ const closeModal = () => {
+ proxy.resetForm("formRef");
+ formState.value = buildEmptyForm();
+ isShow.value = false;
+ };
+
+ // 鐢佃瘽杈撳叆闄愬埗锛氬彧鍏佽鏁板瓧锛屾渶澶�11浣�
+ const phoneInput = field => {
+ formState.value[field] = String(formState.value[field] ?? "")
+ .replace(/\D/g, "")
+ .slice(0, 11);
+ };
+
+ // 浜у搧閫夋嫨澶勭悊
+ const handleProductSelect = async products => {
+ if (products && products.length > 0) {
+ const product = products[0];
+ formState.value.productId = product.productId;
+ formState.value.productName = product.productName;
+ formState.value.model = product.model;
+ formState.value.productModelId = product.id;
+ formState.value.unit = product.unit;
+ // 娌瑰搧閫夐」涓庡晢鍝佸悕绉板悓姝ワ細鍛戒腑娌瑰搧閫夐」鍒欒嚜鍔ㄥ甫鍑鸿娌瑰搧锛屾湭鍛戒腑鍒欐竻绌哄苟绂佺敤
+ formState.value.oilProduct = matchedOilOption.value
+ ? product.productName
+ : undefined;
+ showProductSelectDialog.value = false;
+ proxy.$refs["formRef"]?.validateField("productModelId");
+ }
+ };
+
+ // 鍌ㄥ簱閫夋嫨鏀瑰彉锛氳褰曞簱鍚�-鍏徃鍚�
+ const depotChange = id => {
+ const depot = oilDepotList.value.find(item => item.id === id);
+ formState.value.oilDepotName = depot
+ ? `${depot.depotName}-${depot.company || ""}`
+ : "";
+ };
+
+ // 鍌ㄧ綈閫夋嫨鏀瑰彉锛氳褰曞偍缃愬彿
+ const tankChange = id => {
+ const tank = tankList.value.find(item => item.id === id);
+ formState.value.tankNo = tank?.tankNo || "";
+ };
+
+ // 瀹㈡埛閫夋嫨鏀瑰彉锛氱粦瀹氬鎴锋。妗�(绉佹捣)锛岃嚜鍔ㄥ甫鍑哄鎺ヤ汉涓庡鎺ョ數璇�
+ const customerChange = id => {
+ const customer = customerList.value.find(item => item.id === id);
+ if (customer) {
+ formState.value.customerName = customer.customerName || "";
+ formState.value.contactPerson = customer.contactPerson || "";
+ formState.value.contactPhone = customer.contactPhone || "";
+ } else {
+ formState.value.customerName = "";
+ formState.value.contactPerson = "";
+ formState.value.contactPhone = "";
+ }
+ };
+
+ const handleSubmit = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (!formState.value.productModelId) {
+ proxy.$modal.msgError("璇烽�夋嫨浜у搧");
+ return;
+ }
+ // 璁$畻缁撴灉闅忚〃鍗曟彁浜�
+ formState.value.outTonnage = outTonnage.value;
+ formState.value.netWeight = netWeight.value;
+ formState.value.lossQuantity = lossQuantity.value;
+ formState.value.actualVolume = actualVolume.value;
+ // 鐓х墖杞� JSON 瀛楃涓叉彁浜わ紙鍚庣瀛楁涓烘枃鏈瓨鍌級
+ formState.value.loadingPhotos = JSON.stringify(formState.value.loadingPhotos || []);
+ formState.value.poundPhotos = JSON.stringify(formState.value.poundPhotos || []);
+
+ addOilOutRecordOnly(formState.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeModal();
+ emit("completed");
+ });
+ }
+ });
+ };
+
+ onMounted(() => {
+ allOilDepot().then(res => {
+ oilDepotList.value = res?.data || [];
+ });
+ productTreeList().then(res => {
+ const oilNode = findOilNode(res);
+ oilProductOptions.value = oilNode?.children || [];
+ });
+ allTankInfo().then(res => {
+ tankList.value = res?.data || [];
+ });
+ listCustomer({ current: 1, size: 1000, type: 0 }).then(res => {
+ customerList.value = res?.data?.records || [];
+ });
+ });
+</script>
+
+<style scoped lang="scss">
+ // 琛ㄥ崟鍒嗘爮鏍囬锛氳摑鑹茬珫鏉� + 娴呰摑搴曡壊锛岀獊鍑哄垎鍖�
+ .form-section-title {
+ margin: 18px 0 14px;
+ padding: 8px 14px;
+ font-size: 15px;
+ font-weight: 600;
+ color: #1d6fd8;
+ background: linear-gradient(90deg, rgba(64, 158, 255, 0.14), rgba(64, 158, 255, 0.02));
+ border-left: 4px solid #409eff;
+ border-radius: 3px;
+ }
+
+ // 鍌ㄥ簱鍚嶇О涓嬫媺閫夐」锛氬皬鍗$墖鏍峰紡
+ .oil-depot-option {
+ padding: 8px 10px;
+
+ .oil-depot-option-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+ }
+
+ .oil-depot-option-line {
+ font-size: 12px;
+ color: #909399;
+ line-height: 1.8;
+ }
+ }
+
+ // 鍌ㄧ綈鍙蜂笅鎷夐�夐」锛氬皬鍗$墖鏍峰紡
+ .tank-option {
+ padding: 8px 10px;
+
+ .tank-option-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+ }
+
+ .tank-option-line {
+ font-size: 12px;
+ color: #909399;
+ line-height: 1.8;
+ }
+ }
+
+ // 瀹㈡埛鍚嶇О涓嬫媺閫夐」锛氬皬鍗$墖鏍峰紡
+ .customer-option {
+ padding: 8px 10px;
+
+ .customer-option-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+ }
+
+ .customer-option-line {
+ font-size: 12px;
+ color: #909399;
+ line-height: 1.8;
+ }
+ }
+</style>
+
+<style lang="scss">
+ // 涓嬫媺闈㈡澘娓叉煋鍦� body 涓嬶紝闇�鍏ㄥ眬鏍峰紡
+ .oil-depot-select-popper {
+ .el-select-dropdown__item {
+ height: auto;
+ line-height: normal;
+ padding: 4px 0;
+ }
+
+ .oil-depot-option {
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ background-color: #fafbfc;
+
+ &:hover {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+ }
+ }
+ }
+
+ // 鍌ㄧ綈鍙蜂笅鎷夐潰鏉匡紙body 涓嬶紝闇�鍏ㄥ眬鏍峰紡锛�
+ .tank-select-popper {
+ .el-select-dropdown__item {
+ height: auto;
+ line-height: normal;
+ padding: 4px 0;
+ }
+
+ .tank-option {
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ background-color: #fafbfc;
+
+ &:hover {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+ }
+ }
+ }
+
+ // 瀹㈡埛鍚嶇О涓嬫媺闈㈡澘锛坆ody 涓嬶紝闇�鍏ㄥ眬鏍峰紡锛�
+ .customer-select-popper {
+ .el-select-dropdown__item {
+ height: auto;
+ line-height: normal;
+ padding: 4px 0;
+ }
+
+ .customer-option {
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ background-color: #fafbfc;
+
+ &:hover {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+ }
+ }
+ }
+</style>
diff --git a/src/views/inventoryManagement/stockManagement/Record.vue b/src/views/inventoryManagement/stockManagement/Record.vue
index 9ee214c..bdd00b4 100644
--- a/src/views/inventoryManagement/stockManagement/Record.vue
+++ b/src/views/inventoryManagement/stockManagement/Record.vue
@@ -49,6 +49,10 @@
<div style="display: flex; gap: 10px; flex-wrap: nowrap;">
<el-button type="primary"
@click="isShowNewModal = true">鏂板搴撳瓨</el-button>
+ <el-button type="primary"
+ @click="isShowOilInModal = true">鏂板娌瑰搧鍏ュ簱</el-button>
+ <el-button type="primary"
+ @click="isShowOilOutModal = true">鏂板娌瑰搧鍑哄簱</el-button>
<el-button type="info"
plain
icon="Upload"
@@ -77,36 +81,47 @@
width="60" />
<el-table-column label="浜у搧鍚嶇О"
prop="productName"
+ min-width="120"
show-overflow-tooltip />
<el-table-column label="瑙勬牸鍨嬪彿"
prop="model"
+ min-width="120"
show-overflow-tooltip />
<el-table-column label="鍗曚綅"
prop="unit"
+ min-width="70"
show-overflow-tooltip />
<el-table-column label="鎵瑰彿"
prop="batchNo"
+ min-width="150"
show-overflow-tooltip />
<el-table-column label="鍚堟牸搴撳瓨鏁伴噺"
prop="qualifiedQuantity"
+ min-width="110"
show-overflow-tooltip />
<el-table-column label="涓嶅悎鏍煎簱瀛樻暟閲�"
prop="unQualifiedQuantity"
+ min-width="120"
show-overflow-tooltip />
<el-table-column label="鍚堟牸鍐荤粨鏁伴噺"
prop="qualifiedLockedQuantity"
+ min-width="110"
show-overflow-tooltip />
<el-table-column label="涓嶅悎鏍煎喕缁撴暟閲�"
prop="unQualifiedLockedQuantity"
+ min-width="120"
show-overflow-tooltip />
<el-table-column label="搴撳瓨棰勮鏁伴噺"
prop="warnNum"
+ min-width="110"
show-overflow-tooltip />
<el-table-column label="澶囨敞"
prop="remark"
+ min-width="150"
show-overflow-tooltip />
<el-table-column label="鏈�杩戞洿鏂版椂闂�"
prop="updateTime"
+ min-width="160"
show-overflow-tooltip />
<el-table-column fixed="right"
label="鎿嶄綔"
@@ -136,6 +151,12 @@
v-model:visible="isShowNewModal"
:top-product-parent-id="props.productId"
@completed="handleQuery" />
+ <oil-stock-in-dialog v-if="isShowOilInModal"
+ v-model:visible="isShowOilInModal"
+ @completed="handleQuery" />
+ <oil-stock-out-dialog v-if="isShowOilOutModal"
+ v-model:visible="isShowOilOutModal"
+ @completed="handleQuery" />
<subtract-stock-inventory v-if="isShowSubtractModal"
v-model:visible="isShowSubtractModal"
:record="record"
@@ -172,6 +193,12 @@
const NewStockInventory = defineAsyncComponent(() =>
import("@/views/inventoryManagement/stockManagement/New.vue")
);
+ const OilStockInDialog = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/OilStockInDialog.vue")
+ );
+ const OilStockOutDialog = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/OilStockOutDialog.vue")
+ );
const SubtractStockInventory = defineAsyncComponent(() =>
import("@/views/inventoryManagement/stockManagement/Subtract.vue")
);
@@ -196,6 +223,10 @@
const total = ref(0);
// 鏄惁鏄剧ず鏂板寮规
const isShowNewModal = ref(false);
+ // 鏄惁鏄剧ず娌瑰搧鍏ュ簱寮规
+ const isShowOilInModal = ref(false);
+ // 鏄惁鏄剧ず娌瑰搧鍑哄簱寮规
+ const isShowOilOutModal = ref(false);
// 鏄惁鏄剧ず棰嗙敤寮规
const isShowSubtractModal = ref(false);
// 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 7e1576b..087f716 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -161,6 +161,42 @@
prop="projectName"
width="320"
show-overflow-tooltip />
+ <el-table-column label="閲囪喘绫诲埆"
+ prop="purchaseCategory"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="鎻愯揣鏂瑰紡"
+ prop="pickupMethod"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="閲囪喘娌瑰搧"
+ prop="purchaseOilProduct"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="鐗╂祦鏂瑰紡"
+ prop="logisticsMethod"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="閲囪喘娌瑰簱"
+ prop="oilDepotName"
+ width="150"
+ show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛鍚嶇О"
+ prop="customerName"
+ width="150"
+ show-overflow-tooltip />
+ <el-table-column label="鏈�浣冲埌绔欐棩鏈�"
+ prop="bestArrivalDate"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="閲囪喘鏁伴噺锛堝惃锛�"
+ prop="purchaseQuantity"
+ width="120"
+ align="center" />
+ <el-table-column label="閲囪喘鐢宠璁㈠崟鐘舵��"
+ prop="purchaseOrderStatus"
+ width="140"
+ show-overflow-tooltip />
<el-table-column label="瀹℃壒鐘舵��"
prop="approvalStatus"
width="100"
@@ -300,17 +336,10 @@
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="浠樻鏂瑰紡">
- <el-input v-model="form.paymentMethod"
- placeholder="璇疯緭鍏�"
- clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="绛捐鏃ユ湡锛�"
- prop="executionDate">
+ <el-form-item label="鏈�浣冲埌绔欐棩鏈燂細"
+ prop="bestArrivalDate">
<el-date-picker style="width: 100%"
- v-model="form.executionDate"
+ v-model="form.bestArrivalDate"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
type="date"
@@ -318,9 +347,16 @@
clearable />
</el-form-item>
</el-col>
+ <el-col :span="12">
+ <el-form-item label="浠樻鏂瑰紡">
+ <el-input v-model="form.paymentMethod"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
</el-row>
<el-row :gutter="30">
- <el-col :span="12">
+ <el-col :span="8">
<el-form-item label="褰曞叆浜猴細"
prop="recorderId">
<el-select v-model="form.recorderId"
@@ -334,7 +370,19 @@
</el-select>
</el-form-item>
</el-col>
- <el-col :span="12">
+ <el-col :span="8">
+ <el-form-item label="绛捐鏃ユ湡锛�"
+ prop="executionDate">
+ <el-date-picker style="width: 100%"
+ v-model="form.executionDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
<el-form-item label="褰曞叆鏃ユ湡锛�"
prop="entryDate">
<el-date-picker style="width: 100%"
@@ -344,6 +392,144 @@
type="date"
placeholder="璇烽�夋嫨"
clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">閲囪喘鍏ュ簱鎻愪氦</div>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鐢宠鎻愪氦鏃堕棿锛�"
+ prop="applicationSubmitTime">
+ <el-date-picker style="width: 100%"
+ v-model="form.applicationSubmitTime"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ format="YYYY-MM-DD HH:mm:ss"
+ type="datetime"
+ placeholder="璇烽�夋嫨"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閲囪喘绫诲埆锛�"
+ prop="purchaseCategory">
+ <el-radio-group v-model="form.purchaseCategory"
+ @change="purchaseCategoryChange">
+ <el-radio value="瀹㈠瓨">瀹㈠瓨</el-radio>
+ <el-radio value="浠e偍">浠e偍</el-radio>
+ <el-radio value="閲囪喘鍏ュ簱">閲囪喘鍏ュ簱</el-radio>
+ <el-radio value="閲囪喘鐩撮攢">閲囪喘鐩撮攢</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="閲囪喘娌瑰搧锛�"
+ prop="purchaseOilProduct">
+ <el-select v-model="form.purchaseOilProduct"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="姹�#92"
+ value="姹�#92" />
+ <el-option label="姹�#95"
+ value="姹�#95" />
+ <el-option label="鏌�#0"
+ value="鏌�#0" />
+ <el-option label="鏌�#-35"
+ value="鏌�#-35" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐗╂祦鏂瑰紡锛�"
+ prop="logisticsMethod">
+ <el-select v-model="form.logisticsMethod"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="鍘傚閰嶉��"
+ value="鍘傚閰嶉��" />
+ <el-option label="濮斿鐗╂祦"
+ value="濮斿鐗╂祦" />
+ <el-option label="瀹㈡埛鑷彁"
+ value="瀹㈡埛鑷彁" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鎻愯揣鏂瑰紡锛�"
+ prop="pickupMethod">
+ <el-radio-group v-model="form.pickupMethod">
+ <el-radio value="鏆備笉鎻愯揣">鏆備笉鎻愯揣</el-radio>
+ <el-radio value="鎻愯揣">鎻愯揣</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閲囪喘娌瑰簱锛�"
+ prop="oilDepotId">
+ <el-select v-model="form.oilDepotId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ popper-class="oil-depot-select-popper"
+ style="width: 100%">
+ <el-option v-for="item in oilDepotList"
+ :key="item.id"
+ :label="item.depotName"
+ :value="item.id">
+ <div class="oil-depot-option">
+ <div class="oil-depot-option-title">{{ item.depotName }}</div>
+ <div class="oil-depot-option-line">璐熻矗浜猴細{{ item.chargePerson }}</div>
+ <div class="oil-depot-option-line">鑱旂郴鐢佃瘽锛歿{ item.phone }}</div>
+ <div class="oil-depot-option-line">鎵�灞炲叕鍙革細{{ item.company }}</div>
+ <div class="oil-depot-option-line">鍚敤鏃ユ湡锛歿{ item.enableDate }}</div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="瀹㈡埛鍚嶇О锛�"
+ prop="customerName">
+ <el-input v-model="form.customerName"
+ placeholder="浠呴噰璐被鍒负浠e偍/閲囪喘鐩撮攢鏃跺彲濉啓"
+ clearable
+ :disabled="!['浠e偍', '閲囪喘鐩撮攢'].includes(form.purchaseCategory)" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閲囪喘鏁伴噺锛堝惃锛夛細"
+ prop="purchaseQuantity">
+ <el-input-number v-model="form.purchaseQuantity"
+ :precision="0"
+ :step="1"
+ :min="0"
+ placeholder="璇疯緭鍏�"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="form-section-title">绯荤粺淇℃伅</div>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="閲囪喘鐢宠璁㈠崟鐘舵�侊細"
+ prop="purchaseOrderStatus">
+ <el-select v-model="form.purchaseOrderStatus"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="宸茬敵璇凤紝鏈杞�"
+ value="宸茬敵璇凤紝鏈杞�" />
+ <el-option label="浠ュ嚭鍘傦紝鏈叆搴�"
+ value="浠ュ嚭鍘傦紝鏈叆搴�" />
+ <el-option label="宸插叆搴�"
+ value="宸插叆搴�" />
+ </el-select>
</el-form-item>
</el-col>
</el-row>
@@ -733,6 +919,7 @@
delPurchaseTemplate,
batchGeneratePurchaseInboundSteps,
} from "@/api/procurementManagement/procurementLedger.js";
+ import { allOilDepot } from "@/api/basicData/oilDepot.js";
import useFormData from "@/hooks/useFormData.js";
const FileList = defineAsyncComponent(() =>
import("@/components/Dialog/FileList.vue")
@@ -749,6 +936,7 @@
const productOptions = ref([]);
const salesContractList = ref([]);
const supplierList = ref([]);
+ const oilDepotList = ref([]);
const tableLoading = ref(false);
const recordId = ref();
const fileListDialogVisible = ref(false);
@@ -931,6 +1119,16 @@
paymentMethod: "",
executionDate: "",
isChecked: false,
+ purchaseCategory: "",
+ purchaseOilProduct: "",
+ logisticsMethod: "",
+ pickupMethod: "",
+ oilDepotId: "",
+ customerName: "",
+ bestArrivalDate: "",
+ purchaseQuantity: "",
+ purchaseOrderStatus: "",
+ applicationSubmitTime: "",
},
rules: {
purchaseContractNumber: [
@@ -942,6 +1140,18 @@
supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ purchaseCategory: [
+ { required: true, message: "璇烽�夋嫨閲囪喘绫诲埆", trigger: "change" },
+ ],
+ purchaseOilProduct: [
+ { required: true, message: "璇烽�夋嫨閲囪喘娌瑰搧", trigger: "change" },
+ ],
+ oilDepotId: [
+ { required: true, message: "璇烽�夋嫨閲囪喘娌瑰簱", trigger: "change" },
+ ],
+ purchaseQuantity: [
+ { required: true, message: "璇疯緭鍏ラ噰璐暟閲�", trigger: "change" },
+ ],
},
});
const { form, rules } = toRefs(data);
@@ -1311,9 +1521,10 @@
isTemplateNameDuplicate.value = false;
try {
// 骞惰鍔犺浇鍩虹鏁版嵁
- const [salesRes, supplierRes] = await Promise.all([
+ const [salesRes, supplierRes, oilDepotRes] = await Promise.all([
getSalesNo(),
getOptions(),
+ allOilDepot(),
]);
salesContractList.value = salesRes || [];
@@ -1321,6 +1532,7 @@
supplierList.value = (supplierRes.data || []).filter(
item => item.isWhite === 0
);
+ oilDepotList.value = oilDepotRes?.data || [];
form.value.entryDate = getCurrentDate();
@@ -1896,6 +2108,13 @@
}
}
};
+ // 閲囪喘绫诲埆鏀瑰彉锛氫粎浠e偍/閲囪喘鐩撮攢鏃跺鎴峰悕绉板彲鐢紝鍒囨崲鍚庢竻绌�
+ const purchaseCategoryChange = val => {
+ if (!["浠e偍", "閲囪喘鐩撮攢"].includes(val)) {
+ form.value.customerName = "";
+ }
+ };
+
// 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
const salesLedgerChange = async row => {
console.log("row", row);
@@ -1984,6 +2203,18 @@
</script>
<style scoped lang="scss">
+ // 琛ㄥ崟鍒嗘爮鏍囬锛氳摑鑹茬珫鏉� + 娴呰摑搴曡壊锛岀獊鍑哄垎鍖�
+ .form-section-title {
+ margin: 18px 0 14px;
+ padding: 8px 14px;
+ font-size: 15px;
+ font-weight: 600;
+ color: #1d6fd8;
+ background: linear-gradient(90deg, rgba(64, 158, 255, 0.14), rgba(64, 158, 255, 0.02));
+ border-left: 4px solid #409eff;
+ border-radius: 3px;
+ }
+
.invalid-row {
opacity: 0.6;
background-color: #f5f7fa;
@@ -2001,6 +2232,24 @@
.select-button-group {
display: flex;
align-items: center;
+ }
+
+ // 閲囪喘娌瑰簱涓嬫媺閫夐」锛氬皬鍗$墖鏍峰紡
+ .oil-depot-option {
+ padding: 8px 10px;
+
+ .oil-depot-option-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+ }
+
+ .oil-depot-option-line {
+ font-size: 12px;
+ color: #909399;
+ line-height: 1.8;
+ }
}
// 瀹℃壒浜鸿妭鐐瑰鍣ㄦ牱寮�
@@ -2064,3 +2313,25 @@
}
}
</style>
+
+<style lang="scss">
+ // 涓嬫媺闈㈡澘娓叉煋鍦� body 涓嬶紝闇�鍏ㄥ眬鏍峰紡
+ .oil-depot-select-popper {
+ .el-select-dropdown__item {
+ height: auto;
+ line-height: normal;
+ padding: 4px 0;
+ }
+
+ .oil-depot-option {
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ background-color: #fafbfc;
+
+ &:hover {
+ border-color: #409eff;
+ background-color: #f0f7ff;
+ }
+ }
+ }
+</style>
--
Gitblit v1.9.3