Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions alert_function.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
-- =======================================
-- 药品库存智能预警功能数据库脚本
-- =======================================

-- 1. 为药品信息表添加最低库存阈值字段
ALTER TABLE `yaopinxinxi`
ADD COLUMN `low_stock_threshold` INT(11) NULL DEFAULT 10 COMMENT '最低库存阈值' AFTER `beizhu`;

-- 2. 创建库存预警记录表
DROP TABLE IF EXISTS `stock_alert`;
CREATE TABLE `stock_alert` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`yaopin_id` bigint(20) NOT NULL COMMENT '药品ID',
`yaopinmingcheng` varchar(200) NOT NULL COMMENT '药品名称',
`current_stock` int(11) NOT NULL COMMENT '当前库存',
`low_stock_threshold` int(11) NOT NULL COMMENT '最低库存阈值',
`alert_level` int(11) DEFAULT 1 COMMENT '预警级别(1:低库存预警, 2:紧急预警)',
`status` int(11) DEFAULT 0 COMMENT '处理状态(0:未处理, 1:已处理)',
`handler_id` bigint(20) DEFAULT NULL COMMENT '处理人ID',
`handler_name` varchar(200) DEFAULT NULL COMMENT '处理人姓名',
`handle_time` timestamp NULL DEFAULT NULL COMMENT '处理时间',
`handle_note` varchar(500) DEFAULT NULL COMMENT '处理备注',
PRIMARY KEY (`id`),
KEY `idx_yaopin_id` (`yaopin_id`),
KEY `idx_status` (`status`),
KEY `idx_addtime` (`addtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='库存预警记录表';

-- 3. 创建药品采购建议表
DROP TABLE IF EXISTS `purchase_suggestion`;
CREATE TABLE `purchase_suggestion` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`yaopin_id` bigint(20) NOT NULL COMMENT '药品ID',
`yaopinmingcheng` varchar(200) NOT NULL COMMENT '药品名称',
`guige` varchar(200) DEFAULT NULL COMMENT '规格',
`current_stock` int(11) NOT NULL COMMENT '当前库存',
`low_stock_threshold` int(11) NOT NULL COMMENT '最低库存阈值',
`suggested_quantity` int(11) NOT NULL COMMENT '建议采购数量',
`suggested_min_quantity` int(11) DEFAULT NULL COMMENT '建议最小采购量',
`suggested_max_quantity` int(11) DEFAULT NULL COMMENT '建议最大采购量',
`avg_monthly_usage` int(11) DEFAULT NULL COMMENT '月平均使用量',
`lead_time_days` int(11) DEFAULT NULL COMMENT '采购提前期(天)',
`urgency_level` int(11) DEFAULT 1 COMMENT '紧急程度(1:一般, 2:紧急, 3:非常紧急)',
`status` int(11) DEFAULT 0 COMMENT '状态(0:待审核, 1:已采纳, 2:已拒绝)',
`creator_id` bigint(20) DEFAULT NULL COMMENT '创建人ID',
`creator_name` varchar(200) DEFAULT NULL COMMENT '创建人姓名',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `idx_yaopin_id` (`yaopin_id`),
KEY `idx_status` (`status`),
KEY `idx_urgency_level` (`urgency_level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='药品采购建议表';

-- 4. 初始化现有药品的最低库存阈值为10
UPDATE `yaopinxinxi` SET `low_stock_threshold` = 10 WHERE `low_stock_threshold` IS NULL;

-- 5. 创建索引优化查询
CREATE INDEX idx_yaopin_kucun ON yaopinxinxi(kucun);
CREATE INDEX idx_yaopin_threshold ON yaopinxinxi(low_stock_threshold);
216 changes: 204 additions & 12 deletions manage_code/src/views/yaopinxinxi/list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
<el-button class="statis_btn" type="warning" @click="echartClick1" v-if="btnAuth('yaopinxinxi','药品库存统计')">
<i class="iconfont icon-bar-chart--line"></i>
药品库存统计
</el-button>
<el-button class="statis_btn" type="info" @click="checkStockAlertHandler" v-if="btnAuth('yaopinxinxi','库存预警检查')">
<i class="iconfont icon-tishi"></i>
库存预警检查
</el-button>
<el-button class="statis_btn" type="primary" @click="generatePurchaseSuggestionsHandler" v-if="btnAuth('yaopinxinxi','采购建议')">
<i class="iconfont icon-dingdan3"></i>
生成采购建议
</el-button>
</div>
</div>
Expand Down Expand Up @@ -101,16 +109,29 @@
</template>
</el-table-column>
<el-table-column min-width="140"
:resizable='true'
:sortable='true'
align="left"
header-align="left"
prop="kucun"
label="库存">
<template #default="scope">
:resizable='true'
:sortable='true'
align="left"
header-align="left"
prop="kucun"
label="库存">
<template #default="scope">
<el-tag :type="scope.row.kucun < scope.row.lowStockThreshold ? 'danger' : 'success'" size="small">
{{scope.row.kucun}}
</template>
</el-table-column>
</el-tag>
</template>
</el-table-column>
<el-table-column min-width="140"
:resizable='true'
:sortable='true'
align="left"
header-align="left"
prop="lowStockThreshold"
label="最低库存阈值">
<template #default="scope">
{{scope.row.lowStockThreshold || '-'}}
</template>
</el-table-column>
<el-table-column min-width="140"
:resizable='true'
:sortable='true'
Expand Down Expand Up @@ -150,9 +171,13 @@
入库
</el-button>
<el-button class="cross_btn" v-if="btnAuth('yaopinxinxi','出库')" type="success" @click="chukujiluCrossAddOrUpdateHandler(scope.row,'cross','','','','')">
<i class="iconfont icon-dingdan3"></i>
出库
</el-button>
<i class="iconfont icon-dingdan3"></i>
出库
</el-button>
<el-button class="cross_btn" v-if="btnAuth('yaopinxinxi','设置阈值')" type="info" @click="setThresholdHandler(scope.row)">
<i class="iconfont icon-xiugai5"></i>
设置阈值
</el-button>
</template>
</el-table-column>
</el-table>
Expand Down Expand Up @@ -182,6 +207,77 @@
</el-dialog>
<rukujiluFormModel ref="rukujiluFormModelRef" @formModelChange="formModelChange"></rukujiluFormModel>
<chukujiluFormModel ref="chukujiluFormModelRef" @formModelChange="formModelChange"></chukujiluFormModel>
<!-- 设置阈值对话框 -->
<el-dialog v-model="thresholdDialogVisible" title="设置最低库存阈值" width="500px">
<el-form :model="thresholdForm" label-width="120px">
<el-form-item label="药品名称">
{{thresholdForm.yaopinmingcheng}}
</el-form-item>
<el-form-item label="当前库存">
{{thresholdForm.kucun}}
</el-form-item>
<el-form-item label="最低库存阈值" required>
<el-input-number v-model="thresholdForm.lowStockThreshold" :min="0" :max="10000" style="width: 100%;" />
</el-form-item>
</el-form>
<template #footer>
<span class="formModel_btn_box">
<el-button class="cancel_btn" @click="thresholdDialogVisible=false">取消</el-button>
<el-button class="confirm_btn" type="primary" @click="saveThresholdHandler">确定</el-button>
</span>
</template>
</el-dialog>
<!-- 库存预警记录对话框 -->
<el-dialog v-model="stockAlertDialogVisible" title="库存预警记录" width="80%">
<el-table :data="stockAlertList" border v-loading="stockAlertLoading">
<el-table-column prop="yaopinmingcheng" label="药品名称" min-width="150" />
<el-table-column prop="currentStock" label="当前库存" min-width="120" />
<el-table-column prop="lowStockThreshold" label="最低阈值" min-width="120" />
<el-table-column prop="alertLevel" label="预警级别" min-width="120">
<template #default="scope">
<el-tag :type="scope.row.alertLevel === 1 ? 'warning' : 'danger'" size="small">
{{scope.row.alertLevel === 1 ? '轻度预警' : '重度预警'}}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" min-width="100">
<template #default="scope">
<el-tag :type="scope.row.status === 0 ? 'info' : 'success'" size="small">
{{scope.row.status === 0 ? '未处理' : '已处理'}}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="addtime" label="预警时间" min-width="180" />
</el-table>
<template #footer>
<span class="formModel_btn_box">
<el-button class="cancel_btn" @click="stockAlertDialogVisible=false">关闭</el-button>
</span>
</template>
</el-dialog>
<!-- 采购建议对话框 -->
<el-dialog v-model="purchaseSuggestionDialogVisible" title="药品采购建议" width="80%">
<el-table :data="purchaseSuggestionList" border v-loading="purchaseSuggestionLoading">
<el-table-column prop="yaopinmingcheng" label="药品名称" min-width="150" />
<el-table-column prop="suggestedQuantity" label="建议采购数量" min-width="120" />
<el-table-column prop="urgencyLevel" label="紧急程度" min-width="120">
<template #default="scope">
<el-tag :type="scope.row.urgencyLevel === 1 ? 'success' : (scope.row.urgencyLevel === 2 ? 'warning' : 'danger')" size="small">
{{scope.row.urgencyLevel === 1 ? '正常' : (scope.row.urgencyLevel === 2 ? '紧急' : '非常紧急')}}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="estimatedUsageDays" label="预计可用天数" min-width="120" />
<el-table-column prop="lastPurchaseQuantity" label="上次采购量" min-width="120" />
<el-table-column prop="remark" label="备注" min-width="200" show-overflow-tooltip />
<el-table-column prop="addtime" label="生成时间" min-width="180" />
</el-table>
<template #footer>
<span class="formModel_btn_box">
<el-button class="cancel_btn" @click="purchaseSuggestionDialogVisible=false">关闭</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
Expand Down Expand Up @@ -471,6 +567,102 @@
chukujiluFormModelRef.value.init(row.id,'cross','出库',row,'yaopinxinxi',statusColumnName,tips,statusColumnValue)
})
}
// 设置阈值
const thresholdDialogVisible = ref(false)
const thresholdForm = ref({
id: null,
yaopinmingcheng: '',
kucun: 0,
lowStockThreshold: 0
})
const setThresholdHandler = (row) => {
thresholdForm.value = {
id: row.id,
yaopinmingcheng: row.yaopinmingcheng,
kucun: row.kucun,
lowStockThreshold: row.lowStockThreshold || 0
}
thresholdDialogVisible.value = true
}
const saveThresholdHandler = () => {
if(thresholdForm.value.lowStockThreshold === undefined || thresholdForm.value.lowStockThreshold < 0) {
context?.$toolUtil.message('请输入有效的最低库存阈值','error')
return
}
context.$http({
url: `${tableName}/setThreshold`,
method: 'post',
data: {
id: thresholdForm.value.id,
lowStockThreshold: thresholdForm.value.lowStockThreshold
}
}).then(res => {
context?.$toolUtil.message('设置成功','success')
thresholdDialogVisible.value = false
getList()
})
}
// 库存预警检查
const checkStockAlertHandler = () => {
context.$http({
url: `${tableName}/checkStockAlert`,
method: 'post'
}).then(res => {
if(res.data.data && res.data.data.alertCount > 0) {
context?.$alert(`发现${res.data.data.alertCount}条库存预警,请查看预警记录`)
// 自动打开预警记录对话框
getStockAlertList()
} else {
context?.$toolUtil.message('库存检查完成,暂无预警','success')
}
})
}
// 库存预警记录
const stockAlertDialogVisible = ref(false)
const stockAlertList = ref([])
const stockAlertLoading = ref(false)
const getStockAlertList = () => {
stockAlertLoading.value = true
context.$http({
url: 'stockalert/list',
method: 'get',
params: { status: 0 }
}).then(res => {
stockAlertLoading.value = false
stockAlertList.value = res.data.data
stockAlertDialogVisible.value = true
})
}
// 生成采购建议
const generatePurchaseSuggestionsHandler = () => {
context.$http({
url: `${tableName}/generatePurchaseSuggestions`,
method: 'post'
}).then(res => {
if(res.data.data && res.data.data.suggestionCount > 0) {
context?.$alert(`已生成${res.data.data.suggestionCount}条采购建议,请查看`)
// 自动打开采购建议对话框
getPurchaseSuggestionList()
} else {
context?.$toolUtil.message('暂无需要采购的药品','success')
}
})
}
// 采购建议列表
const purchaseSuggestionDialogVisible = ref(false)
const purchaseSuggestionList = ref([])
const purchaseSuggestionLoading = ref(false)
const getPurchaseSuggestionList = () => {
purchaseSuggestionLoading.value = true
context.$http({
url: 'purchasesuggestion/list',
method: 'get'
}).then(res => {
purchaseSuggestionLoading.value = false
purchaseSuggestionList.value = res.data.data
purchaseSuggestionDialogVisible.value = true
})
}
//初始化
const init = () => {
let urlkucun = 'yaopinxinxi/remind/kucun/1'
Expand Down
Loading