修改枚举

This commit is contained in:
2025-11-06 20:33:59 +08:00
parent df88ce9315
commit d898d1eb48
15 changed files with 425 additions and 92 deletions

View File

@@ -0,0 +1,7 @@
# 需求
后端将所有枚举修改为中文, 前端对应调整
## 涉及枚举
## 任务列表

View File

@@ -993,6 +993,7 @@
}, },
{ {
"enum": [ "enum": [
7,
-1, -1,
0, 0,
1, 1,
@@ -1002,12 +1003,12 @@
5, 5,
-1, -1,
5, 5,
6, 6
7
], ],
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"x-enum-varnames": [ "x-enum-varnames": [
"_numLevels",
"DebugLevel", "DebugLevel",
"InfoLevel", "InfoLevel",
"WarnLevel", "WarnLevel",
@@ -1017,8 +1018,7 @@
"FatalLevel", "FatalLevel",
"_minLevel", "_minLevel",
"_maxLevel", "_maxLevel",
"InvalidLevel", "InvalidLevel"
"_numLevels"
], ],
"name": "level", "name": "level",
"in": "query" "in": "query"
@@ -4055,6 +4055,46 @@
} }
} }
} }
},
"/healthz": {
"get": {
"description": "检查服务进程是否运行正常,只要服务能响应就返回 200 OK。",
"produces": [
"application/json"
],
"tags": [
"健康检查"
],
"summary": "服务存活检查",
"responses": {
"200": {
"description": "服务存活",
"schema": {
"$ref": "#/definitions/controller.Response"
}
}
}
}
},
"/readyz": {
"get": {
"description": "检查服务是否已准备好接收流量。当前实现为只要服务能响应即代表就绪。",
"produces": [
"application/json"
],
"tags": [
"健康检查"
],
"summary": "服务就绪检查",
"responses": {
"200": {
"description": "服务已就绪",
"schema": {
"$ref": "#/definitions/controller.Response"
}
}
}
}
} }
}, },
"definitions": { "definitions": {
@@ -6854,6 +6894,7 @@
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"enum": [ "enum": [
7,
-1, -1,
0, 0,
1, 1,
@@ -6863,10 +6904,10 @@
5, 5,
-1, -1,
5, 5,
6, 6
7
], ],
"x-enum-varnames": [ "x-enum-varnames": [
"_numLevels",
"DebugLevel", "DebugLevel",
"InfoLevel", "InfoLevel",
"WarnLevel", "WarnLevel",
@@ -6876,8 +6917,7 @@
"FatalLevel", "FatalLevel",
"_minLevel", "_minLevel",
"_maxLevel", "_maxLevel",
"InvalidLevel", "InvalidLevel"
"_numLevels"
] ]
} }
}, },

View File

@@ -27,8 +27,8 @@
<el-form-item label="类别" prop="category"> <el-form-item label="类别" prop="category">
<el-select v-model="formData.category" placeholder="请选择类别" @change="handleCategoryChange"> <el-select v-model="formData.category" placeholder="请选择类别" @change="handleCategoryChange">
<el-option label="执行器" value="执行器" /> <el-option :label="DeviceCategory.ACTUATOR" :value="DeviceCategory.ACTUATOR" />
<el-option label="传感器" value="传感器" /> <el-option :label="DeviceCategory.SENSOR" :value="DeviceCategory.SENSOR" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@@ -42,7 +42,7 @@
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="formData.category === '传感器'" v-if="formData.category === DeviceCategory.SENSOR"
label="值描述 (JSON)" label="值描述 (JSON)"
prop="values" prop="values"
> >
@@ -68,6 +68,7 @@
import { ref, reactive, computed, watch, nextTick } from 'vue'; import { ref, reactive, computed, watch, nextTick } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import deviceTemplateService from '../services/deviceTemplateService.js'; import deviceTemplateService from '../services/deviceTemplateService.js';
import { DeviceCategory } from '../enums.js';
// 默认的JSON模板 // 默认的JSON模板
const DEFAULT_ACTUATOR_COMMANDS = JSON.stringify({ const DEFAULT_ACTUATOR_COMMANDS = JSON.stringify({
@@ -115,7 +116,7 @@ export default {
name: '', name: '',
manufacturer: '', manufacturer: '',
description: '', description: '',
category: '执行器', // 默认执行器 category: DeviceCategory.ACTUATOR, // 默认执行器
commands: DEFAULT_ACTUATOR_COMMANDS, // 预填充执行器指令 commands: DEFAULT_ACTUATOR_COMMANDS, // 预填充执行器指令
values: '', values: '',
}); });
@@ -143,7 +144,7 @@ export default {
{ validator: validateJson, message: '指令参数必须是有效的 JSON 格式', trigger: 'blur' }, { validator: validateJson, message: '指令参数必须是有效的 JSON 格式', trigger: 'blur' },
], ],
values: [ values: [
{ required: formData.category === '传感器', message: '请输入值描述', trigger: 'blur' }, { required: formData.category === DeviceCategory.SENSOR, message: '请输入值描述', trigger: 'blur' },
{ validator: validateJson, message: '值描述必须是有效的 JSON 格式', trigger: 'blur' }, { validator: validateJson, message: '值描述必须是有效的 JSON 格式', trigger: 'blur' },
], ],
})); }));
@@ -153,10 +154,10 @@ export default {
}); });
const handleCategoryChange = (newCategory) => { const handleCategoryChange = (newCategory) => {
if (newCategory === '执行器') { if (newCategory === DeviceCategory.ACTUATOR) {
formData.commands = DEFAULT_ACTUATOR_COMMANDS; formData.commands = DEFAULT_ACTUATOR_COMMANDS;
formData.values = ''; // 执行器没有values formData.values = ''; // 执行器没有values
} else if (newCategory === '传感器') { } else if (newCategory === DeviceCategory.SENSOR) {
formData.commands = DEFAULT_SENSOR_COMMANDS; formData.commands = DEFAULT_SENSOR_COMMANDS;
formData.values = DEFAULT_SENSOR_VALUES; // 传感器预填充values formData.values = DEFAULT_SENSOR_VALUES; // 传感器预填充values
} }
@@ -193,7 +194,7 @@ export default {
commands: JSON.parse(formData.commands), commands: JSON.parse(formData.commands),
}; };
if (formData.category === '传感器' && formData.values) { if (formData.category === DeviceCategory.SENSOR && formData.values) {
submitData.values = JSON.parse(formData.values); submitData.values = JSON.parse(formData.values);
} }
@@ -227,9 +228,9 @@ export default {
formData.manufacturer = newVal.manufacturer; formData.manufacturer = newVal.manufacturer;
formData.description = newVal.description; formData.description = newVal.description;
if (newVal.category === 'sensor') { if (newVal.category === 'sensor') {
formData.category = '传感器'; formData.category = DeviceCategory.SENSOR;
} else if (newVal.category === 'actuator') { } else if (newVal.category === 'actuator') {
formData.category = '执行器'; formData.category = DeviceCategory.ACTUATOR;
} else { } else {
formData.category = newVal.category; formData.category = newVal.category;
} }
@@ -274,6 +275,7 @@ export default {
handleCategoryChange, handleCategoryChange,
handleClose, handleClose,
handleSubmit, handleSubmit,
DeviceCategory,
}; };
}, },
}; };

View File

@@ -39,6 +39,7 @@
import { ref, reactive, watch, computed, nextTick } from 'vue'; import { ref, reactive, watch, computed, nextTick } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { createPen, updatePen } from '@/api/pen.js'; import { createPen, updatePen } from '@/api/pen.js';
import { PenStatus } from '@/enums.js';
export default { export default {
name: 'PenForm', name: 'PenForm',
@@ -60,13 +61,13 @@ export default {
setup(props, { emit }) { setup(props, { emit }) {
const formRef = ref(null); const formRef = ref(null);
const loading = ref(false); const loading = ref(false);
const penStatusOptions = ["空闲", "使用中", "病猪栏", "康复栏", "清洗消毒", "维修中"]; const penStatusOptions = Object.values(PenStatus);
const initialFormData = () => ({ const initialFormData = () => ({
id: null, id: null,
pen_number: '', pen_number: '',
capacity: 10, capacity: 10,
status: '空闲', status: PenStatus.EMPTY,
house_id: null house_id: null
}); });

View File

@@ -53,6 +53,7 @@
import {ref, reactive, watch, computed, nextTick} from 'vue'; import {ref, reactive, watch, computed, nextTick} from 'vue';
import {ElMessage} from 'element-plus'; import {ElMessage} from 'element-plus';
import {createPigBatch, updatePigBatch} from '@/api/pigBatch.js'; import {createPigBatch, updatePigBatch} from '@/api/pigBatch.js';
import { PigBatchOriginType, PigBatchStatus } from '@/enums.js';
export default { export default {
name: 'PigBatchForm', name: 'PigBatchForm',
@@ -75,16 +76,16 @@ export default {
const formRef = ref(null); const formRef = ref(null);
const loading = ref(false); const loading = ref(false);
const originTypeOptions = ["自繁", "外购"]; const originTypeOptions = Object.values(PigBatchOriginType);
const batchStatusOptions = ["保育", "生长", "育肥", "待售", "已出售", "已归档"]; const batchStatusOptions = Object.values(PigBatchStatus);
const initialFormData = () => ({ const initialFormData = () => ({
id: null, id: null,
batch_number: '', batch_number: '',
initial_count: 1, initial_count: 1,
origin_type: '自繁', origin_type: PigBatchOriginType.SELF_FARROWED,
start_date: '', start_date: '',
status: '保育', status: PigBatchStatus.WEANING,
}); });
const formData = reactive(initialFormData()); const formData = reactive(initialFormData());
@@ -182,8 +183,8 @@ export default {
formData.id = props.batchData.id; formData.id = props.batchData.id;
formData.batch_number = props.batchData.batch_number || ''; formData.batch_number = props.batchData.batch_number || '';
formData.initial_count = props.batchData.initial_count || 1; formData.initial_count = props.batchData.initial_count || 1;
formData.origin_type = props.batchData.origin_type || '自繁'; formData.origin_type = props.batchData.origin_type || PigBatchOriginType.SELF_FARROWED;
formData.status = props.batchData.status || '保育'; formData.status = props.batchData.status || PigBatchStatus.WEANING;
formData.start_date = fromRFC3339(props.batchData.start_date); formData.start_date = fromRFC3339(props.batchData.start_date);
} }
nextTick(() => { nextTick(() => {

View File

@@ -18,6 +18,7 @@
<script> <script>
import { computed } from 'vue'; import { computed } from 'vue';
import { PenStatus } from '@/enums.js';
export default { export default {
name: 'PigBatchPenCard', name: 'PigBatchPenCard',
@@ -39,14 +40,14 @@ export default {
setup(props, { emit }) { setup(props, { emit }) {
const statusType = computed(() => { const statusType = computed(() => {
switch (props.pen.status) { switch (props.pen.status) {
case '使用中': case PenStatus.OCCUPIED:
return 'success'; return 'success';
case '病猪栏': case PenStatus.SICK_PEN:
case '维修中': case PenStatus.UNDER_MAINTENANCE:
return 'danger'; return 'danger';
case '清洗消毒': case PenStatus.CLEANING:
return 'warning'; return 'warning';
case '空闲': case PenStatus.EMPTY:
default: default:
return 'info'; return 'info';
} }

View File

@@ -18,6 +18,7 @@
<script> <script>
import { computed } from 'vue'; import { computed } from 'vue';
import { PenStatus } from '@/enums.js';
export default { export default {
name: 'PigPenInfoCard', name: 'PigPenInfoCard',
@@ -31,14 +32,14 @@ export default {
setup(props, { emit }) { setup(props, { emit }) {
const statusType = computed(() => { const statusType = computed(() => {
switch (props.pen.status) { switch (props.pen.status) {
case '使用中': case PenStatus.OCCUPIED:
return 'success'; return 'success';
case '病猪栏': case PenStatus.SICK_PEN:
case '维修中': case PenStatus.UNDER_MAINTENANCE:
return 'danger'; return 'danger';
case '清洗消毒': case PenStatus.CLEANING:
return 'warning'; return 'warning';
case '空闲': case PenStatus.EMPTY:
default: default:
return 'info'; return 'info';
} }

View File

@@ -31,8 +31,8 @@
<!-- 执行方式 --> <!-- 执行方式 -->
<el-form-item label="执行方式" prop="execution_type"> <el-form-item label="执行方式" prop="execution_type">
<el-radio-group v-model="formData.execution_type" @change="handleExecutionTypeChange"> <el-radio-group v-model="formData.execution_type" @change="handleExecutionTypeChange">
<el-radio label="automatic">自动执行</el-radio> <el-radio :label="PlanExecutionType.AUTOMATIC">自动执行</el-radio>
<el-radio label="manual">手动执行</el-radio> <el-radio :label="PlanExecutionType.MANUAL">手动执行</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
@@ -40,7 +40,7 @@
<el-form-item <el-form-item
label="执行次数" label="执行次数"
prop="execute_num" prop="execute_num"
v-if="formData.execution_type === 'automatic'"> v-if="formData.execution_type === PlanExecutionType.AUTOMATIC">
<el-input-number <el-input-number
v-model="formData.execute_num" v-model="formData.execute_num"
:min="0" :min="0"
@@ -56,7 +56,7 @@
<el-form-item <el-form-item
label="执行频率" label="执行频率"
prop="cron_expression" prop="cron_expression"
v-if="formData.execution_type === 'automatic'"> v-if="formData.execution_type === PlanExecutionType.AUTOMATIC">
<cron-expression-editor <cron-expression-editor
v-model="formData.cron_expression" v-model="formData.cron_expression"
/> />
@@ -82,6 +82,7 @@
import { ref, reactive, computed, watch } from 'vue'; import { ref, reactive, computed, watch } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import CronExpressionEditor from './CronExpressionEditor.vue'; import CronExpressionEditor from './CronExpressionEditor.vue';
import { PlanExecutionType } from '../enums.js';
export default { export default {
name: 'PlanForm', name: 'PlanForm',
@@ -115,7 +116,7 @@ export default {
id: null, id: null,
name: '', name: '',
description: '', description: '',
execution_type: 'automatic', // 默认自动执行 execution_type: PlanExecutionType.AUTOMATIC, // 默认自动执行
execute_num: 0, // 0表示无限执行 execute_num: 0, // 0表示无限执行
cron_expression: '', // cron表达式 cron_expression: '', // cron表达式
content_type: 'tasks' // 默认类型为tasks content_type: 'tasks' // 默认类型为tasks
@@ -145,7 +146,7 @@ export default {
// 处理执行方式变更 // 处理执行方式变更
const handleExecutionTypeChange = (value) => { const handleExecutionTypeChange = (value) => {
// 如果切换为手动执行清空执行次数和cron表达式 // 如果切换为手动执行清空执行次数和cron表达式
if (value === '手动') { if (value === PlanExecutionType.MANUAL) {
formData.execute_num = 0; formData.execute_num = 0;
formData.cron_expression = ''; formData.cron_expression = '';
} else { } else {
@@ -178,7 +179,7 @@ export default {
} }
// 如果是手动执行清除执行次数和cron表达式 // 如果是手动执行清除执行次数和cron表达式
if (formData.execution_type === '手动') { if (formData.execution_type === PlanExecutionType.MANUAL) {
submitData.execute_num = 0; submitData.execute_num = 0;
submitData.cron_expression = ''; submitData.cron_expression = '';
} }
@@ -220,7 +221,7 @@ export default {
} }
}); });
// 默认值 // 默认值
formData.execution_type = 'automatic'; formData.execution_type = PlanExecutionType.AUTOMATIC;
formData.content_type = 'tasks'; // 确保content_type有默认值 formData.content_type = 'tasks'; // 确保content_type有默认值
} }
}, { immediate: true }); }, { immediate: true });
@@ -233,7 +234,8 @@ export default {
title, title,
handleExecutionTypeChange, handleExecutionTypeChange,
handleClose, handleClose,
handleSubmit handleSubmit,
PlanExecutionType
}; };
} }
}; };

277
src/enums.js Normal file
View File

@@ -0,0 +1,277 @@
/**
* @fileoverview 枚举常量定义文件
* @author Divano
* @date 2023-11-20
*/
/**
* 业务状态码
* @enum {number}
*/
export const ResponseCode = {
SUCCESS: 2000, // 操作成功
CREATED: 2001, // 创建成功
BAD_REQUEST: 4000, // 请求参数错误
UNAUTHORIZED: 4001, // 未授权
FORBIDDEN: 4003, // 禁止访问
NOT_FOUND: 4004, // 资源未找到
CONFLICT: 4009, // 资源冲突
INTERNAL_ERROR: 5000, // 服务器内部错误
SERVICE_UNAVAILABLE: 5003, // 服务不可用
};
/**
* 审计状态
* @enum {string}
*/
export const AuditStatus = {
SUCCESS: '成功',
FAILED: '失败',
};
/**
* 设备类别
* @enum {string}
*/
export const DeviceCategory = {
ACTUATOR: '执行器',
SENSOR: '传感器',
};
/**
* 执行状态
* @enum {string}
*/
export const ExecutionStatus = {
STARTED: '已开始', // 开始执行
COMPLETED: '已完成', // 执行完成
FAILED: '失败', // 执行失败
CANCELLED: '已取消', // 执行取消
WAITING: '等待中', // 等待执行 (用于预写日志)
};
/**
* 日志变更类型
* @enum {string}
*/
export const LogChangeType = {
DEATH: '死亡',
CULL: '淘汰',
SALE: '销售',
BUY: '购买',
TRANSFER_IN: '转入',
TRANSFER_OUT: '转出',
CORRECTION: '盘点校正',
};
/**
* 用药原因
* @enum {string}
*/
export const MedicationReasonType = {
PREVENTIVE: '预防',
TREATMENT: '治疗',
HEALTH_CARE: '保健',
};
/**
* 通知状态
* @enum {string}
*/
export const NotificationStatus = {
SUCCESS: '发送成功', // 通知已成功发送
FAILED: '发送失败', // 通知发送失败
SKIPPED: '已跳过', // 通知因某些原因被跳过(例如:用户未配置联系方式)
};
/**
* 猪栏状态
* @enum {string}
*/
export const PenStatus = {
EMPTY: '空闲',
OCCUPIED: '使用中',
SICK_PEN: '病猪栏',
RECOVERING: '康复栏',
CLEANING: '清洗消毒',
UNDER_MAINTENANCE: '维修中',
};
/**
* 待采集请求状态
* @enum {string}
*/
export const PendingCollectionStatus = {
PENDING: '等待中', // 请求已发送,等待设备响应
FULFILLED: '已完成', // 已收到设备响应并成功处理
TIMED_OUT: '已超时', // 请求超时,未收到设备响应
};
/**
* 猪批次来源
* @enum {string}
*/
export const PigBatchOriginType = {
SELF_FARROWED: '自繁',
PURCHASED: '外购',
};
/**
* 病猪日志原因类型
* @enum {string}
*/
export const PigBatchSickPigReasonType = {
ILLNESS: '患病',
RECOVERY: '康复',
DEATH: '死亡',
ELIMINATE: '淘汰',
TRANSFER_IN: '转入', // 病猪转入当前批次
TRANSFER_OUT: '转出', // 病猪转出当前批次 (例如转到其他批次或出售)
OTHER: '其他',
};
/**
* 病猪治疗地点
* @enum {string}
*/
export const PigBatchSickPigTreatmentLocation = {
ON_SITE: '原地治疗',
SICK_BAY: '病猪栏治疗',
};
/**
* 猪批次状态
* @enum {string}
*/
export const PigBatchStatus = {
WEANING: '保育', // 从断奶到保育结束
GROWING: '生长', // 生长育肥阶段
FINISHING: '育肥', // 最后的育肥阶段
FOR_SALE: '待售', // 达到出栏标准
SOLD: '已出售',
ARCHIVED: '已归档', // 批次结束(如全群淘汰等)
};
/**
* 猪只迁移类型
* @enum {string}
*/
export const PigTransferType = {
INTERNAL: '群内调栏', // 同一猪群内猪栏间的调动
CROSS_BATCH: '跨群调栏', // 不同猪群间的调动
SALE: '销售', // 猪只售出
DEATH: '死亡', // 猪只死亡
CULL: '淘汰', // 猪只淘汰
PURCHASE: '新购入', // 新购入猪只
DELIVERY_ROOM_TRANSFER: '产房转入',
};
/**
* 计划内容类型
* @enum {string}
*/
export const PlanContentType = {
SUB_PLANS: '子计划', // 计划包含子计划
TASKS: '任务', // 计划包含任务
};
/**
* 计划执行类型
* @enum {string}
*/
export const PlanExecutionType = {
AUTOMATIC: '自动', // 自动执行 (包含定时和循环)
MANUAL: '手动', // 手动执行
};
/**
* 计划状态
* @enum {string}
*/
export const PlanStatus = {
DISABLED: '已禁用', // 禁用计划
ENABLED: '已启用', // 启用计划
STOPPED: '执行完毕', // 执行完毕
FAILED: '执行失败', // 执行失败
};
/**
* 计划类型
* @enum {string}
*/
export const PlanType = {
CUSTOM: '自定义任务',
SYSTEM: '系统任务',
};
/**
* 传感器类型
* @enum {string}
*/
export const SensorType = {
SIGNAL_METRICS: '信号强度',
BATTERY_LEVEL: '电池电量',
TEMPERATURE: '温度',
HUMIDITY: '湿度',
WEIGHT: '重量',
};
/**
* 库存日志来源类型
* @enum {string}
*/
export const StockLogSourceType = {
PURCHASE: '采购入库',
FEEDING: '饲喂出库',
DETERIORATE: '变质出库',
SALE: '售卖出库',
MISCELLANEOUS: '杂用领取',
MANUAL: '手动盘点',
};
/**
* 任务类型
* @enum {string}
*/
export const TaskType = {
PLAN_ANALYSIS: '计划分析', // 解析Plan的Task列表并添加到待执行队列的特殊任务
WAITING: '等待', // 等待任务
RELEASE_FEED_WEIGHT: '下料', // 下料口释放指定重量任务
FULL_COLLECTION: '全量采集', // 新增的全量采集任务
};
/**
* 通知渠道类型
* @enum {string}
*/
export const NotifierType = {
SMTP: '邮件',
WECHAT: '企业微信',
LARK: '飞书',
LOG: '日志',
};
/**
* 计划类型过滤器
* @enum {string}
*/
export const PlanTypeFilter = {
ALL: '所有任务',
CUSTOM: '自定义任务',
SYSTEM: '系统任务',
};
/**
* 日志级别, 对应后端的 zapcore.Level
* @enum {number}
*/
export const ZapcoreLevel = {
DEBUG: -1,
INFO: 0,
WARN: 1,
ERROR: 2,
DPANIC: 3,
PANIC: 4,
FATAL: 5,
INVALID: 6,
};

View File

@@ -189,6 +189,7 @@ import {
House, Monitor, Calendar, ArrowDown, Menu, Fold, Expand, Setting, Tickets, DataAnalysis, Document, Food, House, Monitor, Calendar, ArrowDown, Menu, Fold, Expand, Setting, Tickets, DataAnalysis, Document, Food,
FirstAidKit, Clock, Files, ShoppingCart, SoldOut, Warning, Switch, List, Shop, Coin, DataLine, Finished, User, ScaleToOriginal, OfficeBuilding, Management, Bell FirstAidKit, Clock, Files, ShoppingCart, SoldOut, Warning, Switch, List, Shop, Coin, DataLine, Finished, User, ScaleToOriginal, OfficeBuilding, Management, Bell
} from '@element-plus/icons-vue'; } from '@element-plus/icons-vue';
import { routeTitles } from '../routeTitles.js';
export default { export default {
name: 'MainLayout', name: 'MainLayout',
@@ -227,33 +228,7 @@ export default {
}); });
const currentPageTitle = computed(() => { const currentPageTitle = computed(() => {
const routeMap = { return routeTitles[route.path] || '猪场管理系统';
'/': '系统首页',
'/devices': '设备管理',
'/device-templates': '设备模板管理',
'/pms/farm-management': '栏舍管理',
'/pms/batch-management': '猪群管理',
'/plans': '计划管理',
'/monitor/device-command-logs': '设备命令日志',
'/monitor/feed-usage-records': '饲料使用记录',
'/monitor/medication-logs': '用药记录',
'/monitor/notifications': '通知记录',
'/monitor/pending-collections': '待采集请求',
'/monitor/pig-batch-logs': '猪批次日志',
'/monitor/pig-purchases': '猪只采购记录',
'/monitor/pig-sales': '猪只售卖记录',
'/monitor/pig-sick-logs': '病猪日志',
'/monitor/pig-transfer-logs': '猪只迁移日志',
'/monitor/plan-execution-logs': '计划执行日志',
'/monitor/raw-material-purchases': '原料采购记录',
'/monitor/raw-material-stock-logs': '原料库存日志',
'/monitor/sensor-data': '传感器数据',
'/monitor/task-execution-logs': '任务执行日志',
'/monitor/user-action-logs': '用户操作日志',
'/monitor/weighing-batches': '批次称重记录',
'/monitor/weighing-records': '单次称重记录',
};
return routeMap[route.path] || '猪场管理系统';
}); });
const logout = () => { const logout = () => {

26
src/routeTitles.js Normal file
View File

@@ -0,0 +1,26 @@
export const routeTitles = {
'/': '系统首页',
'/devices': '设备管理',
'/device-templates': '设备模板管理',
'/pms/farm-management': '栏舍管理',
'/pms/batch-management': '猪群管理',
'/plans': '计划管理',
'/monitor/device-command-logs': '设备命令日志',
'/monitor/feed-usage-records': '饲料使用记录',
'/monitor/medication-logs': '用药记录',
'/monitor/notifications': '通知记录',
'/monitor/pending-collections': '待采集请求',
'/monitor/pig-batch-logs': '猪批次日志',
'/monitor/pig-purchases': '猪只采购记录',
'/monitor/pig-sales': '猪只售卖记录',
'/monitor/pig-sick-logs': '病猪日志',
'/monitor/pig-transfer-logs': '猪只迁移日志',
'/monitor/plan-execution-logs': '计划执行日志',
'/monitor/raw-material-purchases': '原料采购记录',
'/monitor/raw-material-stock-logs': '原料库存日志',
'/monitor/sensor-data': '传感器数据',
'/monitor/task-execution-logs': '任务执行日志',
'/monitor/user-action-logs': '用户操作日志',
'/monitor/weighing-batches': '批次称重记录',
'/monitor/weighing-records': '单次称重记录',
};

View File

@@ -86,6 +86,7 @@ import deviceService from '../../services/deviceService.js';
import { DeviceApi } from '../../api/device.js'; import { DeviceApi } from '../../api/device.js';
import { DeviceTemplateApi } from '../../api/deviceTemplate.js'; import { DeviceTemplateApi } from '../../api/deviceTemplate.js';
import DeviceForm from '../../components/DeviceForm.vue'; import DeviceForm from '../../components/DeviceForm.vue';
import { DeviceCategory } from '../../enums.js';
export default { export default {
name: 'DeviceList', name: 'DeviceList',
@@ -259,7 +260,7 @@ export default {
} }
// 如果设备模板类型不是'传感器',则禁用 // 如果设备模板类型不是'传感器',则禁用
if (deviceTemplate.category !== '传感器') { if (deviceTemplate.category !== DeviceCategory.SENSOR) {
return true; return true;
} }
@@ -279,14 +280,14 @@ export default {
return; return;
} }
if (deviceTemplate.category === '传感器') { if (deviceTemplate.category === DeviceCategory.SENSOR) {
try { try {
await DeviceApi.manualControl(device.id, {}); await DeviceApi.manualControl(device.id, {});
this.$message.success('测试请求已发送,请前往传感器数据页面查看结果'); this.$message.success('测试请求已发送,请前往传感器数据页面查看结果');
} catch (error) { } catch (error) {
this.$message.error('发送测试请求失败: ' + (error.message || '未知错误')); this.$message.error('发送测试请求失败: ' + (error.message || '未知错误'));
} }
} else if (deviceTemplate.category === '执行器') { } else if (deviceTemplate.category === DeviceCategory.ACTUATOR) {
this.$message.warning('暂不支持非传感器类的测试'); this.$message.warning('暂不支持非传感器类的测试');
} }
} }

View File

@@ -79,6 +79,7 @@ import { Refresh } from '@element-plus/icons-vue';
import deviceTemplateService from '../../services/deviceTemplateService.js'; import deviceTemplateService from '../../services/deviceTemplateService.js';
import DeviceTemplateForm from '../../components/DeviceTemplateForm.vue'; import DeviceTemplateForm from '../../components/DeviceTemplateForm.vue';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { DeviceCategory } from '../../enums.js';
export default { export default {
name: 'DeviceTemplateList', name: 'DeviceTemplateList',
@@ -116,8 +117,8 @@ export default {
}, },
formatCategory(category) { formatCategory(category) {
const categoryMap = { const categoryMap = {
'actuator': '执行器', [DeviceCategory.ACTUATOR]: '执行器',
'sensor': '传感器' [DeviceCategory.SENSOR]: '传感器'
}; };
return categoryMap[category] || category || '-'; return categoryMap[category] || category || '-';
}, },

View File

@@ -11,6 +11,7 @@
import GenericMonitorList from '../../components/GenericMonitorList.vue'; import GenericMonitorList from '../../components/GenericMonitorList.vue';
import { getSensorData } from '../../api/monitor.js'; import { getSensorData } from '../../api/monitor.js';
import { formatRFC3339 } from '../../utils/format.js'; import { formatRFC3339 } from '../../utils/format.js';
import { SensorType } from '../../enums.js';
// 适配通用组件的 fetchData prop // 适配通用组件的 fetchData prop
const fetchSensorData = async (params) => { const fetchSensorData = async (params) => {
@@ -32,13 +33,7 @@ const sensorDataColumns = [
dataIndex: 'sensor_type', dataIndex: 'sensor_type',
key: 'sensor_type', key: 'sensor_type',
filterType: 'select', filterType: 'select',
filterOptions: [ filterOptions: Object.values(SensorType).map(value => ({ text: value, value: value })),
{ text: '信号强度', value: '信号强度' },
{ text: '电池电量', value: '电池电量' },
{ text: '温度', value: '温度' },
{ text: '湿度', value: '湿度' },
{ text: '重量', value: '重量' },
],
minWidth: 150, minWidth: 150,
}, },
{ {

View File

@@ -15,9 +15,9 @@
<div class="filter-and-add"> <div class="filter-and-add">
<el-select v-model="planTypeFilter" placeholder="选择计划类型" @change="loadPlans" <el-select v-model="planTypeFilter" placeholder="选择计划类型" @change="loadPlans"
style="width: 150px; margin-right: 10px;"> style="width: 150px; margin-right: 10px;">
<el-option label="所有任务" value="所有任务"></el-option> <el-option :label="PlanTypeFilter.ALL" :value="PlanTypeFilter.ALL"></el-option>
<el-option label="自定义任务" value="自定义任务"></el-option> <el-option :label="PlanTypeFilter.CUSTOM" :value="PlanTypeFilter.CUSTOM"></el-option>
<el-option label="系统任务" value="系统任务"></el-option> <el-option :label="PlanTypeFilter.SYSTEM" :value="PlanTypeFilter.SYSTEM"></el-option>
</el-select> </el-select>
<el-button type="primary" @click="addPlan">添加计划</el-button> <el-button type="primary" @click="addPlan">添加计划</el-button>
</div> </div>
@@ -55,7 +55,7 @@
<el-table-column prop="description" label="计划描述" min-width="150"/> <el-table-column prop="description" label="计划描述" min-width="150"/>
<el-table-column prop="execution_type" label="执行类型" min-width="150" sortable="custom"> <el-table-column prop="execution_type" label="执行类型" min-width="150" sortable="custom">
<template #default="scope"> <template #default="scope">
<el-tag v-if="scope.row.execution_type === '手动'">手动</el-tag> <el-tag v-if="scope.row.execution_type === PlanExecutionType.MANUAL">手动</el-tag>
<el-tag v-else-if="scope.row.execute_num === 0" type="success">自动(无限执行)</el-tag> <el-tag v-else-if="scope.row.execute_num === 0" type="success">自动(无限执行)</el-tag>
<el-tag v-else type="warning">自动({{ scope.row.execute_num }})</el-tag> <el-tag v-else type="warning">自动({{ scope.row.execute_num }})</el-tag>
</template> </template>
@@ -133,6 +133,7 @@ import apiClient from '../../api';
import PlanForm from '../../components/PlanForm.vue'; import PlanForm from '../../components/PlanForm.vue';
import PlanDetail from '../../components/PlanDetail.vue'; // 导入新组件 import PlanDetail from '../../components/PlanDetail.vue'; // 导入新组件
import cronParser from 'cron-parser'; import cronParser from 'cron-parser';
import { PlanExecutionType, PlanTypeFilter } from '../../enums.js';
export default { export default {
name: 'PlanList', name: 'PlanList',
@@ -154,14 +155,16 @@ export default {
id: null, id: null,
name: '', name: '',
description: '', description: '',
execution_type: 'automatic', execution_type: PlanExecutionType.AUTOMATIC,
execute_num: 0, execute_num: 0,
cron_expression: '' cron_expression: ''
}, },
selectedPlanIdForDetails: null, // 当前要查看详情的计划ID selectedPlanIdForDetails: null, // 当前要查看详情的计划ID
startingPlanId: null, startingPlanId: null,
stoppingPlanId: null, stoppingPlanId: null,
planTypeFilter: '自定义任务', // 新增:计划类型筛选,默认自定义任务 planTypeFilter: PlanTypeFilter.CUSTOM, // 新增:计划类型筛选,默认自定义任务
PlanExecutionType, // 导出枚举以便在模板中使用
PlanTypeFilter, // 导出枚举以便在模板中使用
}; };
}, },
async mounted() { async mounted() {
@@ -251,7 +254,7 @@ export default {
id: null, id: null,
name: '', name: '',
description: '', description: '',
execution_type: 'automatic', execution_type: PlanExecutionType.AUTOMATIC,
execute_num: 0, execute_num: 0,
cron_expression: '' cron_expression: ''
}; };