From 63afcf7bd6eff23e4feee8b6d12053bd8e78abb8 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期六, 09 五月 2026 17:38:10 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_NEW_pro
---
src/views/inventoryManagement/dispatchLog/Record.vue | 11
src/views/customerService/feedbackRegistration/components/formDia.vue | 895 +++++++++++----------
src/views/equipmentManagement/operationManagement/index.vue | 132 +++
src/views/customerService/expiryAfterSales/index.vue | 6
src/views/inventoryManagement/stockReport/index.vue | 1251 +++++++++++++++---------------
src/views/inventoryManagement/receiptManagement/Record.vue | 11
src/views/customerService/expiryAfterSales/components/formDia.vue | 92 +
7 files changed, 1,272 insertions(+), 1,126 deletions(-)
diff --git a/src/views/customerService/expiryAfterSales/components/formDia.vue b/src/views/customerService/expiryAfterSales/components/formDia.vue
index 2fe603b..d899b8d 100644
--- a/src/views/customerService/expiryAfterSales/components/formDia.vue
+++ b/src/views/customerService/expiryAfterSales/components/formDia.vue
@@ -20,7 +20,7 @@
v-model="form.productName"
placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('productName')"
/>
</el-form-item>
</el-col>
@@ -30,7 +30,7 @@
v-model="form.batchNumber"
placeholder="璇疯緭鍏ヤ骇鍝佹壒鍙�"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('batchNumber')"
/>
</el-form-item>
</el-col>
@@ -46,7 +46,7 @@
type="date"
placeholder="璇烽�夋嫨涓存湡鏃ユ湡"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('expiryDate')"
/>
</el-form-item>
</el-col>
@@ -57,7 +57,7 @@
:min="0"
placeholder="璇疯緭鍏ュ簱瀛樻暟閲�"
style="width: 100%"
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('stockQuantity')"
/>
</el-form-item>
</el-col>
@@ -69,7 +69,7 @@
v-model="form.customerName"
placeholder="璇疯緭鍏ュ鎴峰悕绉�"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('customerName')"
/>
</el-form-item>
</el-col>
@@ -79,7 +79,7 @@
v-model="form.contactPhone"
placeholder="璇疯緭鍏ヨ仈绯荤數璇�"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('contactPhone')"
/>
</el-form-item>
</el-col>
@@ -91,7 +91,7 @@
v-model="form.problemDesc"
placeholder="璇疯緭鍏ラ棶棰樻弿杩�"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('problemDesc')"
type="textarea"
:rows="3"
/>
@@ -105,7 +105,7 @@
v-model="form.handlerId"
placeholder="璇烽�夋嫨澶勭悊浜�"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('handlerId')"
style="width: 100%"
>
<el-option
@@ -127,7 +127,7 @@
type="date"
placeholder="璇烽�夋嫨澶勭悊鏃ユ湡"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('handleDate')"
/>
</el-form-item>
</el-col>
@@ -139,7 +139,7 @@
v-model="form.handleResult"
placeholder="璇疯緭鍏ュ鐞嗙粨鏋�"
clearable
- :disabled="operationType === 'view'"
+ :disabled="isFieldDisabled('handleResult')"
type="textarea"
:rows="3"
/>
@@ -175,6 +175,8 @@
return '鏂板涓存湡鍞悗';
case 'edit':
return '缂栬緫涓存湡鍞悗';
+ case 'handle':
+ return '澶勭悊涓存湡鍞悗';
case 'view':
return '鏌ョ湅涓存湡鍞悗';
default:
@@ -212,6 +214,13 @@
})
const { form, rules } = toRefs(data);
const userList = ref([])
+const handleEditableFields = ["handlerId", "handleDate", "handleResult"];
+
+const isFieldDisabled = (field) => {
+ if (operationType.value === "view") return true;
+ if (operationType.value === "handle") return !handleEditableFields.includes(field);
+ return false;
+};
// 鎵撳紑寮规
const openDialog = (type, row) => {
@@ -242,7 +251,7 @@
} else {
// 缂栬緫鎴栨煡鐪嬫椂濉厖鏁版嵁
form.value = { ...row };
- if (type === 'edit' && !form.value.handlerId) {
+ if (type === 'handle' && !form.value.handlerId) {
form.value.handlerId = userStore.id;
form.value.handleDate = getCurrentDate();
}
@@ -250,36 +259,49 @@
}
const submitForm = () => {
+ if (operationType.value === "handle") {
+ if (!form.value.handlerId || !form.value.handleDate || !form.value.handleResult) {
+ proxy.$modal.msgWarning("璇峰~鍐欏鐞嗕汉銆佸鐞嗘棩鏈熷拰澶勭悊缁撴灉");
+ return;
+ }
+ handleSubmit();
+ return;
+ }
proxy.$refs["formRef"].validate(valid => {
if (valid) {
- const submitData = {
- id: form.value.id,
- productName: form.value.productName,
- batchNumber: form.value.batchNumber,
- expireDate: form.value.expiryDate,
- stockQuantity: form.value.stockQuantity,
- customerName: form.value.customerName,
- contactPhone: form.value.contactPhone,
- disRes: form.value.problemDesc,
- status: form.value.status,
- disposeUserId: form.value.handlerId,
- disposeNickName: userList.value.find(item => item.userId === form.value.handlerId)?.nickName,
- disposeResult: form.value.handleResult,
- disDate: form.value.handleDate
- };
-
- const apiCall = operationType.value === 'add' ? expiryAfterSalesAdd : expiryAfterSalesUpdate;
- apiCall(submitData).then(() => {
- proxy.$modal.msgSuccess(operationType.value === 'add' ? "鏂板鎴愬姛" : "鏇存柊鎴愬姛");
- closeDia();
- }).catch(error => {
- console.error('鎻愪氦鏁版嵁澶辫触:', error);
- proxy.$modal.msgError('鎻愪氦鏁版嵁澶辫触锛岃绋嶅悗閲嶈瘯');
- });
+ handleSubmit();
}
});
}
+const handleSubmit = () => {
+ const submitData = {
+ id: form.value.id,
+ productName: form.value.productName,
+ batchNumber: form.value.batchNumber,
+ expireDate: form.value.expiryDate,
+ stockQuantity: form.value.stockQuantity,
+ customerName: form.value.customerName,
+ contactPhone: form.value.contactPhone,
+ disRes: form.value.problemDesc,
+ status: operationType.value === "handle" ? 2 : form.value.status,
+ disposeUserId: form.value.handlerId,
+ disposeNickName: userList.value.find(item => item.userId === form.value.handlerId)?.nickName,
+ disposeResult: form.value.handleResult,
+ disDate: form.value.handleDate
+ };
+
+ const apiCall = operationType.value === 'add' ? expiryAfterSalesAdd : expiryAfterSalesUpdate;
+ apiCall(submitData).then(() => {
+ const successText = operationType.value === "add" ? "鏂板鎴愬姛" : operationType.value === "handle" ? "澶勭悊鎴愬姛" : "鏇存柊鎴愬姛";
+ proxy.$modal.msgSuccess(successText);
+ closeDia();
+ }).catch(error => {
+ console.error('鎻愪氦鏁版嵁澶辫触:', error);
+ proxy.$modal.msgError('鎻愪氦鏁版嵁澶辫触锛岃绋嶅悗閲嶈瘯');
+ });
+}
+
// 鍏抽棴寮规
const closeDia = () => {
proxy.resetForm("formRef");
diff --git a/src/views/customerService/expiryAfterSales/index.vue b/src/views/customerService/expiryAfterSales/index.vue
index c94e3dd..9966785 100644
--- a/src/views/customerService/expiryAfterSales/index.vue
+++ b/src/views/customerService/expiryAfterSales/index.vue
@@ -39,7 +39,7 @@
<el-button type="danger" @click="handleDelete">鍒犻櫎</el-button>
</div>
</div>
-
+
<div class="table_list">
<PIMTable
rowKey="id"
@@ -60,7 +60,7 @@
<template #operation="{ row }">
<el-button type="primary" link @click="openForm('view', row)">鏌ョ湅</el-button>
- <el-button type="primary" link @click="openForm('edit', row)" v-if="row.status === 1">缂栬緫</el-button>
+ <el-button type="primary" link @click="openForm('handle', row)" v-if="row.status === 1">澶勭悊</el-button>
</template>
</PIMTable>
</div>
@@ -201,7 +201,7 @@
current: page.value.current,
size: page.value.size
};
-
+
expiryAfterSalesListPage(queryParams).then(res => {
// 鏄犲皠鍚庣杩斿洖鏁版嵁鍒板墠绔〃鏍�
tableData.value = res.data.records.map(item => ({
diff --git a/src/views/customerService/feedbackRegistration/components/formDia.vue b/src/views/customerService/feedbackRegistration/components/formDia.vue
index 5c9e565..790ddbe 100644
--- a/src/views/customerService/feedbackRegistration/components/formDia.vue
+++ b/src/views/customerService/feedbackRegistration/components/formDia.vue
@@ -1,490 +1,507 @@
<template>
<div>
- <el-dialog
- v-model="dialogFormVisible"
- title="鏂板鍞悗鍗�"
- width="90%"
- @close="closeDia"
- >
+ <el-dialog v-model="dialogFormVisible"
+ title="鏂板鍞悗鍗�"
+ width="90%"
+ @close="closeDia">
<div>
<span class="descriptions">鍩虹璧勬枡</span>
- <el-form
- :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef"
- >
+ <el-form :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef">
<el-row :gutter="30">
<el-col :span="4">
- <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerName">
- <el-select
- v-model="form.customerName"
- filterable
- @change="customerNameChange"
- >
- <el-option
- v-for="item in customerNameOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
+ <el-form-item label="瀹㈡埛鍚嶇О锛�"
+ prop="customerName">
+ <el-select v-model="form.customerName"
+ filterable
+ @change="customerNameChange">
+ <el-option v-for="item in customerNameOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鍞悗绫诲瀷锛�" prop="serviceType">
- <el-select
- v-model="form.serviceType"
- filterable
- >
- <el-option
- v-for="dict in serviceTypeOptions"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
+ <el-form-item label="鍞悗绫诲瀷锛�"
+ prop="serviceType">
+ <el-select v-model="form.serviceType"
+ filterable>
+ <el-option v-for="dict in serviceTypeOptions"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鍏宠仈閿�鍞崟鍙凤細" prop="salesContractNo">
- <el-select
- v-model="form.salesContractNo"
- @change="associatedSalesOrderNumberChange"
- filterable
- >
- <el-option
- v-for="item in associatedSalesOrderNumberOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
+ <el-form-item label="鍏宠仈閿�鍞崟鍙凤細"
+ prop="salesContractNo">
+ <el-select v-model="form.salesContractNo"
+ @change="associatedSalesOrderNumberChange"
+ filterable>
+ <el-option v-for="item in associatedSalesOrderNumberOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="绱ф�ョ▼搴︼細" prop="urgency">
- <el-select
- v-model="form.urgency"
- filterable
- >
- <el-option
- v-for="dict in urgencyOptions"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
+ <el-form-item label="绱ф�ョ▼搴︼細"
+ prop="urgency">
+ <el-select v-model="form.urgency"
+ filterable>
+ <el-option v-for="dict in urgencyOptions"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="闂鎻忚堪锛�" prop="proDesc">
- <el-input
- v-model="form.proDesc"
- placeholder="璇疯緭鍏ラ棶棰樻弿杩�"
- />
+ <el-form-item label="闂鎻忚堪锛�"
+ prop="proDesc">
+ <el-input v-model="form.proDesc"
+ placeholder="璇疯緭鍏ラ棶棰樻弿杩�" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<hr>
- <div style="padding-top: 20px">
- <div style="display: flex; justify-content: space-between">
- <span class="descriptions">鍏宠仈浜у搧</span>
- <el-button
- type="primary"
- style="margin-right: 12px; margin-bottom: 10px"
- @click="isShowProductSelectDialog = true"
- >
+ <div style="padding-top: 20px">
+ <div style="display: flex; justify-content: space-between">
+ <span class="descriptions">鍏宠仈浜у搧</span>
+ <el-button type="primary"
+ style="margin-right: 12px; margin-bottom: 10px"
+ @click="isShowProductSelectDialog = true">
閫夋嫨浜у搧
</el-button>
- </div>
- <PIMTable
- :isShowPagination="false"
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- >
- <template #approveStatus="{ row }">
- <el-tag :type="getApproveStatusType(row)" size="small">
- {{ getApproveStatusText(row) }}
- </el-tag>
- </template>
- <template #shippingStatus="{ row }">
- <el-tag :type="getShippingStatusType(row)" size="small">
- {{ getShippingStatusText(row) }}
- </el-tag>
- </template>
- </PIMTable>
</div>
+ <PIMTable :isShowPagination="false"
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData">
+ <template #approveStatus="{ row }">
+ <el-tag :type="getApproveStatusType(row)"
+ size="small">
+ {{ getApproveStatusText(row) }}
+ </el-tag>
+ </template>
+ <template #shippingStatus="{ row }">
+ <el-tag :type="getShippingStatusType(row)"
+ size="small">
+ {{ getShippingStatusText(row) }}
+ </el-tag>
+ </template>
+ </PIMTable>
+ </div>
</div>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭</el-button>
- <el-button @click="closeDia">鍙栨秷</el-button>
- </div>
- </template>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
</el-dialog>
<!-- 閫夋嫨浜у搧寮圭獥 -->
- <ProductSelectDialog
- v-model="isShowProductSelectDialog"
- :products="currentSalesOrderProducts"
- :selected-ids="currentSelectedProductIds"
- @confirm="handleSelectProducts"
- />
+ <ProductSelectDialog v-model="isShowProductSelectDialog"
+ :products="currentSalesOrderProducts"
+ :selected-ids="currentSelectedProductIds"
+ @confirm="handleSelectProducts" />
</div>
</template>
<script setup>
-import { ref, reactive, toRefs, getCurrentInstance, computed } from "vue";
-import ProductSelectDialog from "./ProductSelectDialog.vue";
-import useUserStore from "@/store/modules/user.js";
-import {userListNoPageByTenantId} from "@/api/system/user.js";
-import {afterSalesServiceAdd, afterSalesServiceUpdate, getAllCustomerList, getSalesLedger } from "@/api/customerService/index.js";
-import { getCurrentDate } from "@/utils/index.js";
-const { proxy } = getCurrentInstance()
-const emit = defineEmits(['close'])
-const dialogFormVisible = ref(false);
-const operationType = ref('')
-const formRef = ref(null)
-const customerNameOptions = ref([])
-const userStore = useUserStore();
+ import { ref, reactive, toRefs, getCurrentInstance, computed } from "vue";
+ import ProductSelectDialog from "./ProductSelectDialog.vue";
+ import useUserStore from "@/store/modules/user.js";
+ import { userListNoPageByTenantId } from "@/api/system/user.js";
+ import {
+ afterSalesServiceAdd,
+ afterSalesServiceUpdate,
+ getAllCustomerList,
+ getSalesLedger,
+ } from "@/api/customerService/index.js";
+ import { getCurrentDate } from "@/utils/index.js";
+ const { proxy } = getCurrentInstance();
+ const emit = defineEmits(["close"]);
+ const dialogFormVisible = ref(false);
+ const operationType = ref("");
+ const formRef = ref(null);
+ const customerNameOptions = ref([]);
+ const userStore = useUserStore();
-const data = reactive({
- form: {
- topic: "",
- serviceType: "",
- urgency: "",
- salesLedgerId: null,
- productModelIds: "",
- customerId: null,
- salesContractNo: "",
- proDesc: "",
- customerName: ""
- },
- rules: {
- customerName: [{required: true, message: "璇烽�夋嫨瀹㈡埛鍚嶇О", trigger: "change"}],
- serviceType: [{required: true, message: "璇烽�夋嫨鍞悗绫诲瀷", trigger: "change"}],
- urgency: [{required: true, message: "璇烽�夋嫨绱ф�ョ▼搴�", trigger: "change"}],
- feedbackDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
- }
-})
-
-// 鑷畾涔夋牎楠屽嚱鏁帮細鍒ゆ柇鏄惁闇�瑕佹牎楠屽敭鍚庣紪鍙�
-
-const { form, rules } = toRefs(data);
-const userList = ref([])
-
-const formatCurrency = (val) => {
- if (val === null || val === undefined || val === '') return '-'
- const num = Number(val)
- return Number.isFinite(num) ? num.toFixed(2) : '-'
-}
-
-const { post_sale_waiting_list, degree_of_urgency } = proxy.useDict(
- "post_sale_waiting_list",
- "degree_of_urgency"
-);
-
-const serviceTypeOptions = computed(() => post_sale_waiting_list?.value || []);
-const urgencyOptions = computed(() => degree_of_urgency?.value || []);
-
-const getProductRowId = (row) => {
- return row?.id ?? row?.productModelId ?? row?.modelId ?? `${row?.productCategory || row?.productName || ""}-${row?.specificationModel || row?.model || ""}-${row?.unit || ""}`
-}
-
-const normalizeProductRow = (row) => {
- return {
- ...row,
- id: getProductRowId(row),
- productCategory: row?.productCategory ?? row?.productName ?? '',
- specificationModel: row?.specificationModel ?? row?.model ?? '',
- unit: row?.unit ?? '',
- approveStatus: row?.approveStatus ?? null,
- shippingStatus: row?.shippingStatus ?? '',
- expressCompany: row?.expressCompany ?? '',
- expressNumber: row?.expressNumber ?? '',
- shippingCarNumber: row?.shippingCarNumber ?? '',
- shippingDate: row?.shippingDate ?? '',
- quantity: row?.quantity ?? 0,
- taxRate: row?.taxRate ?? 0,
- taxInclusiveUnitPrice: row?.taxInclusiveUnitPrice ?? 0,
- taxInclusiveTotalPrice: row?.taxInclusiveTotalPrice ?? 0,
- taxExclusiveTotalPrice: row?.taxExclusiveTotalPrice ?? 0,
- noQuantity: row?.noQuantity ?? 0,
- }
-}
-
-const tableColumn = ref([
- { label: "浜у搧澶х被", prop: "productCategory" },
- { label: "瑙勬牸鍨嬪彿", prop: "specificationModel" },
- { label: "鍗曚綅", prop: "unit" },
- {
- label: "浜у搧鐘舵��",
- prop: "approveStatus",
- width: 100,
- align: "center",
- dataType: "slot",
- slot: "approveStatus",
- },
- {
- label: "鍙戣揣鐘舵��",
- align: "center",
- width: 140,
- dataType: "slot",
- slot: "shippingStatus",
- },
- { label: "蹇�掑叕鍙�", prop: "expressCompany", width: 140 },
- { label: "蹇�掑崟鍙�", prop: "expressNumber", width: 160 },
- { label: "鍙戣揣杞︾墝", prop: "shippingCarNumber", minWidth: 100, align: "center" },
- { label: "鍙戣揣鏃ユ湡", prop: "shippingDate", minWidth: 100, align: "center" },
- { label: "鏁伴噺", prop: "quantity", width: 100 },
- { label: "绋庣巼(%)", prop: "taxRate", width: 100 },
- {
- label: "鍚◣鍗曚环(鍏�)",
- prop: "taxInclusiveUnitPrice",
- width: 160,
- formatData: formatCurrency,
- },
- {
- label: "鍚◣鎬讳环(鍏�)",
- prop: "taxInclusiveTotalPrice",
- width: 160,
- formatData: formatCurrency,
- },
- {
- label: "涓嶅惈绋庢�讳环(鍏�)",
- prop: "taxExclusiveTotalPrice",
- width: 160,
- formatData: formatCurrency,
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: 'right',
- operation: [
- {
- name: "鍒犻櫎",
- type: "text",
- clickFun: (row) => {
- tableData.value = tableData.value.filter(i => getProductRowId(i) !== getProductRowId(row))
- },
-
- },
- ],
- },
-])
-const tableData = ref([])
-// 閫夋嫨浜у搧寮圭獥
-const isShowProductSelectDialog = ref(false)
-const handleSelectProducts = (rows) => {
- if (!Array.isArray(rows)) return
- const existingIds = new Set(tableData.value.map(i => String(getProductRowId(i))))
- const mapped = rows
- .map(normalizeProductRow)
- .filter(r => !existingIds.has(String(getProductRowId(r))))
- tableData.value = tableData.value.concat(mapped)
-}
-const currentSelectedProductIds = computed(() => {
- return tableData.value.map(item => getProductRowId(item)).filter(item => item !== undefined && item !== null && item !== '')
-})
-
-const associatedSalesOrderNumberChange = () => {
- const opt = associatedSalesOrderNumberOptions.value.find(
- (item) => item.value === form.value.salesContractNo
- )
- tableData.value = (opt?.productData || []).map(normalizeProductRow)
- form.value.salesLedgerId = opt?.id || null
-}
-
-const associatedSalesOrderNumberOptions = ref([])
-
-const currentSalesOrderProducts = computed(() => {
- const opt = associatedSalesOrderNumberOptions.value.find(
- (item) => item.value === form.value.salesContractNo
- )
- return (opt?.productData || []).map(normalizeProductRow)
-})
-
-const customerNameChange = (val) => {
- form.value.salesContractNo = "";
- form.value.salesLedgerId = null;
- tableData.value = [];
- associatedSalesOrderNumberOptions.value = [];
- const opt = customerNameOptions.value.find(item => item.value === val);
- if (opt) {
- form.value.customerId = opt.id;
- } else {
- form.value.customerId = null;
- }
- getSalesLedger({
- customerName: form.value.customerName
- }).then(res => {
- if(res.code === 200){
- associatedSalesOrderNumberOptions.value = res.data.records.map(item => ({
- label: item.salesContractNo,
- value: item.salesContractNo,
- productData:item.productData,
- id: item.id
- }))
- }
- })
-}
-
-const getApproveStatusText = (row) => {
- if (!row) return '涓嶈冻'
- if (row.approveStatus === 1 && (!row.shippingDate || !row.shippingCarNumber)) {
- return '鍏呰冻'
- }
- if (row.approveStatus === 0 && (row.shippingDate || row.shippingCarNumber)) {
- return '宸插嚭搴�'
- }
- return '涓嶈冻'
-}
-
-const getApproveStatusType = (row) => {
- const statusText = getApproveStatusText(row)
- return statusText === '涓嶈冻' ? 'danger' : 'success'
-}
-
-const getShippingStatusText = (row) => {
- if (!row) return '寰呭彂璐�'
- if (row.shippingDate || row.shippingCarNumber) {
- return '宸插彂璐�'
- }
- const status = row.shippingStatus
- if (status === null || status === undefined || status === '') {
- return '寰呭彂璐�'
- }
- const map = {
- '寰呭彂璐�': '寰呭彂璐�',
- '寰呭鏍�': '寰呭鏍�',
- '瀹℃牳涓�': '瀹℃牳涓�',
- '瀹℃牳鎷掔粷': '瀹℃牳鎷掔粷',
- '瀹℃牳閫氳繃': '瀹℃牳閫氳繃',
- '宸插彂璐�': '宸插彂璐�'
- }
- return map[String(status).trim()] || '寰呭彂璐�'
-}
-
-const getShippingStatusType = (row) => {
- if (!row) return 'info'
- if (row.shippingDate || row.shippingCarNumber) {
- return 'success'
- }
- const status = row.shippingStatus
- if (status === null || status === undefined || status === '') {
- return 'info'
- }
- const map = {
- '寰呭彂璐�': 'info',
- '寰呭鏍�': 'warning',
- '瀹℃牳涓�': 'warning',
- '瀹℃牳鎷掔粷': 'danger',
- '瀹℃牳閫氳繃': 'success',
- '宸插彂璐�': 'success'
- }
- return map[String(status).trim()] || 'info'
-}
-
-// 鎵撳紑寮规
-const openDialog =async (type, row) => {
- // 璇锋眰澶氫釜鎺ュ彛锛岃幏鍙栨暟鎹�
- let res = await getAllCustomerList({
- current: 1,
- size: 1000,
- total: 0,
+ const data = reactive({
+ form: {
+ topic: "",
+ serviceType: "",
+ urgency: "",
+ salesLedgerId: null,
+ productModelIds: "",
+ customerId: null,
+ salesContractNo: "",
+ proDesc: "",
+ customerName: "",
+ },
+ rules: {
+ customerName: [
+ { required: true, message: "璇烽�夋嫨瀹㈡埛鍚嶇О", trigger: "change" },
+ ],
+ serviceType: [
+ { required: true, message: "璇烽�夋嫨鍞悗绫诲瀷", trigger: "change" },
+ ],
+ urgency: [{ required: true, message: "璇烽�夋嫨绱ф�ョ▼搴�", trigger: "change" }],
+ feedbackDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
});
- if(res.records){
- customerNameOptions.value = res.records.map(item => ({
- label: item.customerName,
- value: item.customerName,
- id: item.id
- }));
- }
+ // 鑷畾涔夋牎楠屽嚱鏁帮細鍒ゆ柇鏄惁闇�瑕佹牎楠屽敭鍚庣紪鍙�
- operationType.value = type;
- dialogFormVisible.value = true;
- form.value = {}
- proxy.resetForm("formRef");
- form.value.checkUserId = userStore.id;
- form.value.feedbackDate = getCurrentDate();
- // 鏂板鏃舵竻绌哄凡閫夊叧鑱斾骇鍝�
- if (type === "add") {
- tableData.value = []
- }
- userListNoPageByTenantId().then((res) => {
- userList.value = res.data;
- });
- if (type === "edit") {
- form.value = {...row}
- if (form.value.customerName) {
- const res = await getSalesLedger({ customerName: form.value.customerName })
- if (res?.code === 200) {
- console.log(res)
- associatedSalesOrderNumberOptions.value = (res.data?.records || []).map(item => ({
+ const { form, rules } = toRefs(data);
+ const userList = ref([]);
+
+ const formatCurrency = val => {
+ if (val === null || val === undefined || val === "") return "-";
+ const num = Number(val);
+ return Number.isFinite(num) ? num.toFixed(2) : "-";
+ };
+
+ const { post_sale_waiting_list, degree_of_urgency } = proxy.useDict(
+ "post_sale_waiting_list",
+ "degree_of_urgency"
+ );
+
+ const serviceTypeOptions = computed(() => post_sale_waiting_list?.value || []);
+ const urgencyOptions = computed(() => degree_of_urgency?.value || []);
+
+ const getProductRowId = row => {
+ return (
+ row?.id ??
+ row?.productModelId ??
+ row?.modelId ??
+ `${row?.productCategory || row?.productName || ""}-${
+ row?.specificationModel || row?.model || ""
+ }-${row?.unit || ""}`
+ );
+ };
+
+ const normalizeProductRow = row => {
+ return {
+ ...row,
+ id: getProductRowId(row),
+ productCategory: row?.productCategory ?? row?.productName ?? "",
+ specificationModel: row?.specificationModel ?? row?.model ?? "",
+ unit: row?.unit ?? "",
+ approveStatus: row?.approveStatus ?? null,
+ shippingStatus: row?.shippingStatus ?? "",
+ expressCompany: row?.expressCompany ?? "",
+ expressNumber: row?.expressNumber ?? "",
+ shippingCarNumber: row?.shippingCarNumber ?? "",
+ shippingDate: row?.shippingDate ?? "",
+ quantity: row?.quantity ?? 0,
+ taxRate: row?.taxRate ?? 0,
+ taxInclusiveUnitPrice: row?.taxInclusiveUnitPrice ?? 0,
+ taxInclusiveTotalPrice: row?.taxInclusiveTotalPrice ?? 0,
+ taxExclusiveTotalPrice: row?.taxExclusiveTotalPrice ?? 0,
+ noQuantity: row?.noQuantity ?? 0,
+ };
+ };
+
+ const tableColumn = ref([
+ { label: "浜у搧澶х被", prop: "productCategory" },
+ { label: "瑙勬牸鍨嬪彿", prop: "specificationModel" },
+ { label: "鍗曚綅", prop: "unit" },
+ {
+ label: "浜у搧鐘舵��",
+ prop: "approveStatus",
+ width: 100,
+ align: "center",
+ dataType: "slot",
+ slot: "approveStatus",
+ },
+ {
+ label: "鍙戣揣鐘舵��",
+ align: "center",
+ width: 140,
+ dataType: "slot",
+ slot: "shippingStatus",
+ },
+ { label: "蹇�掑叕鍙�", prop: "expressCompany", width: 140 },
+ { label: "蹇�掑崟鍙�", prop: "expressNumber", width: 160 },
+ {
+ label: "鍙戣揣杞︾墝",
+ prop: "shippingCarNumber",
+ minWidth: 100,
+ align: "center",
+ },
+ { label: "鍙戣揣鏃ユ湡", prop: "shippingDate", minWidth: 100, align: "center" },
+ { label: "鏁伴噺", prop: "quantity", width: 100 },
+ { label: "绋庣巼(%)", prop: "taxRate", width: 100 },
+ {
+ label: "鍚◣鍗曚环(鍏�)",
+ prop: "taxInclusiveUnitPrice",
+ width: 160,
+ formatData: formatCurrency,
+ },
+ {
+ label: "鍚◣鎬讳环(鍏�)",
+ prop: "taxInclusiveTotalPrice",
+ width: 160,
+ formatData: formatCurrency,
+ },
+ {
+ label: "涓嶅惈绋庢�讳环(鍏�)",
+ prop: "taxExclusiveTotalPrice",
+ width: 160,
+ formatData: formatCurrency,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ operation: [
+ {
+ name: "鍒犻櫎",
+ type: "text",
+ clickFun: row => {
+ tableData.value = tableData.value.filter(
+ i => getProductRowId(i) !== getProductRowId(row)
+ );
+ },
+ },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ // 閫夋嫨浜у搧寮圭獥
+ const isShowProductSelectDialog = ref(false);
+ const handleSelectProducts = rows => {
+ if (!Array.isArray(rows)) return;
+ const existingIds = new Set(
+ tableData.value.map(i => String(getProductRowId(i)))
+ );
+ const mapped = rows
+ .map(normalizeProductRow)
+ .filter(r => !existingIds.has(String(getProductRowId(r))));
+ tableData.value = tableData.value.concat(mapped);
+ };
+ const currentSelectedProductIds = computed(() => {
+ return tableData.value
+ .map(item => getProductRowId(item))
+ .filter(item => item !== undefined && item !== null && item !== "");
+ });
+
+ const associatedSalesOrderNumberChange = () => {
+ const opt = associatedSalesOrderNumberOptions.value.find(
+ item => item.value === form.value.salesContractNo
+ );
+ tableData.value = (opt?.productData || []).map(normalizeProductRow);
+ form.value.salesLedgerId = opt?.id || null;
+ };
+
+ const associatedSalesOrderNumberOptions = ref([]);
+
+ const currentSalesOrderProducts = computed(() => {
+ const opt = associatedSalesOrderNumberOptions.value.find(
+ item => item.value === form.value.salesContractNo
+ );
+ return (opt?.productData || []).map(normalizeProductRow);
+ });
+
+ const customerNameChange = val => {
+ form.value.salesContractNo = "";
+ form.value.salesLedgerId = null;
+ tableData.value = [];
+ associatedSalesOrderNumberOptions.value = [];
+ const opt = customerNameOptions.value.find(item => item.value === val);
+ if (opt) {
+ form.value.customerId = opt.id;
+ } else {
+ form.value.customerId = null;
+ }
+ getSalesLedger({
+ customerName: form.value.customerName,
+ }).then(res => {
+ if (res.code === 200) {
+ associatedSalesOrderNumberOptions.value = res.data.records.map(item => ({
label: item.salesContractNo,
value: item.salesContractNo,
productData: item.productData,
- id: item.id
- }))
+ id: item.id,
+ }));
}
+ });
+ };
+
+ const getApproveStatusText = row => {
+ if (!row) return "涓嶈冻";
+ if (
+ row.approveStatus === 1 &&
+ (!row.shippingDate || !row.shippingCarNumber)
+ ) {
+ return "鍏呰冻";
}
- console.log(form.value)
- }
-}
-const submitForm = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- // 鍖归厤浜у搧鍨嬪彿IDs
- form.value.productModelIds = tableData.value.map(item => item.id).join(",")
- if (operationType.value === "add") {
- afterSalesServiceAdd(form.value).then(response => {
- proxy.$modal.msgSuccess("鏂板鎴愬姛")
- closeDia()
- })
- } else {
- afterSalesServiceUpdate(form.value).then(response => {
- proxy.$modal.msgSuccess("淇敼鎴愬姛")
- closeDia()
- })
- }
- }
- })
-}
-// 鍏抽棴寮规
-const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- emit('close')
-};
-defineExpose({
- openDialog,
-});
+ if (row.approveStatus === 0 && (row.shippingDate || row.shippingCarNumber)) {
+ return "宸插嚭搴�";
+ }
+ return "涓嶈冻";
+ };
+
+ const getApproveStatusType = row => {
+ const statusText = getApproveStatusText(row);
+ return statusText === "涓嶈冻" ? "danger" : "success";
+ };
+
+ const getShippingStatusText = row => {
+ if (!row) return "寰呭彂璐�";
+ if (row.shippingDate || row.shippingCarNumber) {
+ return "宸插彂璐�";
+ }
+ const status = row.shippingStatus;
+ if (status === null || status === undefined || status === "") {
+ return "寰呭彂璐�";
+ }
+ const map = {
+ 寰呭彂璐�: "寰呭彂璐�",
+ 寰呭鏍�: "寰呭鏍�",
+ 瀹℃牳涓�: "瀹℃牳涓�",
+ 瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
+ 瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
+ 宸插彂璐�: "宸插彂璐�",
+ };
+ return map[String(status).trim()] || "寰呭彂璐�";
+ };
+
+ const getShippingStatusType = row => {
+ if (!row) return "info";
+ if (row.shippingDate || row.shippingCarNumber) {
+ return "success";
+ }
+ const status = row.shippingStatus;
+ if (status === null || status === undefined || status === "") {
+ return "info";
+ }
+ const map = {
+ 寰呭彂璐�: "info",
+ 寰呭鏍�: "warning",
+ 瀹℃牳涓�: "warning",
+ 瀹℃牳鎷掔粷: "danger",
+ 瀹℃牳閫氳繃: "success",
+ 宸插彂璐�: "success",
+ };
+ return map[String(status).trim()] || "info";
+ };
+
+ // 鎵撳紑寮规
+ const openDialog = async (type, row) => {
+ // 璇锋眰澶氫釜鎺ュ彛锛岃幏鍙栨暟鎹�
+ let res = await getAllCustomerList({
+ current: 1,
+ size: 1000,
+ total: 0,
+ });
+ console.log(res, "res");
+
+ if (res.data.records) {
+ customerNameOptions.value = res.data.records.map(item => ({
+ label: item.customerName,
+ value: item.customerName,
+ id: item.id,
+ }));
+ } else {
+ }
+
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ form.value = {};
+ proxy.resetForm("formRef");
+ form.value.checkUserId = userStore.id;
+ form.value.feedbackDate = getCurrentDate();
+ // 鏂板鏃舵竻绌哄凡閫夊叧鑱斾骇鍝�
+ if (type === "add") {
+ tableData.value = [];
+ }
+ userListNoPageByTenantId().then(res => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ form.value = { ...row };
+ if (form.value.customerName) {
+ const res = await getSalesLedger({
+ customerName: form.value.customerName,
+ });
+ if (res?.code === 200) {
+ console.log(res);
+ associatedSalesOrderNumberOptions.value = (res.data?.records || []).map(
+ item => ({
+ label: item.salesContractNo,
+ value: item.salesContractNo,
+ productData: item.productData,
+ id: item.id,
+ })
+ );
+ }
+ }
+ console.log(form.value);
+ }
+ };
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ // 鍖归厤浜у搧鍨嬪彿IDs
+ form.value.productModelIds = tableData.value
+ .map(item => item.id)
+ .join(",");
+ if (operationType.value === "add") {
+ afterSalesServiceAdd(form.value).then(response => {
+ proxy.$modal.msgSuccess("鏂板鎴愬姛");
+ closeDia();
+ });
+ } else {
+ afterSalesServiceUpdate(form.value).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛");
+ closeDia();
+ });
+ }
+ }
+ });
+ };
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ emit("close");
+ };
+ defineExpose({
+ openDialog,
+ });
</script>
<style scoped lang="scss">
-.descriptions {
- margin-bottom: 20px;
- display: inline-block;
- font-size: 1rem;
- font-weight: 600;
- padding-left: 12px;
- position: relative;
-}
+ .descriptions {
+ margin-bottom: 20px;
+ display: inline-block;
+ font-size: 1rem;
+ font-weight: 600;
+ padding-left: 12px;
+ position: relative;
+ }
-.descriptions::before {
- content: "";
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
- width: 4px;
- height: 1rem;
- background-color: #002FA7; /* Element 榛樿绾㈣壊 */
- border-radius: 2px;
-}
+ .descriptions::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 4px;
+ height: 1rem;
+ background-color: #002fa7; /* Element 榛樿绾㈣壊 */
+ border-radius: 2px;
+ }
</style>
diff --git a/src/views/equipmentManagement/operationManagement/index.vue b/src/views/equipmentManagement/operationManagement/index.vue
index 008cc2c..99c3bd1 100644
--- a/src/views/equipmentManagement/operationManagement/index.vue
+++ b/src/views/equipmentManagement/operationManagement/index.vue
@@ -104,7 +104,7 @@
align="center"
>
<template #default="scope">
- {{ scope.row.runtimeDuration || '-' }}
+ {{ getRuntimeDurationDisplay(scope.row) }}
</template>
</el-table-column>
<el-table-column
@@ -154,7 +154,8 @@
</template>
<script setup>
-import { ref, onMounted, computed } from 'vue'
+import { ref, onMounted, onUnmounted, computed } from 'vue'
+import dayjs from 'dayjs'
import { ElMessage } from 'element-plus'
import {
VideoPlay,
@@ -193,6 +194,98 @@
return filtered
})
+
+// 杩愯涓棤缁撴潫鏃堕棿鏃讹紝杩愯鏃堕暱闇�闅忓綋鍓嶆椂闂村彉鍖栵紝鐢� tick 瑙﹀彂妯℃澘閲嶇畻
+const runtimeDisplayTick = ref(0)
+
+/** 鍙栧悗绔彲鑳戒娇鐢ㄧ殑寮�濮�/缁撴潫鏃堕棿瀛楁 */
+const pickStartTime = (row) => row?.startRuntimeTime ?? row?.startTime ?? row?.start_time
+const pickEndTime = (row) => row?.endRuntimeTime ?? row?.endTime ?? row?.end_time
+
+/**
+ * 瑙f瀽鎺ュ彛/鍓嶇鍐欏叆鐨勫悇绫绘椂闂达細鏃堕棿鎴炽�両SO 瀛楃涓层�亂yyy-MM-dd HH:mm:ss銆丣ackson 鏁扮粍 [y,M,d,h,m,s]銆佸惈涓枃鐨� toLocaleString 绛�
+ */
+const parseDeviceTime = (input) => {
+ if (input === null || input === undefined || input === '') return null
+ if (typeof input === 'number' && !Number.isNaN(input)) {
+ const d = dayjs(input)
+ return d.isValid() ? d.toDate() : null
+ }
+ if (Array.isArray(input)) {
+ const [y, mo, day, h = 0, mi = 0, se = 0] = input
+ if (y == null || y === '') return null
+ const d = dayjs()
+ .year(Number(y))
+ .month(Number(mo || 1) - 1)
+ .date(Number(day || 1))
+ .hour(Number(h) || 0)
+ .minute(Number(mi) || 0)
+ .second(Number(se) || 0)
+ return d.isValid() ? d.toDate() : null
+ }
+ const s = String(input).trim()
+ if (!s || s === '-') return null
+ let d = dayjs(s)
+ if (d.isValid()) return d.toDate()
+ d = dayjs(s.replace(/-/g, '/'))
+ if (d.isValid()) return d.toDate()
+ d = dayjs(s.replace(/\//g, '-'))
+ if (d.isValid()) return d.toDate()
+ return null
+}
+
+const formatDurationMs = (durationMs) => {
+ if (durationMs == null || Number.isNaN(durationMs) || durationMs < 0) return '-'
+ const hours = Math.floor(durationMs / (1000 * 60 * 60))
+ const minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60))
+ if (hours === 0 && minutes === 0) return '涓嶈冻1鍒嗛挓'
+ return `${hours}灏忔椂${minutes}鍒嗛挓`
+}
+
+const hasMeaningfulEnd = (endRaw) =>
+ endRaw !== null &&
+ endRaw !== undefined &&
+ String(endRaw).trim() !== '' &&
+ String(endRaw).trim() !== '-'
+
+const formatStoredDuration = (row) => {
+ const rd = row?.runtimeDuration
+ if (rd === null || rd === undefined) return ''
+ const t = String(rd).trim()
+ return t === '' || t === '-' ? '' : String(rd)
+}
+
+/** 杩愯涓細濮嬬粓鐢ㄣ�屽綋鍓嶆椂闂� - 寮�濮嬫椂闂淬�嶏紱宸插仠姝細浼樺厛鎺ュ彛 runtimeDuration锛屽惁鍒欑敤缁撴潫-寮�濮嬶紱鏃犵粨鏉熷彲鐪嬪凡瀛樻椂闀挎垨鍔ㄦ�佹帹绠� */
+const getRuntimeDurationDisplay = (row) => {
+ void runtimeDisplayTick.value
+ const start = parseDeviceTime(pickStartTime(row))
+ if (!start) {
+ return formatStoredDuration(row) || '-'
+ }
+
+ const statusStr = String(row?.status ?? '').trim()
+ const isRunning = statusStr === '杩愯涓�' || statusStr === '1'
+ const endRaw = pickEndTime(row)
+ const hasEnd = hasMeaningfulEnd(endRaw)
+
+ // 鏃犵粨鏉熸椂闂达細杩愯涓竴瀹氬姩鎬佺畻锛涘凡鍋滄鍒欎紭鍏堝睍绀哄悗绔凡瀛樻椂闀匡紝娌℃湁鍐嶆寜褰撳墠鏃堕棿鎺ㄧ畻
+ if (!hasEnd) {
+ if (isRunning) return formatDurationMs(Date.now() - start.getTime())
+ const stored = formatStoredDuration(row)
+ if (stored) return stored
+ return formatDurationMs(Date.now() - start.getTime())
+ }
+
+ if (isRunning) {
+ return formatDurationMs(Date.now() - start.getTime())
+ }
+
+ const end = parseDeviceTime(endRaw)
+ const stored = formatStoredDuration(row)
+ if (stored) return stored
+ if (end) return formatDurationMs(end.getTime() - start.getTime())
+ return '-'
+}
// 妫�鏌ヨ澶囨槸鍚﹁秴鏃舵湭鍚姩
const isOverdue = (device) => {
@@ -246,12 +339,11 @@
device.endRuntimeTime = currentTime
// 璁$畻杩愯鏃堕暱
if (device.startRuntimeTime) {
- const startTime = new Date(device.startRuntimeTime)
- const endTime = new Date(currentTime)
- const duration = endTime - startTime
- const hours = Math.floor(duration / (1000 * 60 * 60))
- const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60))
- device.runtimeDuration = `${hours}灏忔椂${minutes}鍒嗛挓`
+ const startTime = parseDeviceTime(device.startRuntimeTime)
+ const endTime = parseDeviceTime(currentTime)
+ if (startTime && endTime) {
+ device.runtimeDuration = formatDurationMs(endTime.getTime() - startTime.getTime())
+ }
}
}
const params = {
@@ -297,9 +389,31 @@
-// 缁勪欢鎸傝浇鏃跺垵濮嬪寲鏁版嵁
+const POLL_MS = 60 * 1000
+const RUNTIME_TICK_MS = 30 * 1000
+let listPollTimer = null
+let runtimeTickTimer = null
+
+// 缁勪欢鎸傝浇鏃舵媺鍙栨暟鎹紝骞舵瘡鍒嗛挓鍒锋柊涓�娆″垪琛紱杩愯涓椂闀挎瘡 30 绉掑埛鏂版樉绀�
onMounted(() => {
getList()
+ listPollTimer = setInterval(() => {
+ getList()
+ }, POLL_MS)
+ runtimeTickTimer = setInterval(() => {
+ runtimeDisplayTick.value++
+ }, RUNTIME_TICK_MS)
+})
+
+onUnmounted(() => {
+ if (listPollTimer != null) {
+ clearInterval(listPollTimer)
+ listPollTimer = null
+ }
+ if (runtimeTickTimer != null) {
+ clearInterval(runtimeTickTimer)
+ runtimeTickTimer = null
+ }
})
</script>
diff --git a/src/views/inventoryManagement/dispatchLog/Record.vue b/src/views/inventoryManagement/dispatchLog/Record.vue
index 88fc8d2..f41eaaa 100644
--- a/src/views/inventoryManagement/dispatchLog/Record.vue
+++ b/src/views/inventoryManagement/dispatchLog/Record.vue
@@ -96,7 +96,9 @@
</el-table-column>
<el-table-column label="瀹℃壒鐘舵��" prop="approvalStatus" show-overflow-tooltip>
<template #default="scope">
- {{ getApprovalStatusLabel(scope.row.approvalStatus) }}
+ <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)" size="small">
+ {{ getApprovalStatusLabel(scope.row.approvalStatus) }}
+ </el-tag>
</template>
</el-table-column>
</el-table>
@@ -216,6 +218,13 @@
return approvalStatusLabelMap[status] || "寰呭鎵�";
};
+// 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
+const getApprovalStatusTagType = (status) => {
+ if (status === 1 || status === "1" || status === "approved" || status === "APPROVED") return "success";
+ if (status === 2 || status === "2" || status === "rejected" || status === "REJECTED") return "danger";
+ return "warning";
+};
+
// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
const fetchStockRecordTypeOptions = () => {
if (props.type === '0') {
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index 75d884a..c9cb6ee 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -91,7 +91,9 @@
prop="approvalStatus"
show-overflow-tooltip>
<template #default="scope">
- {{ getApprovalStatusLabel(scope.row.approvalStatus) }}
+ <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)" size="small">
+ {{ getApprovalStatusLabel(scope.row.approvalStatus) }}
+ </el-tag>
</template>
</el-table-column>
</el-table>
@@ -187,6 +189,13 @@
return approvalStatusLabelMap[status] || "寰呭鎵�";
};
+// 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
+const getApprovalStatusTagType = (status) => {
+ if (status === 1 || status === "1" || status === "approved" || status === "APPROVED") return "success";
+ if (status === 2 || status === "2" || status === "rejected" || status === "REJECTED") return "danger";
+ return "warning";
+};
+
const pageProductChange = obj => {
page.current = obj.page;
page.size = obj.limit;
diff --git a/src/views/inventoryManagement/stockReport/index.vue b/src/views/inventoryManagement/stockReport/index.vue
index 89773cf..8139508 100644
--- a/src/views/inventoryManagement/stockReport/index.vue
+++ b/src/views/inventoryManagement/stockReport/index.vue
@@ -4,708 +4,683 @@
<div class="search_form">
<div class="search_left">
<span class="search_title">鎶ヨ〃绫诲瀷锛�</span>
- <el-select
- v-model="searchForm.reportType"
- style="width: 150px;"
- placeholder="璇烽�夋嫨"
- @change="handleReportTypeChange"
- >
- <el-option label="鏃ユ姤" value="daily" />
- <el-option label="鏈堟姤" value="monthly" />
- <el-option label="杩涘嚭瀛樻姤琛�" value="inout" />
+ <el-select v-model="searchForm.reportType"
+ style="width: 150px;"
+ placeholder="璇烽�夋嫨"
+ @change="handleReportTypeChange">
+ <el-option label="鏃ユ姤"
+ value="daily" />
+ <el-option label="鏈堟姤"
+ value="monthly" />
+ <el-option label="杩涘嚭瀛樻姤琛�"
+ value="inout" />
</el-select>
-
<span class="search_title ml10">鏃堕棿鑼冨洿锛�</span>
- <el-date-picker
- v-if="searchForm.reportType === 'daily'"
- v-model="searchForm.singleDate"
- type="date"
- placeholder="璇烽�夋嫨鏃ユ湡"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- style="width: 200px;"
- />
- <el-date-picker
- v-else-if="searchForm.reportType === 'monthly'"
- v-model="searchForm.monthRange"
- type="monthrange"
- range-separator="鑷�"
- start-placeholder="寮�濮嬫湀浠�"
- end-placeholder="缁撴潫鏈堜唤"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- style="width: 240px;"
- />
- <el-date-picker
- v-else
- v-model="searchForm.dateRange"
- type="daterange"
- range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�"
- end-placeholder="缁撴潫鏃ユ湡"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- style="width: 240px;"
- />
-
- <el-button type="primary" @click="onSearch" style="margin-left: 10px">
+ <el-date-picker v-if="searchForm.reportType === 'daily'"
+ v-model="searchForm.singleDate"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 200px;" />
+ <el-date-picker v-else-if="searchForm.reportType === 'monthly'"
+ v-model="searchForm.monthRange"
+ type="monthrange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫湀浠�"
+ end-placeholder="缁撴潫鏈堜唤"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 240px;" />
+ <el-date-picker v-else
+ v-model="searchForm.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 240px;" />
+ <el-button type="primary"
+ @click="onSearch"
+ style="margin-left: 10px">
鏌ヨ
</el-button>
<el-button @click="handleReset">閲嶇疆</el-button>
</div>
-
<div class="search_right">
-<!-- <el-button type="success" @click="handleExport" icon="Download">-->
-<!-- 瀵煎嚭鎶ヨ〃-->
-<!-- </el-button>-->
+ <!-- <el-button type="success" @click="handleExport" icon="Download">-->
+ <!-- 瀵煎嚭鎶ヨ〃-->
+ <!-- </el-button>-->
</div>
</div>
-
-<!-- <!– 缁熻鍗$墖 –>-->
-<!-- <div class="stats_cards" v-if="reportData.summary">-->
-<!-- <el-row :gutter="20">-->
-<!-- <el-col :span="6">-->
-<!-- <el-card class="stats_card">-->
-<!-- <div class="stats_content">-->
-<!-- <div class="stats_icon in">-->
-<!-- <el-icon><TrendCharts /></el-icon>-->
-<!-- </div>-->
-<!-- <div class="stats_info">-->
-<!-- <div class="stats_value">{{ reportData.summary.totalIn || 0 }}</div>-->
-<!-- <div class="stats_label">鎬诲叆搴撻噺</div>-->
-<!-- </div>-->
-<!-- </div>-->
-<!-- </el-card>-->
-<!-- </el-col>-->
-<!-- <el-col :span="6">-->
-<!-- <el-card class="stats_card">-->
-<!-- <div class="stats_content">-->
-<!-- <div class="stats_icon out">-->
-<!-- <el-icon><TrendCharts /></el-icon>-->
-<!-- </div>-->
-<!-- <div class="stats_info">-->
-<!-- <div class="stats_value">{{ reportData.summary.totalOut || 0 }}</div>-->
-<!-- <div class="stats_label">鎬诲嚭搴撻噺</div>-->
-<!-- </div>-->
-<!-- </div>-->
-<!-- </el-card>-->
-<!-- </el-col>-->
-<!-- <el-col :span="6">-->
-<!-- <el-card class="stats_card">-->
-<!-- <div class="stats_content">-->
-<!-- <div class="stats_icon stock">-->
-<!-- <el-icon><Box /></el-icon>-->
-<!-- </div>-->
-<!-- <div class="stats_info">-->
-<!-- <div class="stats_value">{{ reportData.summary.currentStock || 0 }}</div>-->
-<!-- <div class="stats_label">褰撳墠搴撳瓨</div>-->
-<!-- </div>-->
-<!-- </div>-->
-<!-- </el-card>-->
-<!-- </el-col>-->
-<!-- <el-col :span="6">-->
-<!-- <el-card class="stats_card">-->
-<!-- <div class="stats_content">-->
-<!-- <div class="stats_icon turnover">-->
-<!-- <el-icon><Refresh /></el-icon>-->
-<!-- </div>-->
-<!-- <div class="stats_info">-->
-<!-- <div class="stats_value">{{ reportData.summary.turnoverRate || 0 }}%</div>-->
-<!-- <div class="stats_label">鍛ㄨ浆鐜�</div>-->
-<!-- </div>-->
-<!-- </div>-->
-<!-- </el-card>-->
-<!-- </el-col>-->
-<!-- </el-row>-->
-<!-- </div>-->
-
-<!-- <!– 鍥捐〃鍖哄煙 –>-->
-<!-- <div class="chart_section" v-if="reportData.chartData">-->
-<!-- <el-row :gutter="20">-->
-<!-- <el-col :span="12">-->
-<!-- <el-card>-->
-<!-- <template #header>-->
-<!-- <span>搴撳瓨瓒嬪娍鍥�</span>-->
-<!-- </template>-->
-<!-- <div ref="trendChart" style="height: 300px;"></div>-->
-<!-- </el-card>-->
-<!-- </el-col>-->
-<!-- <el-col :span="12">-->
-<!-- <el-card>-->
-<!-- <template #header>-->
-<!-- <span>杩涘嚭搴撳姣�</span>-->
-<!-- </template>-->
-<!-- <div ref="comparisonChart" style="height: 300px;"></div>-->
-<!-- </el-card>-->
-<!-- </el-col>-->
-<!-- </el-row>-->
-<!-- </div>-->
-
+ <!-- <!– 缁熻鍗$墖 –>-->
+ <!-- <div class="stats_cards" v-if="reportData.summary">-->
+ <!-- <el-row :gutter="20">-->
+ <!-- <el-col :span="6">-->
+ <!-- <el-card class="stats_card">-->
+ <!-- <div class="stats_content">-->
+ <!-- <div class="stats_icon in">-->
+ <!-- <el-icon><TrendCharts /></el-icon>-->
+ <!-- </div>-->
+ <!-- <div class="stats_info">-->
+ <!-- <div class="stats_value">{{ reportData.summary.totalIn || 0 }}</div>-->
+ <!-- <div class="stats_label">鎬诲叆搴撻噺</div>-->
+ <!-- </div>-->
+ <!-- </div>-->
+ <!-- </el-card>-->
+ <!-- </el-col>-->
+ <!-- <el-col :span="6">-->
+ <!-- <el-card class="stats_card">-->
+ <!-- <div class="stats_content">-->
+ <!-- <div class="stats_icon out">-->
+ <!-- <el-icon><TrendCharts /></el-icon>-->
+ <!-- </div>-->
+ <!-- <div class="stats_info">-->
+ <!-- <div class="stats_value">{{ reportData.summary.totalOut || 0 }}</div>-->
+ <!-- <div class="stats_label">鎬诲嚭搴撻噺</div>-->
+ <!-- </div>-->
+ <!-- </div>-->
+ <!-- </el-card>-->
+ <!-- </el-col>-->
+ <!-- <el-col :span="6">-->
+ <!-- <el-card class="stats_card">-->
+ <!-- <div class="stats_content">-->
+ <!-- <div class="stats_icon stock">-->
+ <!-- <el-icon><Box /></el-icon>-->
+ <!-- </div>-->
+ <!-- <div class="stats_info">-->
+ <!-- <div class="stats_value">{{ reportData.summary.currentStock || 0 }}</div>-->
+ <!-- <div class="stats_label">褰撳墠搴撳瓨</div>-->
+ <!-- </div>-->
+ <!-- </div>-->
+ <!-- </el-card>-->
+ <!-- </el-col>-->
+ <!-- <el-col :span="6">-->
+ <!-- <el-card class="stats_card">-->
+ <!-- <div class="stats_content">-->
+ <!-- <div class="stats_icon turnover">-->
+ <!-- <el-icon><Refresh /></el-icon>-->
+ <!-- </div>-->
+ <!-- <div class="stats_info">-->
+ <!-- <div class="stats_value">{{ reportData.summary.turnoverRate || 0 }}%</div>-->
+ <!-- <div class="stats_label">鍛ㄨ浆鐜�</div>-->
+ <!-- </div>-->
+ <!-- </div>-->
+ <!-- </el-card>-->
+ <!-- </el-col>-->
+ <!-- </el-row>-->
+ <!-- </div>-->
+ <!-- <!– 鍥捐〃鍖哄煙 –>-->
+ <!-- <div class="chart_section" v-if="reportData.chartData">-->
+ <!-- <el-row :gutter="20">-->
+ <!-- <el-col :span="12">-->
+ <!-- <el-card>-->
+ <!-- <template #header>-->
+ <!-- <span>搴撳瓨瓒嬪娍鍥�</span>-->
+ <!-- </template>-->
+ <!-- <div ref="trendChart" style="height: 300px;"></div>-->
+ <!-- </el-card>-->
+ <!-- </el-col>-->
+ <!-- <el-col :span="12">-->
+ <!-- <el-card>-->
+ <!-- <template #header>-->
+ <!-- <span>杩涘嚭搴撳姣�</span>-->
+ <!-- </template>-->
+ <!-- <div ref="comparisonChart" style="height: 300px;"></div>-->
+ <!-- </el-card>-->
+ <!-- </el-col>-->
+ <!-- </el-row>-->
+ <!-- </div>-->
<!-- 璇︾粏鏁版嵁琛ㄦ牸 -->
<div class="table_section">
<el-card>
<template #header>
<span>{{ getTableTitle() }}</span>
</template>
- <el-table
- v-loading="tableLoading"
- :data="reportData.tableData"
- border
- height="400"
- style="width: 100%"
- :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
- >
- <el-table-column
- align="center"
- label="搴忓彿"
- type="index"
- width="60"
- />
- <el-table-column
- label="鍏ュ簱鏃堕棿"
- prop="createTime"
- width="200"
- show-overflow-tooltip
- v-if="searchForm.reportType !== 'inout'"
- />
- <el-table-column
- label="鍏ュ簱鎵规"
- prop="inboundBatches"
- width="240"
- show-overflow-tooltip
- v-if="searchForm.reportType !== 'inout'"
- />
- <el-table-column
- label="浜у搧澶х被"
- prop="productName"
- show-overflow-tooltip
- />
- <el-table-column
- label="瑙勬牸鍨嬪彿"
- prop="model"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍗曚綅"
- prop="unit"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍏ュ簱鏁伴噺"
- prop="totalStockIn"
- align="center"
- v-if="searchForm.reportType === 'inout'"
- />
- <el-table-column
- label="鍏ュ簱鏁伴噺"
- prop="stockInNum"
- align="center"
- v-else
- />
- <el-table-column
- label="鍑哄簱鏁伴噺"
- prop="totalStockOut"
- width="100"
- align="center"
- v-if="searchForm.reportType === 'inout'"
- />
- <el-table-column
- label="鐜板湪搴撳瓨"
- prop="currentStock"
- align="center"
- />
- <el-table-column label="鏉ユ簮"
- prop="recordType"
- v-if="searchForm.reportType !== 'inout'"
- show-overflow-tooltip>
- <template #default="scope">
- {{ getRecordType(scope.row.recordType) }}
- </template>
- </el-table-column>
- <el-table-column
- label="鍏ュ簱浜�"
- prop="createBy"
- width="80"
- v-if="searchForm.reportType !== 'inout'"
- show-overflow-tooltip
- />
+ <el-table v-loading="tableLoading"
+ :data="reportData.tableData"
+ border
+ height="400"
+ style="width: 100%"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="鍏ュ簱鏃堕棿"
+ prop="createTime"
+ width="200"
+ show-overflow-tooltip
+ v-if="searchForm.reportType !== 'inout'" />
+ <el-table-column label="鍏ュ簱鎵规"
+ prop="inboundBatches"
+ width="180"
+ show-overflow-tooltip
+ v-if="searchForm.reportType !== 'inout'" />
+ <el-table-column label="鎵瑰彿"
+ prop="batchNo"
+ width="180"
+ show-overflow-tooltip
+ v-if="searchForm.reportType !== 'inout'" />
+ <el-table-column label="浜у搧澶х被"
+ prop="productName"
+ show-overflow-tooltip />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="model"
+ show-overflow-tooltip />
+ <el-table-column label="鍗曚綅"
+ prop="unit"
+ show-overflow-tooltip />
+ <el-table-column label="鍏ュ簱鏁伴噺"
+ prop="totalStockIn"
+ align="center"
+ v-if="searchForm.reportType === 'inout'" />
+ <el-table-column label="鍏ュ簱鏁伴噺"
+ prop="stockInNum"
+ align="center"
+ v-else />
+ <el-table-column label="鍑哄簱鏁伴噺"
+ prop="totalStockOut"
+ width="100"
+ align="center"
+ v-if="searchForm.reportType === 'inout'" />
+ <el-table-column label="鐜板湪搴撳瓨"
+ prop="currentStock"
+ align="center" />
+ <el-table-column label="鏉ユ簮"
+ prop="recordType"
+ v-if="searchForm.reportType !== 'inout'"
+ show-overflow-tooltip>
+ <template #default="scope">
+ {{ getRecordType(scope.row.recordType) }}
+ </template>
+ </el-table-column>
+ <el-table-column label="鍏ュ簱浜�"
+ prop="createBy"
+ width="80"
+ v-if="searchForm.reportType !== 'inout'"
+ show-overflow-tooltip />
</el-table>
- <pagination
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="page.current"
- :limit="page.size"
- @pagination="paginationChange"
- />
+ <pagination :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
</el-card>
</div>
</div>
</template>
<script setup>
-import { ref, reactive, onMounted, nextTick, getCurrentInstance } from 'vue'
-import { ElMessage } from 'element-plus'
-import * as echarts from 'echarts'
-import pagination from '@/components/PIMTable/Pagination.vue'
-import {
- getStockInventoryInAndOutReportList,
- getStockInventoryReportList
-} from "@/api/inventoryManagement/stockInventory.js";
-import {
- findAllQualifiedStockInRecordTypeOptions,findAllUnQualifiedStockInRecordTypeOptions,
-} from "@/api/basicData/enum.js";
+ import { ref, reactive, onMounted, nextTick, getCurrentInstance } from "vue";
+ import { ElMessage } from "element-plus";
+ import * as echarts from "echarts";
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import {
+ getStockInventoryInAndOutReportList,
+ getStockInventoryReportList,
+ } from "@/api/inventoryManagement/stockInventory.js";
+ import {
+ findAllQualifiedStockInRecordTypeOptions,
+ findAllUnQualifiedStockInRecordTypeOptions,
+ } from "@/api/basicData/enum.js";
+ const { proxy } = getCurrentInstance();
+ // 鍝嶅簲寮忔暟鎹�
+ const tableLoading = ref(false);
+ const trendChart = ref(null);
+ const comparisonChart = ref(null);
-const { proxy } = getCurrentInstance()
-// 鍝嶅簲寮忔暟鎹�
-const tableLoading = ref(false)
-const trendChart = ref(null)
-const comparisonChart = ref(null)
+ const searchForm = reactive({
+ reportType: "daily",
+ singleDate: "",
+ dateRange: [],
+ monthRange: [],
+ });
-const searchForm = reactive({
- reportType: 'daily',
- singleDate: '',
- dateRange: [],
- monthRange: []
-})
-
-const reportData = ref({
- summary: null,
- chartData: null,
- tableData: []
-})
-
-const page = reactive({
- current: 1,
- size: 10,
-})
-
-const total = ref(0)
-
-const stockRecordTypeOptions = ref([])
-
-const getRecordType = (recordType) => {
- return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
-}
-
-// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
-const fetchStockRecordTypeOptions = () => {
- findAllQualifiedStockInRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- findAllUnQualifiedStockInRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = [...stockRecordTypeOptions.value,...res.data];
- })
- })
-}
-
-// 鑾峰彇琛ㄦ牸鏍囬
-const getTableTitle = () => {
- const typeMap = {
- daily: '鏃ユ姤璇︾粏鏁版嵁',
- monthly: '鏈堟姤璇︾粏鏁版嵁',
- inout: '杩涘嚭瀛樻姤琛ㄨ缁嗘暟鎹�'
- }
- return typeMap[searchForm.reportType] || '鎶ヨ〃璇︾粏鏁版嵁'
-}
-
-// 鎶ヨ〃绫诲瀷鏀瑰彉
-const handleReportTypeChange = () => {
- page.current = 1
- reportData.value = {
+ const reportData = ref({
summary: null,
chartData: null,
- tableData: []
- }
-}
+ tableData: [],
+ });
-// 鏌ヨ鏁版嵁
-const handleQuery = async () => {
- if (!validateSearchForm()) {
- return
- }
-
- tableLoading.value = true
- try {
- const baseParams = getQueryParams()
+ const page = reactive({
+ current: 1,
+ size: 10,
+ });
+
+ const total = ref(0);
+
+ const stockRecordTypeOptions = ref([]);
+
+ const getRecordType = recordType => {
+ return (
+ stockRecordTypeOptions.value.find(item => item.value === recordType)
+ ?.label || ""
+ );
+ };
+
+ // 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+ const fetchStockRecordTypeOptions = () => {
+ findAllQualifiedStockInRecordTypeOptions().then(res => {
+ stockRecordTypeOptions.value = res.data;
+ findAllUnQualifiedStockInRecordTypeOptions().then(res => {
+ stockRecordTypeOptions.value = [
+ ...stockRecordTypeOptions.value,
+ ...res.data,
+ ];
+ });
+ });
+ };
+
+ // 鑾峰彇琛ㄦ牸鏍囬
+ const getTableTitle = () => {
+ const typeMap = {
+ daily: "鏃ユ姤璇︾粏鏁版嵁",
+ monthly: "鏈堟姤璇︾粏鏁版嵁",
+ inout: "杩涘嚭瀛樻姤琛ㄨ缁嗘暟鎹�",
+ };
+ return typeMap[searchForm.reportType] || "鎶ヨ〃璇︾粏鏁版嵁";
+ };
+
+ // 鎶ヨ〃绫诲瀷鏀瑰彉
+ const handleReportTypeChange = () => {
+ page.current = 1;
+ reportData.value = {
+ summary: null,
+ chartData: null,
+ tableData: [],
+ };
+ };
+
+ // 鏌ヨ鏁版嵁
+ const handleQuery = async () => {
+ if (!validateSearchForm()) {
+ return;
+ }
+
+ tableLoading.value = true;
+ try {
+ const baseParams = getQueryParams();
+ const params = {
+ ...baseParams,
+ current: page.current,
+ size: page.size,
+ };
+ let response;
+
+ if (searchForm.reportType === "inout") {
+ response = await getStockInventoryInAndOutReportList(params);
+ } else {
+ response = await getStockInventoryReportList(params);
+ }
+ if (response.code === 200) {
+ reportData.value.tableData = response.data.records || [];
+ total.value = response.data.total || 0;
+ // reportData.value.summary = response.data.summary
+ // reportData.value.chartData = response.data.chartData
+ // nextTick(() => {
+ // initCharts()
+ // })
+ }
+ } catch (error) {
+ ElMessage.error("鏌ヨ澶辫触锛�" + error.message);
+ } finally {
+ tableLoading.value = false;
+ }
+ };
+
+ // 鏌ヨ鎸夐挳锛氶噸缃埌绗竴椤靛苟鏌ヨ
+ const onSearch = () => {
+ page.current = 1;
+ handleQuery();
+ };
+
+ // 鍒嗛〉鍙樺寲
+ const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ handleQuery();
+ };
+ // // 鐢熸垚鍋囨暟鎹�
+ // const generateMockData = () => {
+ // // 鐢熸垚缁熻鍗$墖鍋囨暟鎹�
+ // const summary = {
+ // totalIn: 1000,
+ // totalOut: 600,
+ // currentStock: 400,
+ // turnoverRate: 30
+ // }
+
+ // // 鐢熸垚鍥捐〃鍋囨暟鎹�
+ // const trendDates = ['2025-09-15', '2025-09-16', '2025-09-17', '2025-09-18', '2025-09-19']
+ // const trendValues = [300, 350, 400, 380, 420]
+ // const comparisonDates = ['2025-09-15', '2025-09-16', '2025-09-17']
+ // const inValues = [100, 150, 200]
+ // const outValues = [80, 120, 100]
+
+ // const chartData = {
+ // trendDates,
+ // trendValues,
+ // comparisonDates,
+ // inValues,
+ // outValues
+ // }
+
+ // reportData.value = {
+ // summary,
+ // chartData,
+ // tableData: []
+ // }
+ // }
+ // 楠岃瘉鎼滅储琛ㄥ崟
+ const validateSearchForm = () => {
+ if (searchForm.reportType === "daily") {
+ if (!searchForm.singleDate) {
+ ElMessage.warning("璇烽�夋嫨鏃ユ湡");
+ return false;
+ }
+ } else if (searchForm.reportType === "inout") {
+ if (!searchForm.dateRange || searchForm.dateRange.length !== 2) {
+ ElMessage.warning("璇烽�夋嫨鏃ユ湡鑼冨洿");
+ return false;
+ }
+ } else if (searchForm.reportType === "monthly") {
+ if (!searchForm.monthRange || searchForm.monthRange.length !== 2) {
+ ElMessage.warning("璇烽�夋嫨鏈堜唤鑼冨洿");
+ return false;
+ }
+ }
+ return true;
+ };
+
+ // 鑾峰彇鏌ヨ鍙傛暟
+ const getQueryParams = () => {
const params = {
- ...baseParams,
- current: page.current,
- size: page.size,
- }
- let response
+ reportType: searchForm.reportType,
+ reportDate: "",
+ startMonth: "",
+ endMonth: "",
+ startDate: "",
+ endDate: "",
+ };
- if (searchForm.reportType === 'inout') {
- response = await getStockInventoryInAndOutReportList(params)
+ if (searchForm.reportType === "daily") {
+ params.reportDate = searchForm.singleDate;
+ } else if (searchForm.reportType === "monthly") {
+ params.startMonth = searchForm.monthRange[0];
+ params.endMonth = searchForm.monthRange[1];
} else {
- response = await getStockInventoryReportList(params)
+ params.startDate = searchForm.dateRange[0];
+ params.endDate = searchForm.dateRange[1];
}
- if (response.code === 200) {
- reportData.value.tableData = response.data.records || []
- total.value = response.data.total || 0
- // reportData.value.summary = response.data.summary
- // reportData.value.chartData = response.data.chartData
- // nextTick(() => {
- // initCharts()
- // })
-
+
+ return params;
+ };
+
+ // 閲嶇疆鎼滅储
+ const handleReset = () => {
+ searchForm.reportType = "daily";
+ searchForm.singleDate = "";
+ searchForm.dateRange = [];
+ searchForm.monthRange = [];
+ reportData.value = {
+ summary: null,
+ chartData: null,
+ tableData: [],
+ };
+ };
+
+ // 瀵煎嚭鎶ヨ〃
+ const handleExport = async () => {
+ if (!validateSearchForm()) {
+ return;
}
- } catch (error) {
- ElMessage.error('鏌ヨ澶辫触锛�' + error.message)
- } finally {
- tableLoading.value = false
- }
-}
-// 鏌ヨ鎸夐挳锛氶噸缃埌绗竴椤靛苟鏌ヨ
-const onSearch = () => {
- page.current = 1
- handleQuery()
-}
+ try {
+ const params = getQueryParams();
+ // const response = await exportStockReport(params)
+ proxy.download("/stockin/exportCopy", params, "搴撳瓨鎶ヨ〃.xlsx");
+ // 鍒涘缓涓嬭浇閾炬帴
+ // const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
+ // const url = window.URL.createObjectURL(blob)
+ // const link = document.createElement('a')
+ // link.href = url
+ // link.download = `${getTableTitle()}_${new Date().getTime()}.xlsx`
+ // document.body.appendChild(link)
+ // link.click()
+ // document.body.removeChild(link)
+ // window.URL.revokeObjectURL(url)
-// 鍒嗛〉鍙樺寲
-const paginationChange = (obj) => {
- page.current = obj.page
- page.size = obj.limit
- handleQuery()
-}
-// // 鐢熸垚鍋囨暟鎹�
-// const generateMockData = () => {
-// // 鐢熸垚缁熻鍗$墖鍋囨暟鎹�
-// const summary = {
-// totalIn: 1000,
-// totalOut: 600,
-// currentStock: 400,
-// turnoverRate: 30
-// }
-
-// // 鐢熸垚鍥捐〃鍋囨暟鎹�
-// const trendDates = ['2025-09-15', '2025-09-16', '2025-09-17', '2025-09-18', '2025-09-19']
-// const trendValues = [300, 350, 400, 380, 420]
-// const comparisonDates = ['2025-09-15', '2025-09-16', '2025-09-17']
-// const inValues = [100, 150, 200]
-// const outValues = [80, 120, 100]
-
-// const chartData = {
-// trendDates,
-// trendValues,
-// comparisonDates,
-// inValues,
-// outValues
-// }
-
-// reportData.value = {
-// summary,
-// chartData,
-// tableData: []
-// }
-// }
-// 楠岃瘉鎼滅储琛ㄥ崟
-const validateSearchForm = () => {
- if (searchForm.reportType === 'daily') {
- if (!searchForm.singleDate) {
- ElMessage.warning('璇烽�夋嫨鏃ユ湡')
- return false
+ // ElMessage.success('瀵煎嚭鎴愬姛')
+ } catch (error) {
+ ElMessage.error("瀵煎嚭澶辫触锛�" + error.message);
}
- } else if (searchForm.reportType === 'inout') {
- if (!searchForm.dateRange || searchForm.dateRange.length !== 2) {
- ElMessage.warning('璇烽�夋嫨鏃ユ湡鑼冨洿')
- return false
- }
- } else if (searchForm.reportType === 'monthly') {
- if (!searchForm.monthRange || searchForm.monthRange.length !== 2) {
- ElMessage.warning('璇烽�夋嫨鏈堜唤鑼冨洿')
- return false
- }
- }
- return true
-}
+ };
-// 鑾峰彇鏌ヨ鍙傛暟
-const getQueryParams = () => {
- const params = {
- reportType: searchForm.reportType,
- reportDate: "",
- startMonth: "",
- endMonth: "",
- startDate: "",
- endDate: ""
- }
-
- if (searchForm.reportType === 'daily') {
- params.reportDate = searchForm.singleDate
- } else if (searchForm.reportType === 'monthly') {
- params.startMonth = searchForm.monthRange[0]
- params.endMonth = searchForm.monthRange[1]
- } else {
- params.startDate = searchForm.dateRange[0]
- params.endDate = searchForm.dateRange[1]
- }
-
- return params
-}
+ // 鍒濆鍖栧浘琛�
+ const initCharts = () => {
+ if (!reportData.value.chartData) return;
-// 閲嶇疆鎼滅储
-const handleReset = () => {
- searchForm.reportType = 'daily'
- searchForm.singleDate = ''
- searchForm.dateRange = []
- searchForm.monthRange = []
- reportData.value = {
- summary: null,
- chartData: null,
- tableData: []
- }
-}
+ initTrendChart();
+ initComparisonChart();
+ };
-// 瀵煎嚭鎶ヨ〃
-const handleExport = async () => {
- if (!validateSearchForm()) {
- return
- }
-
- try {
- const params = getQueryParams()
- // const response = await exportStockReport(params)
- proxy.download("/stockin/exportCopy", params, '搴撳瓨鎶ヨ〃.xlsx')
- // 鍒涘缓涓嬭浇閾炬帴
- // const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
- // const url = window.URL.createObjectURL(blob)
- // const link = document.createElement('a')
- // link.href = url
- // link.download = `${getTableTitle()}_${new Date().getTime()}.xlsx`
- // document.body.appendChild(link)
- // link.click()
- // document.body.removeChild(link)
- // window.URL.revokeObjectURL(url)
-
- // ElMessage.success('瀵煎嚭鎴愬姛')
- } catch (error) {
- ElMessage.error('瀵煎嚭澶辫触锛�' + error.message)
- }
-}
+ // 鍒濆鍖栬秼鍔垮浘
+ const initTrendChart = () => {
+ if (!trendChart.value) return;
-// 鍒濆鍖栧浘琛�
-const initCharts = () => {
- if (!reportData.value.chartData) return
-
- initTrendChart()
- initComparisonChart()
-}
-
-// 鍒濆鍖栬秼鍔垮浘
-const initTrendChart = () => {
- if (!trendChart.value) return
-
- const chart = echarts.init(trendChart.value)
- const option = {
- title: {
- text: '搴撳瓨鍙樺寲瓒嬪娍',
- left: 'center'
- },
- tooltip: {
- trigger: 'axis'
- },
- legend: {
- data: ['搴撳瓨閲�'],
- top: 30
- },
- xAxis: {
- type: 'category',
- data: reportData.value.chartData.trendDates || []
- },
- yAxis: {
- type: 'value'
- },
- series: [{
- name: '搴撳瓨閲�',
- type: 'line',
- data: reportData.value.chartData.trendValues || [],
- smooth: true,
- itemStyle: {
- color: '#409EFF'
- }
- }]
- }
- chart.setOption(option)
-}
-
-// 鍒濆鍖栧姣斿浘
-const initComparisonChart = () => {
- if (!comparisonChart.value) return
-
- const chart = echarts.init(comparisonChart.value)
- const option = {
- title: {
- text: '杩涘嚭搴撳姣�',
- left: 'center'
- },
- tooltip: {
- trigger: 'axis'
- },
- legend: {
- data: ['鍏ュ簱', '鍑哄簱'],
- top: 30
- },
- xAxis: {
- type: 'category',
- data: reportData.value.chartData.comparisonDates || []
- },
- yAxis: {
- type: 'value'
- },
- series: [
- {
- name: '鍏ュ簱',
- type: 'bar',
- data: reportData.value.chartData.inValues || [],
- itemStyle: {
- color: '#67C23A'
- }
+ const chart = echarts.init(trendChart.value);
+ const option = {
+ title: {
+ text: "搴撳瓨鍙樺寲瓒嬪娍",
+ left: "center",
},
- {
- name: '鍑哄簱',
- type: 'bar',
- data: reportData.value.chartData.outValues || [],
- itemStyle: {
- color: '#F56C6C'
- }
- }
- ]
- }
- chart.setOption(option)
-}
+ tooltip: {
+ trigger: "axis",
+ },
+ legend: {
+ data: ["搴撳瓨閲�"],
+ top: 30,
+ },
+ xAxis: {
+ type: "category",
+ data: reportData.value.chartData.trendDates || [],
+ },
+ yAxis: {
+ type: "value",
+ },
+ series: [
+ {
+ name: "搴撳瓨閲�",
+ type: "line",
+ data: reportData.value.chartData.trendValues || [],
+ smooth: true,
+ itemStyle: {
+ color: "#409EFF",
+ },
+ },
+ ],
+ };
+ chart.setOption(option);
+ };
-// 缁勪欢鎸傝浇鏃惰缃粯璁ゆ椂闂�
-onMounted(() => {
- const today = new Date()
- searchForm.singleDate = today.toISOString().split('T')[0]
-
- const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000)
- searchForm.dateRange = [
- yesterday.toISOString().split('T')[0],
- today.toISOString().split('T')[0]
- ]
+ // 鍒濆鍖栧姣斿浘
+ const initComparisonChart = () => {
+ if (!comparisonChart.value) return;
- fetchStockRecordTypeOptions()
- // 鍒濆鍖栧姞杞戒竴娆℃暟鎹�
- handleQuery()
-})
+ const chart = echarts.init(comparisonChart.value);
+ const option = {
+ title: {
+ text: "杩涘嚭搴撳姣�",
+ left: "center",
+ },
+ tooltip: {
+ trigger: "axis",
+ },
+ legend: {
+ data: ["鍏ュ簱", "鍑哄簱"],
+ top: 30,
+ },
+ xAxis: {
+ type: "category",
+ data: reportData.value.chartData.comparisonDates || [],
+ },
+ yAxis: {
+ type: "value",
+ },
+ series: [
+ {
+ name: "鍏ュ簱",
+ type: "bar",
+ data: reportData.value.chartData.inValues || [],
+ itemStyle: {
+ color: "#67C23A",
+ },
+ },
+ {
+ name: "鍑哄簱",
+ type: "bar",
+ data: reportData.value.chartData.outValues || [],
+ itemStyle: {
+ color: "#F56C6C",
+ },
+ },
+ ],
+ };
+ chart.setOption(option);
+ };
+
+ // 缁勪欢鎸傝浇鏃惰缃粯璁ゆ椂闂�
+ onMounted(() => {
+ const today = new Date();
+ searchForm.singleDate = today.toISOString().split("T")[0];
+
+ const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);
+ searchForm.dateRange = [
+ yesterday.toISOString().split("T")[0],
+ today.toISOString().split("T")[0],
+ ];
+
+ fetchStockRecordTypeOptions();
+ // 鍒濆鍖栧姞杞戒竴娆℃暟鎹�
+ handleQuery();
+ });
</script>
<style scoped>
-.app-container {
- padding: 20px;
-}
+ .app-container {
+ padding: 20px;
+ }
-.search_form {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
- padding: 20px;
- background: #fff;
- border-radius: 4px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-}
+ .search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ padding: 20px;
+ background: #fff;
+ border-radius: 4px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ }
-.search_left {
- display: flex;
- align-items: center;
-}
+ .search_left {
+ display: flex;
+ align-items: center;
+ }
-.search_title {
- font-weight: 500;
- color: #333;
- margin-right: 8px;
-}
+ .search_title {
+ font-weight: 500;
+ color: #333;
+ margin-right: 8px;
+ }
-.ml10 {
- margin-left: 10px;
-}
+ .ml10 {
+ margin-left: 10px;
+ }
-.stats_cards {
- margin-bottom: 20px;
-}
+ .stats_cards {
+ margin-bottom: 20px;
+ }
-.stats_card {
- border-radius: 8px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
-}
+ .stats_card {
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ }
-.stats_content {
- display: flex;
- align-items: center;
- padding: 10px 0;
-}
+ .stats_content {
+ display: flex;
+ align-items: center;
+ padding: 10px 0;
+ }
-.stats_icon {
- width: 50px;
- height: 50px;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: 15px;
- font-size: 24px;
- color: #fff;
-}
+ .stats_icon {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 15px;
+ font-size: 24px;
+ color: #fff;
+ }
-.stats_icon.in {
- background: linear-gradient(135deg, #67C23A, #85CE61);
-}
+ .stats_icon.in {
+ background: linear-gradient(135deg, #67c23a, #85ce61);
+ }
-.stats_icon.out {
- background: linear-gradient(135deg, #F56C6C, #F78989);
-}
+ .stats_icon.out {
+ background: linear-gradient(135deg, #f56c6c, #f78989);
+ }
-.stats_icon.stock {
- background: linear-gradient(135deg, #409EFF, #66B1FF);
-}
+ .stats_icon.stock {
+ background: linear-gradient(135deg, #409eff, #66b1ff);
+ }
-.stats_icon.turnover {
- background: linear-gradient(135deg, #E6A23C, #EEBE77);
-}
+ .stats_icon.turnover {
+ background: linear-gradient(135deg, #e6a23c, #eebe77);
+ }
-.stats_info {
- flex: 1;
-}
+ .stats_info {
+ flex: 1;
+ }
-.stats_value {
- font-size: 24px;
- font-weight: bold;
- color: #333;
- line-height: 1;
- margin-bottom: 5px;
-}
+ .stats_value {
+ font-size: 24px;
+ font-weight: bold;
+ color: #333;
+ line-height: 1;
+ margin-bottom: 5px;
+ }
-.stats_label {
- font-size: 14px;
- color: #666;
-}
+ .stats_label {
+ font-size: 14px;
+ color: #666;
+ }
-.chart_section {
- margin-bottom: 20px;
-}
+ .chart_section {
+ margin-bottom: 20px;
+ }
-.table_section {
- margin-bottom: 20px;
-}
+ .table_section {
+ margin-bottom: 20px;
+ }
-:deep(.el-card__header) {
- background: #f8f9fa;
- border-bottom: 1px solid #e9ecef;
- font-weight: 500;
-}
+ :deep(.el-card__header) {
+ background: #f8f9fa;
+ border-bottom: 1px solid #e9ecef;
+ font-weight: 500;
+ }
-:deep(.el-table .el-table__header-wrapper th) {
- background-color: #F0F1F5 !important;
- color: #333333;
- font-weight: 600;
-}
+ :deep(.el-table .el-table__header-wrapper th) {
+ background-color: #f0f1f5 !important;
+ color: #333333;
+ font-weight: 600;
+ }
-:deep(.el-table .el-table__body-wrapper td) {
- padding: 8px 0;
-}
+ :deep(.el-table .el-table__body-wrapper td) {
+ padding: 8px 0;
+ }
</style>
--
Gitblit v1.9.3