From 648003a577ef7a03046269c77fc5cc64199945e7 Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期二, 20 一月 2026 17:06:47 +0800
Subject: [PATCH] Merge branch 'dev_tide' into dev_tide_zlglxt_xinlan
---
src/views/inventoryManagement/stockWarningLedger/index.vue | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 347 insertions(+), 0 deletions(-)
diff --git a/src/views/inventoryManagement/stockWarningLedger/index.vue b/src/views/inventoryManagement/stockWarningLedger/index.vue
new file mode 100644
index 0000000..d78ea30
--- /dev/null
+++ b/src/views/inventoryManagement/stockWarningLedger/index.vue
@@ -0,0 +1,347 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <el-form :model="searchForm" :inline="true">
+ <el-form-item label="浜у搧澶х被锛�">
+ <el-input
+ v-model="searchForm.productCategory"
+ placeholder="璇疯緭鍏ヤ骇鍝佸ぇ绫�"
+ clearable
+ style="width: 200px"
+ />
+ </el-form-item>
+ <el-form-item label="瑙勬牸鍨嬪彿锛�">
+ <el-input
+ v-model="searchForm.specificationModel"
+ placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+ clearable
+ style="width: 200px"
+ />
+ </el-form-item>
+ <el-form-item label="棰勮鐘舵�侊細">
+ <el-select
+ v-model="searchForm.warningStatus"
+ placeholder="璇烽�夋嫨棰勮鐘舵��"
+ clearable
+ style="width: 150px"
+ >
+ <el-option label="宸查璀�" value="宸查璀�" />
+ <el-option label="姝e父" value="姝e父" />
+ </el-select>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleQuery">鎼滅储</el-button>
+ <el-button @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+
+ <div class="table_list">
+ <div class="actions"></div>
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ style="width: 100%"
+ height="calc(100vh - 280px)"
+ >
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column label="鎵规鍙�" prop="code" width="130" show-overflow-tooltip />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" show-overflow-tooltip />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" show-overflow-tooltip />
+ <el-table-column label="褰撳墠搴撳瓨" prop="currentStock" width="120" show-overflow-tooltip>
+ <template #default="scope">
+ <span :class="getStockClass(scope.row)">{{ scope.row.currentStock || 0 }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏈�浣庡簱瀛�" prop="warnNum" width="120" show-overflow-tooltip />
+ <el-table-column label="棰勮绾у埆" prop="warningLevel" width="100" show-overflow-tooltip>
+ <template #default="scope">
+ <el-tag :type="getWarningLevelTag(scope.row.warningLevel)">
+ {{ scope.row.warningLevel || '-' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="棰勮鐘舵��" prop="warningStatus" width="100" show-overflow-tooltip>
+ <template #default="scope">
+ <el-tag :type="scope.row.warningStatus === '宸查璀�' ? 'danger' : 'success'">
+ {{ scope.row.warningStatus || '姝e父' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="棰勮鏃堕棿" prop="warningTime" width="150" show-overflow-tooltip />
+ <el-table-column label="棰勮缂鸿揣鏃堕棿" prop="expectedShortageTime" width="150" show-overflow-tooltip>
+ <template #default="scope">
+ <div v-if="scope.row.expectedShortageTime">
+ <div v-if="getCountdown(scope.row.expectedShortageTime).isExpired" class="countdown-expired">
+ <el-tag type="danger">宸茬己璐�</el-tag>
+ </div>
+ <div v-else class="countdown-timer">
+ <span :class="getCountdownClass(scope.row.expectedShortageTime)">
+ {{ getCountdown(scope.row.expectedShortageTime).text }}
+ </span>
+ </div>
+ </div>
+ <span v-else>-</span>
+ </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>
+
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+import pagination from '@/components/PIMTable/Pagination.vue'
+import {
+ getStockWarningLedgerPage
+} from '@/api/inventoryManagement/stockWarningLedger.js'
+
+// 鍝嶅簲寮忔暟鎹�
+const tableData = ref([])
+const tableLoading = ref(false)
+const total = ref(0)
+
+// 鍒嗛〉鍙傛暟
+const page = reactive({
+ current: 1,
+ size: 100
+})
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+ productCategory: '',
+ specificationModel: '',
+ warningStatus: ''
+})
+
+// 鑾峰彇鍒楄〃鏁版嵁
+const getList = () => {
+ tableLoading.value = true
+ const params = {
+ ...page,
+ ...searchForm
+ }
+ getStockWarningLedgerPage(params)
+ .then(res => {
+ tableLoading.value = false
+ if (res.code === 200) {
+ tableData.value = res.data.records || []
+ total.value = res.data.total || 0
+
+ // 璁$畻棰勮绾у埆鍜岀姸鎬�
+ tableData.value = tableData.value.map(item => {
+ const currentStock = parseFloat(item.inboundNum0 || item.currentStock || 0)
+ const warnNum = parseFloat(item.warnNum || 0)
+ const safetyStock = parseFloat(item.safetyStock || warnNum * 1.2)
+
+ // 璁$畻棰勮绾у埆
+ if (currentStock <= 0) {
+ item.warningLevel = '绱ф��'
+ item.warningStatus = '宸查璀�'
+ } else if (currentStock < warnNum) {
+ item.warningLevel = '閲嶈'
+ item.warningStatus = '宸查璀�'
+ } else if (currentStock < safetyStock) {
+ item.warningLevel = '涓�鑸�'
+ item.warningStatus = '宸查璀�'
+ } else {
+ item.warningLevel = ''
+ item.warningStatus = '姝e父'
+ }
+
+ // 璁$畻棰勮缂鸿揣鏃堕棿锛堝熀浜庢棩鍧囨秷鑰楅噺锛岃繖閲岀畝鍖栧鐞嗭級
+ if (item.warningStatus === '宸查璀�' && currentStock > 0 && warnNum > 0) {
+ const dailyConsumption = warnNum / 30 // 鍋囪30澶╂秷鑰楀畬鏈�浣庡簱瀛�
+ const daysRemaining = Math.floor(currentStock / dailyConsumption)
+ if (daysRemaining > 0) {
+ const date = new Date()
+ date.setDate(date.getDate() + daysRemaining)
+ item.expectedShortageTime = date.toISOString().split('T')[0]
+ }
+ }
+
+ item.currentStock = currentStock
+ item.safetyStock = safetyStock
+
+ return item
+ })
+ }
+ })
+ .catch(err => {
+ tableLoading.value = false
+ ElMessage.error(err.msg || '鑾峰彇鏁版嵁澶辫触')
+ })
+}
+
+// 鎼滅储
+const handleQuery = () => {
+ page.current = 1
+ getList()
+}
+
+// 閲嶇疆鎼滅储
+const resetQuery = () => {
+ Object.keys(searchForm).forEach(key => {
+ searchForm[key] = ''
+ })
+ handleQuery()
+}
+
+// 鍒嗛〉鍙樺寲
+const paginationChange = (obj) => {
+ page.current = obj.page
+ page.size = obj.limit
+ getList()
+}
+
+// 鑾峰彇搴撳瓨鏍峰紡绫�
+const getStockClass = (row) => {
+ const currentStock = parseFloat(row.currentStock || row.inboundNum0 || 0)
+ const warnNum = parseFloat(row.warnNum || 0)
+
+ if (currentStock <= 0) {
+ return 'text-danger'
+ } else if (currentStock < warnNum) {
+ return 'text-warning'
+ }
+ return 'text-success'
+}
+
+// 鑾峰彇棰勮绾у埆鏍囩鏍峰紡
+const getWarningLevelTag = (level) => {
+ const levelMap = {
+ '绱ф��': 'danger',
+ '閲嶈': 'warning',
+ '涓�鑸�': 'info'
+ }
+ return levelMap[level] || 'info'
+}
+
+// 鑾峰彇鍊掕鏃朵俊鎭�
+const getCountdown = (expectedTime) => {
+ if (!expectedTime) return { text: '-', isExpired: false }
+
+ const now = new Date().getTime()
+ const expected = new Date(expectedTime).getTime()
+ const diff = expected - now
+
+ if (diff <= 0) {
+ return { text: '宸茬己璐�', isExpired: true }
+ }
+
+ const days = Math.floor(diff / (1000 * 60 * 60 * 24))
+ const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
+ const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
+
+ if (days > 0) {
+ return { text: `${days}澶�${hours}灏忔椂`, isExpired: false }
+ } else if (hours > 0) {
+ return { text: `${hours}灏忔椂${minutes}鍒嗛挓`, isExpired: false }
+ } else {
+ return { text: `${minutes}鍒嗛挓`, isExpired: false }
+ }
+}
+
+// 鑾峰彇鍊掕鏃舵牱寮忕被
+const getCountdownClass = (expectedTime) => {
+ if (!expectedTime) return ''
+
+ const now = new Date().getTime()
+ const expected = new Date(expectedTime).getTime()
+ const diff = expected - now
+
+ if (diff <= 0) {
+ return 'countdown-expired'
+ } else if (diff <= 24 * 60 * 60 * 1000) { // 24灏忔椂鍐�
+ return 'countdown-urgent'
+ } else if (diff <= 7 * 24 * 60 * 60 * 1000) { // 7澶╁唴
+ return 'countdown-warning'
+ } else {
+ return 'countdown-normal'
+ }
+}
+
+// 椤甸潰鍔犺浇
+onMounted(() => {
+ getList()
+})
+</script>
+
+<style scoped lang="scss">
+.app-container {
+ padding: 20px;
+
+ .search_form {
+ background: #fff;
+ padding: 20px;
+ border-radius: 4px;
+ margin-bottom: 20px;
+ }
+
+ .table_list {
+ background: #fff;
+ border-radius: 4px;
+ padding: 20px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+
+ .actions {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 20px;
+ }
+ }
+
+ .text-danger {
+ color: #f56c6c;
+ font-weight: bold;
+ }
+
+ .text-warning {
+ color: #e6a23c;
+ font-weight: bold;
+ }
+
+ .text-success {
+ color: #67c23a;
+ font-weight: bold;
+ }
+
+ .countdown-timer {
+ font-weight: bold;
+ }
+
+ .countdown-normal {
+ color: #67c23a;
+ }
+
+ .countdown-warning {
+ color: #e6a23c;
+ }
+
+ .countdown-urgent {
+ color: #f56c6c;
+ animation: blink 1s infinite;
+ }
+
+ .countdown-expired {
+ color: #f56c6c;
+ font-weight: bold;
+ }
+
+ @keyframes blink {
+ 0%, 50% { opacity: 1; }
+ 51%, 100% { opacity: 0.5; }
+ }
+}
+</style>
--
Gitblit v1.9.3