✨ feat: python模型管理
This commit is contained in:
@@ -37,7 +37,7 @@ async def startup_event():
|
|||||||
model_manager = ModelManager()
|
model_manager = ModelManager()
|
||||||
|
|
||||||
# Look for models.json configuration file
|
# Look for models.json configuration file
|
||||||
models_json_path = os.getenv("MODELS_JSON", os.path.join(os.path.dirname(__file__), "..", "models", "models.json"))
|
models_json_path = os.getenv("MODELS_JSON", os.path.join(os.path.dirname(__file__), "..", "models.json"))
|
||||||
|
|
||||||
if os.path.exists(models_json_path):
|
if os.path.exists(models_json_path):
|
||||||
try:
|
try:
|
||||||
|
|||||||
14
python-inference-service/models.json
Normal file
14
python-inference-service/models.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "smoke",
|
||||||
|
"path": "models/smoke_model.py",
|
||||||
|
"size": [640, 640],
|
||||||
|
"comment": "烟雾检测模型"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "garbage",
|
||||||
|
"path": "models/garbage_model.py",
|
||||||
|
"size": [640, 640],
|
||||||
|
"comment": "垃圾检测模型"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"name": "yolov8_detector",
|
|
||||||
"path": "models/yolov8_model.py",
|
|
||||||
"size": [640, 640],
|
|
||||||
"comment": "YOLOv8检测模型,确保将训练好的best.pt文件放在models目录下"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
BIN
python-inference-service/models/smoke.pt
Normal file
BIN
python-inference-service/models/smoke.pt
Normal file
Binary file not shown.
207
python-inference-service/models/smoke_model.py
Normal file
207
python-inference-service/models/smoke_model.py
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
import os
|
||||||
|
import numpy as np
|
||||||
|
import cv2
|
||||||
|
from typing import List, Dict, Any
|
||||||
|
import torch
|
||||||
|
|
||||||
|
class Model:
|
||||||
|
"""
|
||||||
|
垃圾识别模型 - 直接加载 PyTorch 模型文件
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""初始化模型"""
|
||||||
|
# 获取当前文件所在目录路径
|
||||||
|
model_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
# 模型文件路径
|
||||||
|
model_path = os.path.join(model_dir, "smoke.pt")
|
||||||
|
|
||||||
|
print(f"正在加载垃圾识别模型: {model_path}")
|
||||||
|
|
||||||
|
# 加载 PyTorch 模型
|
||||||
|
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||||
|
print(f"使用设备: {self.device}")
|
||||||
|
|
||||||
|
# 使用 YOLOv5 或通用方式加载模型
|
||||||
|
try:
|
||||||
|
# 尝试使用 YOLOv5 加载
|
||||||
|
import sys
|
||||||
|
sys.path.append(os.path.dirname(model_dir)) # 添加父目录到路径
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 方法1: 如果安装了 YOLOv5
|
||||||
|
import yolov5
|
||||||
|
self.model = yolov5.load(model_path, device=self.device)
|
||||||
|
self.yolov5_api = True
|
||||||
|
print("使用 YOLOv5 包加载模型")
|
||||||
|
except (ImportError, ModuleNotFoundError):
|
||||||
|
# 方法2: 直接加载 YOLO 代码
|
||||||
|
from models.yolov5_utils import attempt_load
|
||||||
|
self.model = attempt_load(model_path, device=self.device)
|
||||||
|
self.yolov5_api = False
|
||||||
|
print("使用内置 YOLOv5 工具加载模型")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# 方法3: 通用 PyTorch 加载
|
||||||
|
print(f"YOLOv5 加载失败: {e}")
|
||||||
|
print("使用通用 PyTorch 加载")
|
||||||
|
self.model = torch.load(model_path, map_location=self.device)
|
||||||
|
if isinstance(self.model, dict) and 'model' in self.model:
|
||||||
|
self.model = self.model['model']
|
||||||
|
self.yolov5_api = False
|
||||||
|
|
||||||
|
# 如果是 ScriptModule,设置为评估模式
|
||||||
|
if isinstance(self.model, torch.jit.ScriptModule):
|
||||||
|
self.model.eval()
|
||||||
|
elif hasattr(self.model, 'eval'):
|
||||||
|
self.model.eval()
|
||||||
|
|
||||||
|
# 加载类别名称
|
||||||
|
self.classes = []
|
||||||
|
classes_path = os.path.join(model_dir, "classes.txt")
|
||||||
|
if os.path.exists(classes_path):
|
||||||
|
with open(classes_path, 'r', encoding='utf-8') as f:
|
||||||
|
self.classes = [line.strip() for line in f.readlines() if line.strip()]
|
||||||
|
print(f"已加载 {len(self.classes)} 个类别")
|
||||||
|
else:
|
||||||
|
# 如果模型自带类别信息
|
||||||
|
if hasattr(self.model, 'names') and self.model.names:
|
||||||
|
self.classes = self.model.names
|
||||||
|
print(f"使用模型自带类别,共 {len(self.classes)} 个类别")
|
||||||
|
else:
|
||||||
|
print("未找到类别文件,将使用数字索引作为类别名")
|
||||||
|
|
||||||
|
# 设置识别参数
|
||||||
|
self.conf_threshold = 0.25 # 置信度阈值
|
||||||
|
self.img_size = 640 # 默认输入图像大小
|
||||||
|
|
||||||
|
print("垃圾识别模型加载完成")
|
||||||
|
|
||||||
|
def preprocess(self, image: np.ndarray) -> np.ndarray:
|
||||||
|
"""预处理图像"""
|
||||||
|
# 如果是使用 YOLOv5 API,不需要预处理
|
||||||
|
if hasattr(self, 'yolov5_api') and self.yolov5_api:
|
||||||
|
return image
|
||||||
|
|
||||||
|
# 默认预处理:调整大小并归一化
|
||||||
|
img = cv2.resize(image, (self.img_size, self.img_size))
|
||||||
|
|
||||||
|
# BGR 转 RGB
|
||||||
|
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||||
|
|
||||||
|
# 归一化 [0, 255] -> [0, 1]
|
||||||
|
img = img / 255.0
|
||||||
|
|
||||||
|
# HWC -> CHW (高度,宽度,通道 -> 通道,高度,宽度)
|
||||||
|
img = img.transpose(2, 0, 1)
|
||||||
|
|
||||||
|
# 转为 torch tensor
|
||||||
|
img = torch.from_numpy(img).float()
|
||||||
|
|
||||||
|
# 添加批次维度
|
||||||
|
img = img.unsqueeze(0)
|
||||||
|
|
||||||
|
# 移至设备
|
||||||
|
img = img.to(self.device)
|
||||||
|
|
||||||
|
return img
|
||||||
|
|
||||||
|
def predict(self, image: np.ndarray) -> List[Dict[str, Any]]:
|
||||||
|
"""模型推理"""
|
||||||
|
original_height, original_width = image.shape[:2]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 如果使用 YOLOv5 API
|
||||||
|
if hasattr(self, 'yolov5_api') and self.yolov5_api:
|
||||||
|
# YOLOv5 API 直接处理图像
|
||||||
|
results = self.model(image)
|
||||||
|
|
||||||
|
# 提取检测结果
|
||||||
|
predictions = results.pred[0] # 第一批次的预测
|
||||||
|
|
||||||
|
detections = []
|
||||||
|
for *xyxy, conf, cls_id in predictions.cpu().numpy():
|
||||||
|
x1, y1, x2, y2 = xyxy
|
||||||
|
|
||||||
|
# 转换为归一化坐标 (x, y, w, h)
|
||||||
|
x = x1 / original_width
|
||||||
|
y = y1 / original_height
|
||||||
|
w = (x2 - x1) / original_width
|
||||||
|
h = (y2 - y1) / original_height
|
||||||
|
|
||||||
|
# 整数类别 ID
|
||||||
|
cls_id = int(cls_id)
|
||||||
|
|
||||||
|
# 获取类别名称
|
||||||
|
class_name = f"cls{cls_id}"
|
||||||
|
if 0 <= cls_id < len(self.classes):
|
||||||
|
class_name = self.classes[cls_id]
|
||||||
|
|
||||||
|
# 添加检测结果
|
||||||
|
if conf >= self.conf_threshold:
|
||||||
|
detections.append({
|
||||||
|
'bbox': (x, y, w, h),
|
||||||
|
'class_id': cls_id,
|
||||||
|
'confidence': float(conf)
|
||||||
|
})
|
||||||
|
|
||||||
|
return detections
|
||||||
|
|
||||||
|
else:
|
||||||
|
# 通用 PyTorch 模型处理
|
||||||
|
# 预处理图像
|
||||||
|
img = self.preprocess(image)
|
||||||
|
|
||||||
|
# 推理
|
||||||
|
with torch.no_grad():
|
||||||
|
outputs = self.model(img)
|
||||||
|
|
||||||
|
# 后处理结果(这里需要根据模型输出格式调整)
|
||||||
|
detections = []
|
||||||
|
|
||||||
|
# 假设输出格式是 YOLO 风格:[batch_idx, x1, y1, x2, y2, conf, cls_id]
|
||||||
|
if isinstance(outputs, torch.Tensor) and outputs.dim() == 2 and outputs.size(1) >= 6:
|
||||||
|
for *xyxy, conf, cls_id in outputs.cpu().numpy():
|
||||||
|
if conf >= self.conf_threshold:
|
||||||
|
x1, y1, x2, y2 = xyxy
|
||||||
|
|
||||||
|
# 转换为归一化坐标 (x, y, w, h)
|
||||||
|
x = x1 / original_width
|
||||||
|
y = y1 / original_height
|
||||||
|
w = (x2 - x1) / original_width
|
||||||
|
h = (y2 - y1) / original_height
|
||||||
|
|
||||||
|
# 整数类别 ID
|
||||||
|
cls_id = int(cls_id)
|
||||||
|
|
||||||
|
detections.append({
|
||||||
|
'bbox': (x, y, w, h),
|
||||||
|
'class_id': cls_id,
|
||||||
|
'confidence': float(conf)
|
||||||
|
})
|
||||||
|
# 处理其他可能的输出格式
|
||||||
|
else:
|
||||||
|
# 这里需要根据模型的实际输出格式进行适配
|
||||||
|
print("警告:无法识别的模型输出格式,请检查模型类型")
|
||||||
|
|
||||||
|
return detections
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"推理过程中出错: {str(e)}")
|
||||||
|
# 出错时返回空结果
|
||||||
|
return []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def applies_nms(self) -> bool:
|
||||||
|
"""模型是否内部应用了 NMS"""
|
||||||
|
# YOLOv5 会自动应用 NMS
|
||||||
|
return True
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""释放资源"""
|
||||||
|
if hasattr(self, 'model'):
|
||||||
|
# 删除模型以释放 GPU 内存
|
||||||
|
del self.model
|
||||||
|
if torch.cuda.is_available():
|
||||||
|
torch.cuda.empty_cache()
|
||||||
|
print("垃圾识别模型已关闭")
|
||||||
341
rtsp-vue/src/views/video/model/dict.vue
Normal file
341
rtsp-vue/src/views/video/model/dict.vue
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
|
||||||
|
<el-form-item label="字典标签" prop="dictLabel">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.dictLabel"
|
||||||
|
placeholder="请输入字典标签"
|
||||||
|
clearable
|
||||||
|
style="width: 200px"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-select v-model="queryParams.status" placeholder="数据状态" clearable style="width: 200px">
|
||||||
|
<el-option
|
||||||
|
v-for="dict in sys_normal_disable"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
:value="dict.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="Plus"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['system:dict:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="Edit"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['system:dict:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="Delete"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['system:dict:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="Download"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['system:dict:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="字典编码" align="center" prop="dictCode" />
|
||||||
|
<el-table-column label="字典标签" align="center" prop="dictLabel">
|
||||||
|
<template #default="scope">
|
||||||
|
<span v-if="(scope.row.listClass == '' || scope.row.listClass == 'default') && (scope.row.cssClass == '' || scope.row.cssClass == null)">{{ scope.row.dictLabel }}</span>
|
||||||
|
<el-tag v-else :type="scope.row.listClass == 'primary' ? '' : scope.row.listClass" :class="scope.row.cssClass">{{ scope.row.dictLabel }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="字典键值" align="center" prop="dictValue" />
|
||||||
|
<el-table-column label="字典排序" align="center" prop="dictSort" />
|
||||||
|
<el-table-column label="状态" align="center" prop="status">
|
||||||
|
<template #default="scope">
|
||||||
|
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dict:edit']">修改</el-button>
|
||||||
|
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dict:remove']">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
:total="total"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改参数配置对话框 -->
|
||||||
|
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="dataRef" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="数据标签" prop="dictLabel">
|
||||||
|
<el-input v-model="form.dictLabel" placeholder="请输入数据标签" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据键值" prop="dictValue">
|
||||||
|
<el-input v-model="form.dictValue" placeholder="请输入数据键值" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="样式属性" prop="cssClass">
|
||||||
|
<el-input v-model="form.cssClass" placeholder="请输入样式属性" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="显示排序" prop="dictSort">
|
||||||
|
<el-input-number v-model="form.dictSort" controls-position="right" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="回显样式" prop="listClass">
|
||||||
|
<el-select v-model="form.listClass">
|
||||||
|
<el-option
|
||||||
|
v-for="item in listClassOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label + '(' + item.value + ')'"
|
||||||
|
:value="item.value"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="status">
|
||||||
|
<el-radio-group v-model="form.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in sys_normal_disable"
|
||||||
|
:key="dict.value"
|
||||||
|
:value="dict.value"
|
||||||
|
>{{ dict.label }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="Data">
|
||||||
|
import useDictStore from '@/store/modules/dict'
|
||||||
|
import { optionselect as getDictOptionselect, getType } from "@/api/system/dict/type";
|
||||||
|
import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
||||||
|
|
||||||
|
const dataList = ref([]);
|
||||||
|
const open = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
const title = ref("");
|
||||||
|
const defaultDictType = ref("");
|
||||||
|
const typeOptions = ref([]);
|
||||||
|
const route = useRoute();
|
||||||
|
// 数据标签回显样式
|
||||||
|
const listClassOptions = ref([
|
||||||
|
{ value: "default", label: "默认" },
|
||||||
|
{ value: "primary", label: "主要" },
|
||||||
|
{ value: "success", label: "成功" },
|
||||||
|
{ value: "info", label: "信息" },
|
||||||
|
{ value: "warning", label: "警告" },
|
||||||
|
{ value: "danger", label: "危险" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const data = reactive({
|
||||||
|
form: {},
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
dictType: undefined,
|
||||||
|
dictLabel: undefined,
|
||||||
|
status: undefined
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
dictLabel: [{ required: true, message: "数据标签不能为空", trigger: "blur" }],
|
||||||
|
dictValue: [{ required: true, message: "数据键值不能为空", trigger: "blur" }],
|
||||||
|
dictSort: [{ required: true, message: "数据顺序不能为空", trigger: "blur" }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询字典类型详细 */
|
||||||
|
function getTypes(dictId) {
|
||||||
|
getType(dictId).then(response => {
|
||||||
|
queryParams.value.dictType = response.data.dictType;
|
||||||
|
defaultDictType.value = response.data.dictType;
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询字典类型列表 */
|
||||||
|
function getTypeList() {
|
||||||
|
getDictOptionselect().then(response => {
|
||||||
|
typeOptions.value = response.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询字典数据列表 */
|
||||||
|
function getList() {
|
||||||
|
loading.value = true;
|
||||||
|
listData(queryParams.value).then(response => {
|
||||||
|
dataList.value = response.rows;
|
||||||
|
total.value = response.total;
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
function cancel() {
|
||||||
|
open.value = false;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
function reset() {
|
||||||
|
form.value = {
|
||||||
|
dictCode: undefined,
|
||||||
|
dictLabel: undefined,
|
||||||
|
dictValue: undefined,
|
||||||
|
cssClass: undefined,
|
||||||
|
listClass: "default",
|
||||||
|
dictSort: 0,
|
||||||
|
status: "0",
|
||||||
|
remark: undefined
|
||||||
|
};
|
||||||
|
proxy.resetForm("dataRef");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
function handleQuery() {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 返回按钮操作 */
|
||||||
|
function handleClose() {
|
||||||
|
const obj = { path: "/system/dict" };
|
||||||
|
proxy.$tab.closeOpenPage(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
function resetQuery() {
|
||||||
|
proxy.resetForm("queryRef");
|
||||||
|
queryParams.value.dictType = defaultDictType.value;
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
function handleAdd() {
|
||||||
|
reset();
|
||||||
|
open.value = true;
|
||||||
|
title.value = "添加字典数据";
|
||||||
|
form.value.dictType = queryParams.value.dictType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
function handleSelectionChange(selection) {
|
||||||
|
ids.value = selection.map(item => item.dictCode);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
function handleUpdate(row) {
|
||||||
|
reset();
|
||||||
|
const dictCode = row.dictCode || ids.value;
|
||||||
|
getData(dictCode).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
open.value = true;
|
||||||
|
title.value = "修改字典数据";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
function submitForm() {
|
||||||
|
proxy.$refs["dataRef"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (form.value.dictCode != undefined) {
|
||||||
|
updateData(form.value).then(response => {
|
||||||
|
useDictStore().removeDict(queryParams.value.dictType);
|
||||||
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
|
open.value = false;
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addData(form.value).then(response => {
|
||||||
|
useDictStore().removeDict(queryParams.value.dictType);
|
||||||
|
proxy.$modal.msgSuccess("新增成功");
|
||||||
|
open.value = false;
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
function handleDelete(row) {
|
||||||
|
const dictCodes = row.dictCode || ids.value;
|
||||||
|
proxy.$modal.confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?').then(function() {
|
||||||
|
return delData(dictCodes);
|
||||||
|
}).then(() => {
|
||||||
|
getList();
|
||||||
|
proxy.$modal.msgSuccess("删除成功");
|
||||||
|
useDictStore().removeDict(queryParams.value.dictType);
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
function handleExport() {
|
||||||
|
proxy.download("system/dict/data/export", {
|
||||||
|
...queryParams.value
|
||||||
|
}, `dict_data_${new Date().getTime()}.xlsx`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTypes(105);
|
||||||
|
getTypeList();
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user