Merge remote-tracking branch 'origin/master'
已修改34个文件
已删除8个文件
已添加32个文件
| | |
| | | |
| | | // 查询ArcSetting列表 |
| | | export const getPage = (params: ArcDataPageReqVO) => { |
| | | return request.get({ url: '/data/da/arc/dataPage', params }) |
| | | return request.get({ url: '/data/arc/data/page', params }) |
| | | } |
| | |
| | | type: string, |
| | | point: string, |
| | | calculate: string, |
| | | isEnable: string |
| | | sort: number, |
| | | isEnable: number |
| | | } |
| | | |
| | | export interface ArcSettingPageReqVO extends PageParam { |
| | |
| | | |
| | | // 查询ArcSetting列表 |
| | | export const getArcSettingPage = (params: ArcSettingPageReqVO) => { |
| | | return request.get({ url: '/data/da/arc/page', params }) |
| | | return request.get({ url: '/data/arc/setting/page', params }) |
| | | } |
| | | |
| | | // 查询ArcSetting详情 |
| | | export const getArcSetting = (id: number) => { |
| | | return request.get({ url: `/data/da/arc/info/${id}`}) |
| | | return request.get({ url: `/data/arc/setting/info/${id}`}) |
| | | } |
| | | |
| | | // 新增ArcSetting |
| | | export const createArcSetting = (data: ArcSettingVO) => { |
| | | return request.post({ url: '/data/da/arc/create', data }) |
| | | return request.post({ url: '/data/arc/setting/create', data }) |
| | | } |
| | | |
| | | // 修改ArcSetting |
| | | export const updateArcSetting = (data: ArcSettingVO) => { |
| | | return request.put({ url: '/data/da/arc/update', data }) |
| | | return request.put({ url: '/data/arc/setting/update', data }) |
| | | } |
| | | |
| | | // 删除ArcSetting |
| | | export const deleteArcSetting = (id: number) => { |
| | | return request.delete({ url: '/data/da/arc/delete?id=' + id }) |
| | | return request.delete({ url: '/data/arc/setting/delete?id=' + id }) |
| | | } |
| | |
| | | end?: Date, |
| | | } |
| | | |
| | | export interface ApiPointPageReqVO extends PageParam { |
| | | pointNo?: string |
| | | } |
| | | |
| | | // 查询chart列表 |
| | | export const getPointDaChart = (data: DaPointChartReqVO) => { |
| | | return request.post({ url: '/data/api/query-points/chart', data }) |
| | | } |
| | | |
| | | // 查询多个测点当前值 |
| | | export const getPointsRealValue = (data: []) => { |
| | | return request.post({ url: '/data/api/query-points/real-value', data }) |
| | | } |
| | | |
| | | // 查询计算点当前值 |
| | | export const getMathPointCurrentValue = (data: ApiPointPageReqVO) => { |
| | | return request.post({ url: '/data/api/query-math-point/current-value', data }) |
| | | } |
| | | |
| | | //导出DaPointValue |
| | | export const exportDaPointValue = (params) => { |
| | | return request.download({ url: '/data/da/point/exportValue', params }) |
| | |
| | | itemCategory: string |
| | | } |
| | | |
| | | export type IndValueParam = { |
| | | itemNo: string |
| | | startDate: string |
| | | endTime: string |
| | | } |
| | | |
| | | // 查询列表 |
| | | export const getItemPage = (params: PageParam) => { |
| | |
| | | callback(new Error('请输入数字!')); |
| | | } |
| | | } |
| | | |
| | | export const getItemCurrentData = (itemNo: string) => { |
| | | return request.get({ url: '/data/api/query-ind/default-value?itemNo=' + itemNo}) |
| | | } |
| | | |
| | | export const getItemValueData = (params: IndValueParam) => { |
| | | return request.get({ url: '/data/ind-item-value/getList', params}) |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | // 磁盘监控日志 VO |
| | | export interface MonitorDiskVO { |
| | | id: number // 访问ID |
| | | hostName: string // 主机名称 |
| | | hostIp: string // 服务器ip |
| | | disk: string // 盘符 |
| | | diskName: string // 磁盘名 |
| | | spaceTotal: number // 总空间 |
| | | spaceUsed: number // 已用空间 |
| | | spaceUsable: number // 可用空间 |
| | | spaceRatio: number // 空间使用比例 |
| | | } |
| | | |
| | | // 磁盘监控日志 API |
| | | export const MonitorDiskApi = { |
| | | // 查询磁盘监控日志分页 |
| | | getMonitorDiskPage: async (params: any) => { |
| | | return await request.get({ url: `/infra/monitor-disk/page`, params }) |
| | | }, |
| | | |
| | | // 查询磁盘监控日志列表 |
| | | getMonitorDiskList: async (params: any) => { |
| | | return await request.get({ url: `/infra/monitor-disk/getMonitorDiskList`, params }) |
| | | }, |
| | | |
| | | // 查询磁盘监控日志信息 |
| | | getMonitorDiskInfo: async (params: any) => { |
| | | return await request.get({ url: `/infra/monitor-disk/getMonitorDiskInfo`, params }) |
| | | }, |
| | | |
| | | // 查询磁盘监控日志详情 |
| | | getMonitorDisk: async (id: number) => { |
| | | return await request.get({ url: `/infra/monitor-disk/get?id=` + id }) |
| | | }, |
| | | |
| | | // 新增磁盘监控日志 |
| | | createMonitorDisk: async (data: MonitorDiskVO) => { |
| | | return await request.post({ url: `/infra/monitor-disk/create`, data }) |
| | | }, |
| | | |
| | | // 修改磁盘监控日志 |
| | | updateMonitorDisk: async (data: MonitorDiskVO) => { |
| | | return await request.put({ url: `/infra/monitor-disk/update`, data }) |
| | | }, |
| | | |
| | | // 删除磁盘监控日志 |
| | | deleteMonitorDisk: async (id: number) => { |
| | | return await request.delete({ url: `/infra/monitor-disk/delete?id=` + id }) |
| | | }, |
| | | |
| | | // 导出磁盘监控日志 Excel |
| | | exportMonitorDisk: async (params) => { |
| | | return await request.download({ url: `/infra/monitor-disk/export-excel`, params }) |
| | | }, |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | // 内存监控日志 VO |
| | | export interface MonitorMemVO { |
| | | id: number // 访问ID |
| | | hostName: string // 主机名称 |
| | | hostIp: string // 服务器ip |
| | | serverName: string // 服务名 |
| | | physicalTotal: number // 总物理内存 |
| | | physicalUsed: number // 已用物理内存 |
| | | physicalFree: number // 剩余物理内存 |
| | | physicalUsage: number // 物理内存使用率 |
| | | runtimeTotal: number // jvm运行总内存 |
| | | runtimeMax: number // jvm最大内存 |
| | | runtimeUsed: number // jvm已用内存 |
| | | runtimeFree: number // jvm空闲内存 |
| | | runtimeUsage: number // jvm内存使用率 |
| | | } |
| | | |
| | | // 内存监控日志 API |
| | | export const MonitorMemApi = { |
| | | // 查询内存监控日志分页 |
| | | getMonitorMemPage: async (params: any) => { |
| | | return await request.get({ url: `/infra/monitor-mem/page`, params }) |
| | | }, |
| | | |
| | | // 查询统计数据列表 |
| | | getMonitorMemList: async (params: any) => { |
| | | return await request.get({ url: `/infra/monitor-mem/getMonitorMemList`, params }) |
| | | }, |
| | | |
| | | // 查询内存监控日志详情 |
| | | getMonitorMem: async (id: number) => { |
| | | return await request.get({ url: `/infra/monitor-mem/get?id=` + id }) |
| | | }, |
| | | |
| | | // 新增内存监控日志 |
| | | createMonitorMem: async (data: MonitorMemVO) => { |
| | | return await request.post({ url: `/infra/monitor-mem/create`, data }) |
| | | }, |
| | | |
| | | // 修改内存监控日志 |
| | | updateMonitorMem: async (data: MonitorMemVO) => { |
| | | return await request.put({ url: `/infra/monitor-mem/update`, data }) |
| | | }, |
| | | |
| | | // 删除内存监控日志 |
| | | deleteMonitorMem: async (id: number) => { |
| | | return await request.delete({ url: `/infra/monitor-mem/delete?id=` + id }) |
| | | }, |
| | | |
| | | // 导出内存监控日志 Excel |
| | | exportMonitorMem: async (params) => { |
| | | return await request.download({ url: `/infra/monitor-mem/export-excel`, params }) |
| | | }, |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export const getPage = async (params: PageParam) => { |
| | | return await request.get({ url: '/model/matlab/model/page', params }) |
| | | } |
| | | |
| | | export const get = async (id: number) => { |
| | | return await request.get({ url: '/model/matlab/model/' + id }) |
| | | } |
| | | |
| | | export const create = async (data) => { |
| | | return await request.post({ url: '/model/matlab/model', data: data }) |
| | | } |
| | | |
| | | export const update = async (params) => { |
| | | return await request.put({ url: '/model/matlab/model', data: params }) |
| | | } |
| | | |
| | | export const deleteModel = async (id: number) => { |
| | | return await request.delete({ url: '/model/matlab/model?id=' + id }) |
| | | } |
| | | |
| | | export const list = (params) => { |
| | | return request.get({ url: '/model/matlab/model/list', params}) |
| | | } |
| | | |
| | | export const test = (data) => { |
| | | return request.post({ url: '/model/matlab/model/test', data}) |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export const getPage = async (params) => { |
| | | return await request.get({ url: '/model/matlab/project/page', params }) |
| | | } |
| | | |
| | | export const getProject = async (id: number) => { |
| | | return await request.get({ url: '/model/matlab/project/' + id }) |
| | | } |
| | | |
| | | export const createProject = async (data) => { |
| | | return await request.post({ url: '/model/matlab/project', data: data }) |
| | | } |
| | | |
| | | export const updateProject = async (params) => { |
| | | return await request.put({ url: '/model/matlab/project', data: params }) |
| | | } |
| | | |
| | | export const deleteProject = async (id: number) => { |
| | | return await request.delete({ url: '/model/matlab/project?id=' + id }) |
| | | } |
| | | |
| | | export const list = () => { |
| | | return request.get({ url: '/model/packageProject/project/list'}) |
| | | } |
| | | |
| | | export const getProjectModel = async (params) => { |
| | | return await request.get({ url: '/model/matlab/project/getProjectModel', params }) |
| | | } |
| | | |
| | | export const publish = async (data) => { |
| | | return await request.post({ url: '/model/matlab/project/publish', data }) |
| | | } |
| | |
| | | return request.post({ url: '/model/mpk/api/test', data: params }) |
| | | } |
| | | |
| | | export const saveModel = (data) => { |
| | | return request.downloadByPost({ url: '/model/mpk/api/saveModel', data }) |
| | | } |
| | | |
| | | export const list = (params) => { |
| | | return request.get({ url: '/model/mpk/file/list', params}) |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export interface MmItemAccuracyHisVO { |
| | | id: string |
| | | rateId: string, |
| | | inDeviation: number, |
| | | inAccuracyRate: number, |
| | | outDeviation: number, |
| | | outAccuracyRate: number, |
| | | } |
| | | |
| | | export interface MmItemAccuracyHisPageReqVO extends PageParam { |
| | | rateId?: string |
| | | } |
| | | |
| | | // 查询MmItemAccuracyHis列表 |
| | | export const getMmItemAccuracyHisPage = (params: MmItemAccuracyHisPageReqVO) => { |
| | | return request.get({ url: '/model/item/accuracy-his/page', params }) |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export interface MmItemAccuracyRateVO { |
| | | id: string |
| | | itemId: string, |
| | | outId: string, |
| | | sampleLength: number, |
| | | valueType: number, |
| | | beginTime: Date, |
| | | inDeviation: number, |
| | | inAccuracyRate: number, |
| | | outDeviation: number, |
| | | outAccuracyRate: number, |
| | | isEnable: number, |
| | | } |
| | | |
| | | export interface MmItemAccuracyRatePageReqVO extends PageParam { |
| | | itemId?: string |
| | | } |
| | | |
| | | // 查询MmItemAccuracyRate列表 |
| | | export const getMmItemAccuracyRatePage = (params: MmItemAccuracyRatePageReqVO) => { |
| | | return request.get({ url: '/model/item/accuracy-rate/page', params }) |
| | | } |
| | | |
| | | // 查询MmItemAccuracyRate详情 |
| | | export const getMmItemAccuracyRate = (id: number) => { |
| | | return request.get({ url: `/model/item/accuracy-rate/get/${id}`}) |
| | | } |
| | | |
| | | // 新增MmItemAccuracyRate |
| | | export const createMmItemAccuracyRate = (data: MmItemAccuracyRateVO) => { |
| | | return request.post({ url: '/model/item/accuracy-rate/create', data }) |
| | | } |
| | | |
| | | // 修改MmItemAccuracyRate |
| | | export const updateMmItemAccuracyRate = (data: MmItemAccuracyRateVO) => { |
| | | return request.put({ url: '/model/item/accuracy-rate/update', data }) |
| | | } |
| | | |
| | | // 删除MmItemAccuracyRate |
| | | export const deleteMmItemAccuracyRate = (id: number) => { |
| | | return request.delete({ url: '/model/item/accuracy-rate/delete?id=' + id }) |
| | | } |
| | | |
| | | |
| | | // 查询getItemAccuracyRateList详情 |
| | | export const getItemAccuracyRateList = () => { |
| | | return request.get({ url: `/model/item/accuracy-rate/list`}) |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export interface MmPredictAlarmConfigVO { |
| | | id: string |
| | | title: string, |
| | | alarmObj: string, |
| | | itemId: string, |
| | | outId: string, |
| | | compLength: number, |
| | | upperLimit: number, |
| | | lowerLimit: number, |
| | | culUpper: number, |
| | | culLower: number, |
| | | unit: string, |
| | | coefficient: number, |
| | | scheduleId: string, |
| | | isEnable: number, |
| | | creator: string, |
| | | createTime: Date, |
| | | updater: string, |
| | | updateTime: Date, |
| | | } |
| | | |
| | | export interface MmPredictAlarmConfigPageReqVO extends PageParam { |
| | | title?: string |
| | | } |
| | | |
| | | // 查询MmPredictAlarmConfig列表 |
| | | export const getMmPredictAlarmConfigPage = (params: MmPredictAlarmConfigPageReqVO) => { |
| | | return request.get({ url: '/model/pre/alarm-config/page', params }) |
| | | } |
| | | |
| | | // 查询MmPredictAlarmConfig详情 |
| | | export const getMmPredictAlarmConfig = (id: number) => { |
| | | return request.get({ url: `/model/pre/alarm-config/get/${id}`}) |
| | | } |
| | | |
| | | // 新增MmPredictAlarmConfig |
| | | export const createMmPredictAlarmConfig = (data: MmPredictAlarmConfigVO) => { |
| | | return request.post({ url: '/model/pre/alarm-config/create', data }) |
| | | } |
| | | |
| | | // 修改MmPredictAlarmConfig |
| | | export const updateMmPredictAlarmConfig = (data: MmPredictAlarmConfigVO) => { |
| | | return request.put({ url: '/model/pre/alarm-config/update', data }) |
| | | } |
| | | |
| | | // 删除MmPredictAlarmConfig |
| | | export const deleteMmPredictAlarmConfig = (id: number) => { |
| | | return request.delete({ url: '/model/pre/alarm-config/delete?id=' + id }) |
| | | } |
| | | |
| | | |
| | | // 查询getPredictAlarmConfigList详情 |
| | | export const getPredictAlarmConfigList = () => { |
| | | return request.get({ url: `/model/pre/alarm-config/list`}) |
| | | } |
对比新文件 |
| | |
| | | import request from '@/config/axios' |
| | | |
| | | export interface MmPredictAlarmMessageVO { |
| | | id: string |
| | | configId: string, |
| | | title: string, |
| | | content: string, |
| | | alarmObj: string, |
| | | pointId: string, |
| | | itemId: string, |
| | | outId: string, |
| | | currentValue: number, |
| | | outTime: Date, |
| | | outValue: number, |
| | | alarmType: string, |
| | | alarmTime: Date, |
| | | createTime: Date, |
| | | } |
| | | |
| | | export interface MmPredictAlarmMessagePageReqVO extends PageParam { |
| | | title?: string |
| | | } |
| | | |
| | | // 查询MmPredictAlarmMessage列表 |
| | | export const getMmPredictAlarmMessagePage = (params: MmPredictAlarmMessagePageReqVO) => { |
| | | return request.get({ url: '/model/pre/alarm-message/page', params }) |
| | | } |
| | | |
| | |
| | | predictphase: string, |
| | | workchecked: number, |
| | | unittransfactor: string, |
| | | saveindex: string |
| | | saveindex: string, |
| | | iscumulant: number, |
| | | cumuldivisor: number, |
| | | cumulpoint: string |
| | | }, |
| | | dmModuleItem: { |
| | | id: string, |
| | |
| | | return request.get({ url: `/model/pre/item/list`, params}) |
| | | } |
| | | |
| | | // 查询MmItemOutput列表 |
| | | export const getMmItemOutputList = (params) => { |
| | | return request.get({ url: `/model/pre/item-output/list/all`, params}) |
| | | } |
| | | |
| | | export const updateModel = (data: any) => { |
| | | return request.upload({ url: '/model/pre/item/upload-model', data }) |
| | | } |
| | |
| | | import * as PlanItemApi from '@/api/data/plan/item' |
| | | import {CommonEnabled} from "@/utils/constants"; |
| | | import {getItemList, ItemVO} from "@/api/data/plan/item"; |
| | | import * as ItemApi from '@/api/data/ind/item/item' |
| | | import {getPointSimpleList} from "@/api/data/da/point"; |
| | | |
| | | export interface ScheduleModelVO { |
| | | id: string |
| | |
| | | export const getModelParamList = async (id) => { |
| | | |
| | | const dataPointList = ref([] as DataPointApi.DaPointVO) |
| | | dataPointList.value = await DataPointApi.getPointList({}) |
| | | dataPointList.value = await DataPointApi.getPointSimpleList({}) |
| | | const pointList = [] |
| | | if (dataPointList.value) { |
| | | dataPointList.value.forEach(item => { |
| | |
| | | }) |
| | | } |
| | | |
| | | // 指标数据 |
| | | const indItemList = await ItemApi.getItemList({}) |
| | | const indList = [] |
| | | if (indItemList) { |
| | | indItemList.forEach(item => { |
| | | indList.push( |
| | | { |
| | | id: item.id, |
| | | name: item.itemName |
| | | } |
| | | ) |
| | | }) |
| | | } |
| | | |
| | | return { |
| | | 'DATAPOINT':pointList, |
| | | 'NormalItem': normalItemList, |
| | | 'MergeItem': mergeItemList, |
| | | 'PLAN': planList, |
| | | 'IND': indList, |
| | | 'IND_ASCII': indList, |
| | | } |
| | | } |
对比新文件 |
| | |
| | | <template> |
| | | <svg :width="size" :height="size" viewBox="0 0 100 100"> |
| | | <!-- 背景圆 --> |
| | | <circle cx="50" cy="50" r="50" fill="#eee"/> |
| | | <!-- 使用率扇形 --> |
| | | <path :d="arcPath" fill="#1C134B"/> |
| | | </svg> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed } from 'vue'; |
| | | |
| | | const props = defineProps({ |
| | | used: { type: Number, required: true }, |
| | | total: { type: Number, required: true }, |
| | | size: { type: Number, default: 150 } |
| | | }); |
| | | |
| | | const percentage = computed(() => { |
| | | if (props.total === 0) return 0; |
| | | return (props.used / props.total) * 100; |
| | | }); |
| | | |
| | | const arcPath = computed(() => { |
| | | if (percentage.value >= 100) return ''; |
| | | |
| | | const angle = (percentage.value * 360) / 100; |
| | | const radians = (angle - 90) * Math.PI / 180; |
| | | const x = 50 + 50 * Math.cos(radians); |
| | | const y = 50 + 50 * Math.sin(radians); |
| | | const largeArc = angle > 180 ? 1 : 0; |
| | | |
| | | return `M 50 50 L 50 0 A 50 50 0 ${largeArc} 1 ${x} ${y} L 50 50 Z`; |
| | | }); |
| | | </script> |
| | |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | path: '/matlab', |
| | | component: Layout, |
| | | name: 'matlab', |
| | | meta: { |
| | | hidden: true |
| | | }, |
| | | children: [ |
| | | { |
| | | path: 'model/form/:id?', |
| | | component: () => import('@/views/model/matlab/model/MatlabModelForm.vue'), |
| | | name: 'MatlabModelForm', |
| | | meta: { |
| | | title: 'Matlab模型表单', |
| | | noCache: true, |
| | | hidden: true, |
| | | canTo: true, |
| | | icon: '', |
| | | activeMenu: '/matlab/model' |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | ] |
| | | |
| | | export default remainingRouter |
对比新文件 |
| | |
| | | import { store } from '@/store' |
| | | import { defineStore } from 'pinia' |
| | | import { KeFuConversationApi, KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation' |
| | | import { KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message' |
| | | import { isEmpty } from '@/utils/is' |
| | | |
| | | interface MallKefuInfoVO { |
| | | conversationList: KeFuConversationRespVO[] // 会话列表 |
| | | conversationMessageList: Map<number, KeFuMessageRespVO[]> // 会话消息 |
| | | } |
| | | |
| | | export const useMallKefuStore = defineStore('mall-kefu', { |
| | | state: (): MallKefuInfoVO => ({ |
| | | conversationList: [], |
| | | conversationMessageList: new Map<number, KeFuMessageRespVO[]>() // key 会话,value 会话消息列表 |
| | | }), |
| | | getters: { |
| | | getConversationList(): KeFuConversationRespVO[] { |
| | | return this.conversationList |
| | | }, |
| | | getConversationMessageList(): (conversationId: number) => KeFuMessageRespVO[] | undefined { |
| | | return (conversationId: number) => this.conversationMessageList.get(conversationId) |
| | | } |
| | | }, |
| | | actions: { |
| | | // ======================= 会话消息相关 ======================= |
| | | /** 缓存历史消息 */ |
| | | saveMessageList(conversationId: number, messageList: KeFuMessageRespVO[]) { |
| | | this.conversationMessageList.set(conversationId, messageList) |
| | | }, |
| | | |
| | | // ======================= 会话相关 ======================= |
| | | /** 加载会话缓存列表 */ |
| | | async setConversationList() { |
| | | this.conversationList = await KeFuConversationApi.getConversationList() |
| | | this.conversationSort() |
| | | }, |
| | | /** 更新会话缓存已读 */ |
| | | async updateConversationStatus(conversationId: number) { |
| | | if (isEmpty(this.conversationList)) { |
| | | return |
| | | } |
| | | const conversation = this.conversationList.find((item) => item.id === conversationId) |
| | | conversation && (conversation.adminUnreadMessageCount = 0) |
| | | }, |
| | | /** 更新会话缓存 */ |
| | | async updateConversation(conversationId: number) { |
| | | if (isEmpty(this.conversationList)) { |
| | | return |
| | | } |
| | | |
| | | const conversation = await KeFuConversationApi.getConversation(conversationId) |
| | | this.deleteConversation(conversationId) |
| | | conversation && this.conversationList.push(conversation) |
| | | this.conversationSort() |
| | | }, |
| | | /** 删除会话缓存 */ |
| | | deleteConversation(conversationId: number) { |
| | | const index = this.conversationList.findIndex((item) => item.id === conversationId) |
| | | // 存在则删除 |
| | | if (index > -1) { |
| | | this.conversationList.splice(index, 1) |
| | | } |
| | | }, |
| | | conversationSort() { |
| | | // 按置顶属性和最后消息时间排序 |
| | | this.conversationList.sort((a, b) => { |
| | | // 按照置顶排序,置顶的会在前面 |
| | | if (a.adminPinned !== b.adminPinned) { |
| | | return a.adminPinned ? -1 : 1 |
| | | } |
| | | // 按照最后消息时间排序,最近的会在前面 |
| | | return (b.lastMessageTime as unknown as number) - (a.lastMessageTime as unknown as number) |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | export const useMallKefuStoreWithOut = () => { |
| | | return useMallKefuStore(store) |
| | | } |
| | |
| | | PRED_GRANULARITY = 'pred_granularity', |
| | | ITEM_RUN_STATUS = 'item_run_status', |
| | | RESULT_TYPE = 'result_type', |
| | | MATLAB_PLATFORM= 'matlab_platform', |
| | | MATLAB_VERSION= 'matlab_version', |
| | | // ========== DATA - 数据平台模块 ========== |
| | | DATA_FIELD_TYPE = 'data_field_type', |
| | | TAG_DATA_TYPE = 'tag_data_type', |
| | |
| | | MODEL_RESULT_TYPE = 'model_result_type', |
| | | DATA_QUALITY = 'data_quality', |
| | | ARC_TYPE = 'arc_type', |
| | | ARC_CALCULATE_TYPE = 'arc_calculate_type' |
| | | ARC_CALCULATE_TYPE = 'arc_calculate_type', |
| | | SOLIDIFY_FLAG = 'ind_solidify_flag' |
| | | } |
| | |
| | | a.download = 'image.png' |
| | | a.click() |
| | | } |
| | | } |
| | | }, |
| | | downloadFile: (data: Blob, fileName: string) => { |
| | | download0(data, fileName, 'application/octet-stream') |
| | | }, |
| | | } |
| | | |
| | | export default download |
| | |
| | | <template> |
| | | <el-drawer |
| | | v-model="drawer" |
| | | size="60%" |
| | | size="50%" |
| | | title="归档数据" |
| | | :direction="direction" |
| | | :before-close="handleClose" |
| | |
| | | format="YYYY-MM-DD HH:mm:00" |
| | | value-format="YYYY-MM-DD HH:mm:00" |
| | | type="datetime" |
| | | :clearable="false" |
| | | :clearable="true" |
| | | placeholder="选择日期时间"/> |
| | | </el-form-item> |
| | | <el-form-item label="结束时间"> |
| | |
| | | format="YYYY-MM-DD HH:mm:00" |
| | | value-format="YYYY-MM-DD HH:mm:00" |
| | | type="datetime" |
| | | :clearable="false" |
| | | :clearable="true" |
| | | placeholder="选择日期时间"/> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column |
| | | prop="value" |
| | | prop="arcValue" |
| | | label="数据值" |
| | | header-align="center" |
| | | align="center" |
| | |
| | | pageSize: 10, |
| | | arcId:undefined, |
| | | startTime: undefined, |
| | | endTime: getYMDHM0(new Date()), |
| | | endTime: undefined |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | const exportLoading = ref(false) // 导出的加载中 |
| | |
| | | queryParams.pageSize = 10 |
| | | queryParams.arcId = '' |
| | | queryParams.startTime = '' |
| | | queryParams.endTime = getYMDHM0(new Date()) |
| | | queryParams.endTime = '' |
| | | } |
| | | |
| | | const handleClose = (done: () => void) => { |
| | |
| | | :rules="formRules" |
| | | label-width="120px" |
| | | > |
| | | <el-form-item label="名称" prop="name"> |
| | | <el-input v-model="formData.name" placeholder="请输入归档名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="归档周期" prop="type"> |
| | | <el-select |
| | | v-model="formData.type" |
| | | clearable |
| | | placeholder="请选择归档周期" |
| | | > |
| | | <el-option |
| | | v-for="dict in getDictOptions(DICT_TYPE.ARC_TYPE)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="归档点位" prop="point"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="编码" prop="code"> |
| | | <el-input v-model="formData.code" placeholder="请输入编码" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="名称" prop="name"> |
| | | <el-input v-model="formData.name" placeholder="请输入名称" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="归档周期" prop="type"> |
| | | <el-select |
| | | v-model="formData.type" |
| | | clearable |
| | | placeholder="请选择归档周期" |
| | | > |
| | | <el-option |
| | | v-for="dict in getDictOptions(DICT_TYPE.ARC_TYPE)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="计算方法" prop="calculate"> |
| | | <el-select |
| | | v-model="formData.calculate" |
| | | clearable |
| | | placeholder="请选择计算方法" |
| | | > |
| | | <el-option |
| | | v-for="dict in getDictOptions(DICT_TYPE.ARC_CALCULATE_TYPE)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="归档点位" prop="point"> |
| | | <el-select |
| | | v-model="formData.point" |
| | | filterable |
| | |
| | | :label="item.pointName" |
| | | :value="item.pointNo"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="计算方法" prop="calculate"> |
| | | <el-select |
| | | v-model="formData.calculate" |
| | | clearable |
| | | placeholder="请选择计算方法" |
| | | > |
| | | <el-option |
| | | v-for="dict in getDictOptions(DICT_TYPE.ARC_CALCULATE_TYPE)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="是否启用" prop="isEnable"> |
| | | <el-select |
| | | v-model="formData.isEnable" |
| | | clearable |
| | | placeholder="请选择是否启用" |
| | | > |
| | | <el-option |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.COM_IS_INT)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否启用" prop="isEnable"> |
| | | <el-select |
| | | v-model="formData.isEnable" |
| | | clearable |
| | | placeholder="请选择是否启用" |
| | | > |
| | | <el-option |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.COM_IS_INT)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
| | |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | | code: undefined, |
| | | name: undefined, |
| | | type: undefined, |
| | | point: undefined, |
| | | calculate: undefined, |
| | | sort: 1, |
| | | isEnable: 1 |
| | | }) |
| | | const formRules = reactive({ |
| | | code: [{ required: true, message: '编码不能为空', trigger: 'blur' }], |
| | | name: [{ required: true, message: '名称不能为空', trigger: 'blur' }], |
| | | type: [{ required: true, message: '归档周期不能为空', trigger: 'blur' }], |
| | | point: [{ required: true, message: '归档点位不能为空', trigger: 'blur' }], |
| | |
| | | type: undefined, |
| | | point: undefined, |
| | | calculate: undefined, |
| | | sort: 1, |
| | | isEnable: 1 |
| | | } |
| | | formRef.value?.resetFields() |
| | |
| | | <template> |
| | | <!-- 搜索 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="名称" prop="name"> |
| | | <el-input |
| | | v-model="queryParams.name" |
| | | placeholder="请输入名称" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px"/> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="openForm('create')" |
| | | > |
| | | <Icon icon="ep:plus" class="mr-5px"/> |
| | | 新增 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="名称" align="center" prop="name"/> |
| | | <el-table-column label="归档周期" align="center" prop="type"/> |
| | | <el-table-column label="归档点位" align="center" prop="point"/> |
| | | <el-table-column label="计算方法" align="center" prop="calculate"/> |
| | | <el-table-column label="是否启用" align="center" prop="isEnable"/> |
| | | <el-table-column label="操作" align="center" min-width="110" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openArcData(scope.row.id)" |
| | | > |
| | | 历史值 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | <!-- 搜索 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="名称" prop="name"> |
| | | <el-input |
| | | v-model="queryParams.name" |
| | | placeholder="请输入名称" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-240px" |
| | | /> |
| | | </ContentWrap> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px"/> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="openForm('create')" |
| | | v-hasPermi="['data:arc:create']" |
| | | > |
| | | <Icon icon="ep:plus" class="mr-5px"/> |
| | | 新增 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <ArcSettingForm ref="formRef" @success="getList"/> |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="编码" align="center" prop="code"/> |
| | | <el-table-column label="名称" align="center" prop="name"/> |
| | | <el-table-column label="归档周期" align="center" prop="type"/> |
| | | <el-table-column label="归档点位" align="center" prop="point"/> |
| | | <el-table-column label="计算方法" align="center" prop="calculate"/> |
| | | <el-table-column label="是否启用" align="center" prop="isEnable"> |
| | | <template #default="scope"> |
| | | <el-tag v-if="scope.row.isEnable === 1" size="small">是</el-tag> |
| | | <el-tag v-else size="small" type="danger">否</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" align="center" min-width="110" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | v-hasPermi="['data:arc:update']" |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openArcData(scope.row.id)" |
| | | > |
| | | 历史值 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | v-hasPermi="['data:arc:delete']" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <!-- 历史值弹窗 --> |
| | | <ArcData ref="dataRef"/> |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <ArcSettingForm ref="formRef" @success="getList"/> |
| | | |
| | | <!-- 历史值弹窗 --> |
| | | <ArcData ref="dataRef"/> |
| | | |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as ArcSetting from '@/api/data/arc/index' |
| | | import ArcSettingForm from './ArcSettingForm.vue' |
| | | import ArcData from './ArcData.vue' |
| | | import * as ArcSetting from '@/api/data/arc/index' |
| | | import ArcSettingForm from './ArcSettingForm.vue' |
| | | import ArcData from './ArcData.vue' |
| | | |
| | | defineOptions({name: 'DataArc'}) |
| | | defineOptions({name: 'DataArc'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 列表的数据 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | name: undefined, |
| | | type: undefined |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | const exportLoading = ref(false) // 导出的加载中 |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 列表的数据 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | name: undefined, |
| | | type: undefined |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | const exportLoading = ref(false) // 导出的加载中 |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const page = await ArcSetting.getArcSettingPage(queryParams) |
| | | list.value = page.list |
| | | total.value = page.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const page = await ArcSetting.getArcSettingPage(queryParams) |
| | | list.value = page.list |
| | | total.value = page.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNo = 1 |
| | | getList() |
| | | } |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNo = 1 |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number) => { |
| | | formRef.value.open(type, id) |
| | | } |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number) => { |
| | | formRef.value.open(type, id) |
| | | } |
| | | |
| | | /** 历史操作 */ |
| | | const dataRef = ref() |
| | | const openArcData = (id?: string) => { |
| | | dataRef.value.open(id) |
| | | } |
| | | /** 历史操作 */ |
| | | const dataRef = ref() |
| | | const openArcData = (id?: string) => { |
| | | dataRef.value.open(id) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await ArcSetting.deleteArcSetting(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await ArcSetting.deleteArcSetting(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | </script> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="查询语句" prop="querySql"> |
| | | <el-input v-model="formData.querySql" placeholder="请输入内容" type="textarea" maxlength="200" |
| | | <el-input v-model="formData.querySql" placeholder="请输入内容" type="textarea" maxlength="500" |
| | | :rows="6" |
| | | @input="checkSensitiveWords" |
| | | show-word-limit spellcheck="false"/> |
| | | </el-form-item> |
| | | <el-form-item v-if="showError"> |
| | | <p>输入中包含以下敏感词:<span style="color: red">{{sensitiveMessage}}</span></p> |
| | | </el-form-item> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" maxlength="100" |
| | |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button :disabled="disableSubmit" type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
| | | import * as DataSetApi from '@/api/data/ind/data/data.set' |
| | | import { CommonStatusEnum } from '@/utils/constants' |
| | | import * as DataSourceConfigApi from "@/api/infra/dataSourceConfig"; |
| | | import * as DataSetApi from '@/api/data/ind/data/data.set' |
| | | import * as DataSourceConfigApi from "@/api/infra/dataSourceConfig"; |
| | | |
| | | defineOptions({ name: 'IndDataSetForm' }) |
| | | defineOptions({ name: 'IndDataSetForm' }) |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const showError = ref(false) |
| | | const foundSensitiveWords = ref() |
| | | const sensitiveMessage = ref('') |
| | | const sensitiveWords = [';', 'master', 'truncate', 'insert', 'delete', 'update', 'declare', 'alter', 'drop'] |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formLoading = ref(false) // 表单的加载中:修改时的数据加载 |
| | | const disableSubmit = ref(false) // 禁止提交 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** |
| | | * 验证敏感词 |
| | | */ |
| | | const checkSensitiveWords = () => { |
| | | showError.value = false; |
| | | const regex = new RegExp(sensitiveWords.map(word => `${word}`).join('|'), 'gi'); |
| | | let matches = formData.value.querySql.match(regex); |
| | | if (matches) { |
| | | showError.value = true; |
| | | foundSensitiveWords.value = Array.from(new Set(matches)); |
| | | disableSubmit.value = true |
| | | sensitiveMessage.value = foundSensitiveWords.value.join('、') |
| | | } else { |
| | | foundSensitiveWords.value = undefined |
| | | disableSubmit.value = false |
| | | } |
| | | } |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | |
| | | if (!valid) return |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | disableSubmit.value = true |
| | | try { |
| | | const data = formData.value as DataSetApi.DataSetVO |
| | | if (formType.value === 'create') { |
| | |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | disableSubmit.value = false |
| | | } |
| | | } |
| | | |
| | |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标分类" prop="itemCategory"> |
| | | <el-select v-model="formData.itemCategory" clearable placeholder="请选择指标分类"> |
| | | <el-option |
| | | v-for="item in dataCategoryList" |
| | | :key="item.id" |
| | | :label="item.label" |
| | | :value="item.id + ''" |
| | | /> |
| | | </el-select> |
| | | <el-tree-select |
| | | v-model="formData.itemCategory" |
| | | :data="dataCategoryList" |
| | | :default-expanded-keys="[0]" |
| | | :props="defaultProps" |
| | | check-strictly |
| | | node-key="id" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="时间粒度" prop="timeGranularity"> |
| | | <el-select v-model="formData.timeGranularity" placeholder="请选择"> |
| | | <el-select v-model="formData.timeGranularity" clearable placeholder="请选择"> |
| | | <el-option |
| | | v-for="dict in getStrDictOptions(DICT_TYPE.TIME_GRANULARITY)" |
| | | :key="dict.value" |
| | |
| | | <el-input v-model="formData.unit"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-form-item label="固化标识" prop="solidifyFlag"> |
| | | <el-select v-model="formData.solidifyFlag" |
| | | clearable |
| | | filterable |
| | | allow-create |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="dict in getStrDictOptions(DICT_TYPE.SOLIDIFY_FLAG)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="6"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="数据集" prop="atomItem.dataSet"> |
| | | <el-select v-model="formData.atomItem.dataSet" clearable placeholder="请选择数据集" @change="handleDataSetChange($event)"> |
| | | <el-select v-model="formData.atomItem.dataSet" filterable |
| | | allow-create clearable placeholder="请选择数据集" @change="handleDataSetChange($event)"> |
| | | <el-option |
| | | v-for="item in dataSetList" |
| | | :key="item.id" |
| | |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-form-item label="使用字段" prop="atomItem.usingField"> |
| | | <el-select v-model="formData.atomItem.usingField" clearable placeholder="请选择字段"> |
| | | <el-select v-model="formData.atomItem.usingField" filterable |
| | | allow-create clearable placeholder="请选择字段"> |
| | | <el-option |
| | | v-for="item in dataSetFieldList" |
| | | :key="item.id" |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-form-item label="统计方式" prop="statFunc"> |
| | | <el-form-item label="统计方式" prop="atomItem.statFunc"> |
| | | <el-select v-model="formData.atomItem.statFunc" clearable placeholder="请选择"> |
| | | <el-option |
| | | v-for="dict in getStrDictOptions(DICT_TYPE.DATA_STAT_FUNC)" |
| | |
| | | import * as DataSetApi from '@/api/data/ind/data/data.set' |
| | | import * as DataSetFieldApi from '@/api/data/ind/data/data.field' |
| | | import * as CategoryApi from '@/api/data/ind/category/index' |
| | | |
| | | import {handleTree} from "@/utils/tree"; |
| | | |
| | | defineOptions({name: 'IndDataSetForm'}) |
| | | |
| | |
| | | timeRange: '', |
| | | timeGranularity: '', |
| | | remark: '', |
| | | solidifyFlag: '', |
| | | atomItem:{ |
| | | dataSource:'', |
| | | dataSet: '', |
| | |
| | | const formRules = reactive({ |
| | | itemName: [{required: true, message: '指标名称不能为空', trigger: 'blur'}], |
| | | itemCategory: [{required: true, message: '指标分类不能为空', trigger: 'blur'}], |
| | | /*precision: [{validator: validateAsNumber, trigger: 'blur' }], |
| | | coefficient: [{validator: validateAsNumber, trigger: 'blur' }], |
| | | statFunc: [{required: true, message: '统计方式不能为空', trigger: 'blur'}], |
| | | timeGranularity: [{required: true, message: '时间粒度不能为空', trigger: 'blur'}], |
| | | "atomItem.dataSet": [{required: true, message: '数据集不能为空', trigger: 'blur'}], |
| | | "atomItem.usingField":[{required: true, message: '使用字段不能为空', trigger: 'blur'}]*/ |
| | | "atomItem.usingField": [{required: true, message: '使用字段不能为空', trigger: 'blur'}], |
| | | // "atomItem.statFunc": [{required: true, message: '统计方式不能为空', trigger: 'blur'}], |
| | | }) |
| | | const formRef = ref() // 表单 Ref |
| | | const dataSetList = ref([] as DataSetApi.DataSetVO[]) |
| | | const dataSetFieldList = ref([] as DataSetFieldApi.DataSetFieldVO[]) |
| | | const dataCategoryList = ref([]) |
| | | |
| | | const dataCategoryList = ref<Tree[]>([]) |
| | | |
| | | const getCategoryTree = async () => { |
| | | dataCategoryList.value = [] |
| | | const res = await CategoryApi.getCategoryListAllSimple() |
| | | let category: Tree = {id: 0, label: '主类目', children: []} |
| | | category.children = handleTree(res, 'id', 'pid') |
| | | dataCategoryList.value.push(category) |
| | | } |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: string) => { |
| | | dialogVisible.value = true |
| | |
| | | resetForm() |
| | | // 加载数据源列表 |
| | | dataSetList.value = await DataSetApi.getDataSetList() |
| | | dataCategoryList.value = await CategoryApi.getCategoryListAllSimple() |
| | | await getCategoryTree() |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标分类" prop="itemCategory"> |
| | | <el-select v-model="formData.itemCategory" clearable placeholder="请选择指标分类"> |
| | | <el-option |
| | | v-for="item in dataCategoryList" |
| | | :key="item.id" |
| | | :label="item.label" |
| | | :value="item.id + ''" |
| | | /> |
| | | </el-select> |
| | | <el-tree-select |
| | | v-model="formData.itemCategory" |
| | | :data="dataCategoryList" |
| | | :default-expanded-keys="[0]" |
| | | :props="defaultProps" |
| | | check-strictly |
| | | node-key="id" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="8"> |
| | | <el-col :span="6"> |
| | | <el-form-item label="指标精度" prop="precision"> |
| | | <el-input v-model="formData.precision"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-col :span="6"> |
| | | <el-form-item label="转换系数" prop="coefficient"> |
| | | <el-input v-model="formData.coefficient"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-col :span="6"> |
| | | <el-form-item label="数量单位" prop="unit"> |
| | | <el-input v-model="formData.unit"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-form-item label="固化标识" prop="solidifyFlag"> |
| | | <el-select v-model="formData.solidifyFlag" |
| | | clearable |
| | | filterable |
| | | allow-create |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="dict in getStrDictOptions(DICT_TYPE.SOLIDIFY_FLAG)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | import * as ItemApi from '@/api/data/ind/item/item' |
| | | import { ElMessage } from 'element-plus' |
| | | import * as CategoryApi from '@/api/data/ind/category/index' |
| | | import {handleTree} from "@/utils/tree"; |
| | | |
| | | defineOptions({name: 'IndDataSetForm'}) |
| | | |
| | |
| | | timeRange: '', |
| | | timeGranularity: '', |
| | | remark: '', |
| | | solidifyFlag:'', |
| | | calItem: { |
| | | id: '', |
| | | expression: '', |
| | |
| | | const operatorList = ref(['+', '-', '*', '/', '&', '|', '!', '>', '<']) |
| | | const formRules = reactive({ |
| | | itemName: [{required: true, message: '指标名称不能为空', trigger: 'blur'}], |
| | | itemCategory: [{required: true, message: '指标类型不能为空', trigger: 'blur'}], |
| | | precision: [{validator: validateAsNumber, trigger: 'blur' }], |
| | | coefficient: [{validator: validateAsNumber, trigger: 'blur' }], |
| | | itemCategory: [{required: true, message: '指标类型不能为空', trigger: 'blur'}] |
| | | // precision: [{validator: validateAsNumber, trigger: 'blur' }], |
| | | // coefficient: [{validator: validateAsNumber, trigger: 'blur' }], |
| | | }) |
| | | const formRef = ref() // 表单 Ref |
| | | const dataSourceList = ref([] as DataSourceConfigApi.DataSourceConfigVO[]) |
| | | const queryParams = reactive({}) |
| | | const dataCategoryList = ref([] as CategoryApi.IndItemCategoryVO[]) |
| | | |
| | | const dataCategoryList = ref<Tree[]>([]) |
| | | const getCategoryTree = async () => { |
| | | dataCategoryList.value = [] |
| | | const res = await CategoryApi.getCategoryListAllSimple() |
| | | let category: Tree = {id: 0, label: '主类目', children: []} |
| | | category.children = handleTree(res, 'id', 'pid') |
| | | dataCategoryList.value.push(category) |
| | | } |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: number) => { |
| | | dialogVisible.value = true |
| | |
| | | resetForm() |
| | | |
| | | // 加载数据源列表 |
| | | dataCategoryList.value = await CategoryApi.getCategoryListAllSimple() |
| | | await getCategoryTree() |
| | | itemList.value = await ItemApi.getItemList(queryParams) |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | |
| | | :rules="formRules" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标编码" prop="itemNo"> |
| | | <el-input v-model="formData.itemNo" disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标名称" prop="itemName"> |
| | | <el-input v-model="formData.itemName"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="原子指标" prop="atomItem.itemId"> |
| | | <el-select v-model="formData.atomItem.itemId" clearable placeholder="请选择原子指标" |
| | | <el-select v-model="formData.atomItem.itemId" filterable |
| | | allow-create clearable placeholder="请选择原子指标" |
| | | @change="handleChange($event)"> |
| | | <el-option |
| | | v-for="item in atomItemList" |
| | |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标编码" prop="itemNo"> |
| | | <el-input v-model="formData.itemNo" disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标名称" prop="itemName"> |
| | | <el-input v-model="formData.itemName"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标分类" prop="itemCategory"> |
| | | <el-select v-model="formData.itemCategory" clearable placeholder="请选择指标分类"> |
| | | <el-option |
| | | v-for="item in dataCategoryList" |
| | | :key="item.id" |
| | | :label="item.label" |
| | | :value="item.id + ''" |
| | | /> |
| | | </el-select> |
| | | <el-tree-select |
| | | v-model="formData.itemCategory" |
| | | :data="dataCategoryList" |
| | | :default-expanded-keys="[0]" |
| | | :props="defaultProps" |
| | | check-strictly |
| | | node-key="id" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | <el-input v-model="formData.unit"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-form-item label="固化标识" prop="solidifyFlag"> |
| | | <el-select v-model="formData.solidifyFlag" |
| | | clearable |
| | | filterable |
| | | allow-create |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="dict in getStrDictOptions(DICT_TYPE.SOLIDIFY_FLAG)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="6"> |
| | | <el-form-item label="时间标识" prop="timeLabel"> |
| | | <el-select v-model="formData.derItem.timeLabel" clearable placeholder="请选择时间标识"> |
| | | <el-select v-model="formData.derItem.timeLabel" allow-create filterable clearable placeholder="请选择时间标识"> |
| | | <el-option |
| | | v-for="item in dataSetFieldList" |
| | | :key="item.id" |
| | |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="分析维度" prop="dimension"> |
| | | <el-select v-model="formData.derItem.dimension" clearable placeholder="请选择分析维度" multiple> |
| | | <el-select v-model="formData.derItem.dimension" filterable |
| | | allow-create clearable placeholder="请选择分析维度" multiple> |
| | | <el-option |
| | | v-for="item in dataSetFieldList" |
| | | :key="item.id" |
| | |
| | | import {PageParam} from "@/api/data/ind/item/item"; |
| | | import * as CategoryApi from "@/api/data/ind/category"; |
| | | import * as DataSetFieldApi from "@/api/data/ind/data/data.field"; |
| | | import {handleTree} from "@/utils/tree"; |
| | | |
| | | defineOptions({name: 'IndDataSetForm'}) |
| | | |
| | |
| | | businessType: '', |
| | | timeRange: '', |
| | | timeGranularity: '', |
| | | solidifyFlag:'', |
| | | atomItem: { |
| | | id: '', |
| | | itemId: '', |
| | |
| | | const formRef = ref() // 表单 Ref |
| | | const atomItemList = ref([] as ItemApi.ItemVO[]) |
| | | const showTimeChange = ref(false) |
| | | const dataCategoryList = ref([] as CategoryApi.IndItemCategoryVO[]) |
| | | const dataSetFieldList = ref([] as DataSetFieldApi.DataSetFieldVO[]) |
| | | const dataCategoryList = ref<Tree[]>([]) |
| | | |
| | | const getCategoryTree = async () => { |
| | | dataCategoryList.value = [] |
| | | const res = await CategoryApi.getCategoryListAllSimple() |
| | | let category: Tree = {id: 0, label: '主类目', children: []} |
| | | category.children = handleTree(res, 'id', 'pid') |
| | | dataCategoryList.value.push(category) |
| | | } |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: string) => { |
| | | dialogVisible.value = true |
| | |
| | | formType.value = type |
| | | resetForm() |
| | | // 加载数据源列表 |
| | | dataCategoryList.value = await CategoryApi.getCategoryListAllSimple() |
| | | await getCategoryTree() |
| | | const queryParams = reactive({ |
| | | itemType: 'ATOM' |
| | | }) |
对比新文件 |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="指标当前值" |
| | | :close-on-click-modal="false" |
| | | width="30%" |
| | | v-model="visible" |
| | | > |
| | | <el-form |
| | | :inline="true" |
| | | :model="dataForm" |
| | | > |
| | | <el-form-item> |
| | | <el-button @click="getData()">查询</el-button> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-input v-model="dataForm.itemCurrentData" type="textarea" :rows="15" style="width: 550px" disabled/> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | | import {ref} from 'vue'; |
| | | import * as ItemApi from '@/api/data/ind/item/item' |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const visible = ref(false); |
| | | const dataForm = ref({ |
| | | itemNo: "", |
| | | itemCurrentData: "", |
| | | }); |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (itemNo: string) => { |
| | | visible.value = true |
| | | dataForm.value.itemNo = itemNo |
| | | dataForm.value.itemCurrentData = JSON.stringify(await ItemApi.getItemCurrentData(itemNo)); |
| | | } |
| | | |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | const getData = async() =>{ |
| | | dataForm.value.itemCurrentData = JSON.stringify(await ItemApi.getItemCurrentData(dataForm.value.itemNo)); |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="历史值" |
| | | :close-on-click-modal="false" |
| | | width="50%" |
| | | v-model="visible" |
| | | > |
| | | <el-form |
| | | :inline="true" |
| | | :model="dataForm" |
| | | @keydown.enter="getDataList()" |
| | | > |
| | | <el-form-item label="开始时间"> |
| | | <el-date-picker |
| | | size="mini" |
| | | v-model="dataForm.startTime" |
| | | format="YYYY-MM-DD HH:mm:00" |
| | | value-format="YYYY-MM-DD HH:mm:00" |
| | | type="datetime" |
| | | :clearable="false" |
| | | placeholder="选择日期时间"/> |
| | | </el-form-item> |
| | | <el-form-item label="结束时间"> |
| | | <el-date-picker |
| | | size="mini" |
| | | v-model="dataForm.endTime" |
| | | format="YYYY-MM-DD HH:mm:00" |
| | | value-format="YYYY-MM-DD HH:mm:00" |
| | | type="datetime" |
| | | :clearable="false" |
| | | placeholder="选择日期时间"/> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="getDataList()">查询</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div ref="chartDom" class="result-chart" v-loading="loading"></div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | | import {ref} from 'vue'; |
| | | import * as echarts from 'echarts'; |
| | | import * as ItemApi from '@/api/data/ind/item/item' |
| | | import {getYMDHM0} from "@/utils/dateUtil" |
| | | import download from "@/utils/download"; |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const visible = ref(false); |
| | | const chartDom = ref(null); |
| | | let myChart = null; |
| | | const chartParams = reactive({ |
| | | itemNo: undefined, |
| | | startTime: undefined, |
| | | endTime: undefined, |
| | | }) |
| | | const dataForm = ref({ |
| | | id: "", |
| | | itemNo: "", |
| | | itemName: "", |
| | | startTime: getYMDHM0(new Date() - 60 * 60 * 1000), |
| | | endTime: "", |
| | | }); |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (row: object) => { |
| | | visible.value = true |
| | | dataForm.value.id = row.id; |
| | | dataForm.value.itemNo = row.itemNo; |
| | | dataForm.value.itemName = row.itemName; |
| | | getDataList(); |
| | | } |
| | | |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | const loading = ref(false) |
| | | |
| | | async function getDataList() { |
| | | visible.value = true; |
| | | loading.value = true |
| | | if (dataForm.value.id) { |
| | | try { |
| | | chartParams.itemNo = dataForm.value.itemNo; |
| | | chartParams.startTime = dataForm.value.startTime; |
| | | chartParams.endTime = dataForm.value.endTime; |
| | | const result = await ItemApi.getItemValueData(chartParams) |
| | | loading.value = false |
| | | let xData = result.map(obj => obj['dataTime']); |
| | | let yData = result.map(obj => obj['dataValue']); |
| | | let data = xData.map((x, index) => [x, yData[index]]); |
| | | let seriesData = [] |
| | | seriesData.push({ |
| | | name: dataForm.value.itemName, |
| | | type: "line", |
| | | data: data, |
| | | showSymbol: true, |
| | | smooth: false, |
| | | lineStyle: { |
| | | normal: { |
| | | color: "#5B8FF9", |
| | | width: 1, |
| | | }, |
| | | }, |
| | | }); |
| | | |
| | | myChart = echarts.init(chartDom.value); |
| | | const option = { |
| | | title: { |
| | | text: dataForm.value.itemName, |
| | | top: 0, |
| | | left: "1%", |
| | | textStyle: { |
| | | fontSize: 14, |
| | | }, |
| | | }, |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "line", |
| | | lineStyle: { |
| | | color: "#cccccc", |
| | | width: "1", |
| | | type: "dashed", |
| | | }, |
| | | }, |
| | | }, |
| | | legend: { |
| | | show: false, |
| | | top: 10, |
| | | }, |
| | | grid: { |
| | | top: 30, |
| | | left: "3%", |
| | | right: "5%", |
| | | bottom: 10, |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | boundaryGap: false, |
| | | data: xData, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | }, |
| | | dataZoom: [ |
| | | { |
| | | type: "inside", |
| | | }, |
| | | ], |
| | | series: seriesData, |
| | | }; |
| | | myChart.setOption(option); |
| | | } catch (error) { |
| | | console.error(error) |
| | | } |
| | | } |
| | | } |
| | | |
| | | </script> |
| | | <style> |
| | | .el-select { |
| | | width: 100%; |
| | | } |
| | | |
| | | .result-chart { |
| | | height: 500px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <!-- 搜索工作栏 --> |
| | | <ContentWrap> |
| | | <el-form ref="queryFormRef" :inline="true" :model="queryParams" class="-mb-15px" |
| | | label-width="68px"> |
| | | <el-form-item label="指标编码" prop="itemNo"> |
| | | <el-input v-model="queryParams.itemNo" class="!w-200px" clearable placeholder="请输入指标编码" |
| | | @keyup.enter="handleQuery"/> |
| | | </el-form-item> |
| | | <el-form-item label="指标名称" prop="itemName"> |
| | | <el-input v-model="queryParams.itemName" class="!w-200px" clearable placeholder="请输入指标名称" |
| | | @keyup.enter="handleQuery"/> |
| | | </el-form-item> |
| | | <el-form-item label="指标类型" prop="itemType"> |
| | | <el-select v-model="queryParams.itemType" class="!w-200px" clearable placeholder="请选择指标类型"> |
| | | <el-option |
| | | v-for="dict in getStrDictOptions(DICT_TYPE.IND_ITEM_TYPE)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon class="mr-5px" icon="ep:search"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon class="mr-5px" icon="ep:refresh"/> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | v-hasPermi="['data:ind-item:create']" |
| | | plain |
| | | type="primary" |
| | | @click="openForm('create')" |
| | | > |
| | | <Icon class="mr-5px" icon="ep:plus"/> |
| | | 新增 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="3" :xs="24"> |
| | | <ContentWrap class="h-1/1"> |
| | | <el-tree |
| | | style="max-width: 600px" |
| | | :data="dataCategoryList" |
| | | :props="treeProps" |
| | | default-expand-all |
| | | highlight-current |
| | | @node-click="handleNodeClick" |
| | | /> |
| | | </ContentWrap> |
| | | </el-col> |
| | | <el-col :span="21" :xs="24"> |
| | | <!-- 搜索工作栏 --> |
| | | <ContentWrap> |
| | | <el-form ref="queryFormRef" :inline="true" :model="queryParams" class="-mb-15px" |
| | | label-width="68px"> |
| | | <el-form-item label="指标编码" prop="itemNo"> |
| | | <el-input v-model="queryParams.itemNo" class="!w-200px" clearable placeholder="请输入指标编码" |
| | | @keyup.enter="handleQuery"/> |
| | | </el-form-item> |
| | | <el-form-item label="指标名称" prop="itemName"> |
| | | <el-input v-model="queryParams.itemName" class="!w-200px" clearable placeholder="请输入指标名称" |
| | | @keyup.enter="handleQuery"/> |
| | | </el-form-item> |
| | | <el-form-item label="指标类型" prop="itemType"> |
| | | <el-select v-model="queryParams.itemType" class="!w-200px" clearable placeholder="请选择指标类型"> |
| | | <el-option |
| | | v-for="dict in getStrDictOptions(DICT_TYPE.IND_ITEM_TYPE)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon class="mr-5px" icon="ep:search"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon class="mr-5px" icon="ep:refresh"/> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | v-hasPermi="['data:ind-item:create']" |
| | | plain |
| | | type="primary" |
| | | @click="openForm('create')" |
| | | > |
| | | <Icon class="mr-5px" icon="ep:plus"/> |
| | | 新增 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column prop="itemNo" label="指标编码" header-align="center" align="center" min-width="80"/> |
| | | <el-table-column prop="itemName" label="指标名称" header-align="center" align="center" min-width="120"/> |
| | | <el-table-column prop="itemCategoryName" label="指标分类" header-align="center" align="center" min-width="100"/> |
| | | <el-table-column prop="itemType" label="指标类型" header-align="center" align="center" min-width="60"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.IND_ITEM_TYPE" :value="scope.row.itemType" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="coefficient" label="系数" header-align="center" align="center" min-width="60"/> |
| | | <el-table-column prop="precision" label="指标精度" header-align="center" align="center" min-width="60"/> |
| | | <el-table-column prop="timeGranularity" label="时间粒度" header-align="center" align="center" min-width="40"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.TIME_GRANULARITY" :value="scope.row.timeGranularity" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | :formatter="dateFormatter" |
| | | align="center" |
| | | label="创建时间" |
| | | prop="createTime" |
| | | width="180"/> |
| | | <el-table-column align="center" label="操作"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | v-hasPermi="['data:ind-item:update']" |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row)"> |
| | | 修改 |
| | | </el-button> |
| | | <el-button |
| | | v-hasPermi="['data:ind-item:delete']" |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)"> |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | v-model:limit="queryParams.pageSize" |
| | | v-model:page="queryParams.pageNo" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column prop="itemNo" label="指标编码" header-align="center" align="center" min-width="70"/> |
| | | <el-table-column prop="itemName" label="指标名称" header-align="center" align="center" min-width="150"/> |
| | | <el-table-column prop="itemCategoryName" label="指标分类" header-align="center" align="center" min-width="80"/> |
| | | <el-table-column prop="itemType" label="指标类型" header-align="center" align="center" min-width="60"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.IND_ITEM_TYPE" :value="scope.row.itemType" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="coefficient" label="系数" header-align="center" align="center" min-width="50"/> |
| | | <el-table-column prop="precision" label="指标精度" header-align="center" align="center" min-width="50"/> |
| | | <el-table-column prop="timeGranularity" label="时间粒度" header-align="center" align="center" min-width="50"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.TIME_GRANULARITY" :value="scope.row.timeGranularity" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | :formatter="dateFormatter" |
| | | align="center" |
| | | label="创建时间" |
| | | prop="createTime" |
| | | width="200"/> |
| | | <el-table-column align="center" label="操作"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | v-hasPermi="['data:ind-item:update']" |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row)"> |
| | | 修改 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="getCurrentData(scope.row.itemNo)"> |
| | | 当前值 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="getHistoryData(scope.row)"> |
| | | 历史值 |
| | | </el-button> |
| | | <el-button |
| | | v-hasPermi="['data:ind-item:delete']" |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)"> |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | v-model:limit="queryParams.pageSize" |
| | | v-model:page="queryParams.pageNo" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <AtomIndDefineForm ref="atomFormRef" @success="getList" /> |
| | | <DerIndDefineForm ref="derFormRef" @success="getList" /> |
| | | <CalIndDefineForm ref="calFormRef" @success="getList" /> |
| | | <SelectItemType ref="itemTypeSel"/> |
| | | <IndCurrentData ref="indCurrentData"/> |
| | | <IndHistoryChart ref="indHistoryChart"/> |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | |
| | | import download from '@/utils/download' |
| | | import * as ItemApi from '@/api/data/ind/item/item' |
| | | import * as CategoryApi from "@/api/data/ind/category"; |
| | | import IndCurrentData from './IndCurrentData.vue' |
| | | import IndHistoryChart from './IndHistoryChart.vue' |
| | | import {handleTree} from "@/utils/tree"; |
| | | |
| | | |
| | | defineOptions({ name: 'IndItem' }) |
| | | |
| | |
| | | const data = await ItemApi.getItemPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | dataCategoryList.value = await CategoryApi.getCategoryListAllSimple() |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | const getCategoryTree = async () => { |
| | | dataCategoryList.value = [] |
| | | const res = await CategoryApi.getCategoryListAllSimple() |
| | | let category: Tree = {id: 0, label: '主类目', children: []} |
| | | category.children = handleTree(res, 'id', 'pid') |
| | | dataCategoryList.value.push(category) |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | |
| | | }else { |
| | | itemTypeSel.value.open(type) |
| | | } |
| | | } |
| | | const indCurrentData = ref() |
| | | const getCurrentData = (itemNo: string) => { |
| | | indCurrentData.value.open(itemNo) |
| | | } |
| | | |
| | | const indHistoryChart = ref() |
| | | const getHistoryData = (raw: object) => { |
| | | indHistoryChart.value.open(raw) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | |
| | | } catch {} |
| | | } |
| | | |
| | | const handleNodeClick = (data: Tree) => { |
| | | if( data.id !== 0 ){ |
| | | queryParams.itemCategory = String(data.id) |
| | | }else { |
| | | queryParams.itemCategory = '' |
| | | } |
| | | getList() |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(() => { |
| | | getList() |
| | | getCategoryTree() |
| | | }) |
| | | </script> |
| | |
| | | </el-form-item> |
| | | <el-form-item label="查询语句" prop="querySql"> |
| | | <el-input v-model="formData.querySql" placeholder="请输入内容" type="textarea" maxlength="300" |
| | | show-word-limit :rows="6" spellcheck="false"/> |
| | | show-word-limit :rows="6" @input="checkSensitiveWords" spellcheck="false"/> |
| | | </el-form-item> |
| | | <el-form-item v-if="showError"> |
| | | <p>输入中包含以下敏感词:<span style="color: red">{{sensitiveMessage}}</span></p> |
| | | </el-form-item> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" maxlength="100" |
| | |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button :disabled="disableSubmit" type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
| | | import * as DataSetApi from '@/api/data/plan/data' |
| | | import { CommonStatusEnum } from '@/utils/constants' |
| | | import * as DataSourceConfigApi from "@/api/infra/dataSourceConfig"; |
| | | |
| | | defineOptions({ name: 'PlanDataSetForm' }) |
| | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const showError = ref(false) |
| | | const foundSensitiveWords = ref() |
| | | const sensitiveMessage = ref('') |
| | | const sensitiveWords = [';', 'master', 'truncate', 'insert', 'delete', 'update', 'declare', 'alter', 'drop'] |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formLoading = ref(false) // 表单的加载中:修改时的数据加载; |
| | | const disableSubmit = ref(false) // 禁止提交 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** |
| | | * 验证敏感词 |
| | | */ |
| | | const checkSensitiveWords = () => { |
| | | showError.value = false; |
| | | const regex = new RegExp(sensitiveWords.map(word => `${word}`).join('|'), 'gi'); |
| | | let matches = formData.value.querySql.match(regex); |
| | | if (matches) { |
| | | showError.value = true; |
| | | foundSensitiveWords.value = Array.from(new Set(matches)); |
| | | disableSubmit.value = true |
| | | sensitiveMessage.value = foundSensitiveWords.value.join('、') |
| | | } else { |
| | | foundSensitiveWords.value = undefined |
| | | disableSubmit.value = false |
| | | } |
| | | } |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | |
| | | if (!valid) return |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | disableSubmit.value = true |
| | | try { |
| | | const data = formData.value as DataSetApi.DataSetVO |
| | | if (formType.value === 'create') { |
| | |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | disableSubmit.value = false |
| | | } |
| | | } |
| | | |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="采集值" |
| | | title="历史值" |
| | | :close-on-click-modal="false" |
| | | width="50%" |
| | | v-model="visible" |
| | |
| | | <el-select |
| | | v-model="formData.pointType" |
| | | clearable |
| | | :disabled = "formType !== 'create'" |
| | | placeholder="请选择测点类型" |
| | | > |
| | | <el-option |
对比新文件 |
| | |
| | | <template> |
| | | <el-dialog |
| | | title="当前值" |
| | | :close-on-click-modal="false" |
| | | width="50%" |
| | | v-model="visible" |
| | | > |
| | | <el-form |
| | | :model="dataForm" |
| | | v-loading="formLoading" |
| | | label-width="120px" |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="测点编码" prop="pointNo"> |
| | | <el-input v-model="dataForm.pointNo" readonly/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="测点名称" prop="pointName"> |
| | | <el-input v-model="dataForm.pointName" readonly/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="数据时间" prop="dataTime"> |
| | | <el-input v-model="dataForm.dataTime" readonly/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="数据值" prop="dataValue"> |
| | | <el-input v-model="dataForm.dataValue" readonly> |
| | | <template #append>{{ dataForm.unit }}</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap v-if="dataForm.pointType === 'CALCULATE'"> |
| | | <el-table border stripe v-loading="tableLoading" :data="list"> |
| | | <el-table-column type="index" header-align="center" align="center" fixed="left" width="50"/> |
| | | <el-table-column fixed label="测点编码" header-align="center" align="left" min-width="150" prop="pointNo" /> |
| | | <el-table-column fixed label="测点名称" header-align="center" align="left" min-width="240" prop="pointName" /> |
| | | <el-table-column fixed label="当前值" header-align="center" align="left" min-width="150" prop="currentValue" /> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | </el-dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | |
| | | import {reactive, ref} from "vue"; |
| | | import {getYMDHM0} from "@/utils/dateUtil"; |
| | | import * as DaPoint from "@/api/data/da/point/daPointChart"; |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const visible = ref(false); |
| | | const formLoading = ref(false) |
| | | const tableLoading = ref(false) |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 列表的数据 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | pointNo: undefined |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | const dataForm = ref({ |
| | | id: "", |
| | | pointNo: "", |
| | | pointName: "", |
| | | pointType: "", |
| | | unit: "", |
| | | dataTime: "", |
| | | dataValue: "", |
| | | }); |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (row: object) => { |
| | | visible.value = true |
| | | resetForm() |
| | | dataForm.value.id = row.id; |
| | | dataForm.value.pointNo = row.pointNo; |
| | | dataForm.value.pointName = row.pointName; |
| | | dataForm.value.pointType = row.pointType; |
| | | dataForm.value.unit = row.unit; |
| | | getCurrentData() |
| | | queryParams.pointNo = row.pointNo; |
| | | if (dataForm.value.pointType === "CALCULATE") { |
| | | getList() |
| | | } |
| | | } |
| | | |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | async function getCurrentData() { |
| | | visible.value = true; |
| | | formLoading.value = true |
| | | if (dataForm.value.id) { |
| | | let params0 = [dataForm.value.pointNo] |
| | | const data = await DaPoint.getPointsRealValue(params0) |
| | | formLoading.value = false |
| | | dataForm.value.dataTime = getYMDHM0(new Date()); |
| | | dataForm.value.dataValue = data[dataForm.value.pointNo] |
| | | } |
| | | } |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | tableLoading.value = true |
| | | try { |
| | | const page = await DaPoint.getMathPointCurrentValue(queryParams) |
| | | list.value = page.list |
| | | total.value = page.total |
| | | } finally { |
| | | tableLoading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | dataForm.value = { |
| | | id: undefined, |
| | | pointNo: undefined, |
| | | pointName: undefined, |
| | | pointType: undefined, |
| | | unit: undefined, |
| | | dataTime: undefined, |
| | | dataValue: undefined, |
| | | } |
| | | } |
| | | |
| | | </script> |
| | |
| | | class="!w-200px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="测点类型" prop="pointType"> |
| | | <el-select |
| | | v-model="queryParams.pointType" |
| | | placeholder="请选择" |
| | | clearable |
| | | class="!w-240px" |
| | | > |
| | | <el-option |
| | | v-for="dict in getStrDictOptions(DICT_TYPE.DATA_POINT_TYPE)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="测点Tag" prop="tagNo"> |
| | | <el-input |
| | | v-model="queryParams.tagNo" |
| | |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" align="center" min-width="130" fixed="right" width="120"> |
| | | <el-table-column label="操作" align="center" min-width="130" fixed="right" width="140"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button link size="mini" type="primary" @click="chartHandle(scope.row)">数据</el-button> |
| | | <el-button link size="mini" type="primary" @click="chartHandle(scope.row)">历史值</el-button> |
| | | <el-button |
| | | link |
| | | size="mini" |
| | |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | <el-button link size="mini" type="primary" @click="pointValueHandle(scope.row)">当前值</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <DaPointForm ref="formRef" @success="getList" /> |
| | | |
| | | <!-- 历史值 --> |
| | | <DaPointChart ref="chartView" /> |
| | | |
| | | <!-- 用户导入对话框 --> |
| | | <!-- 当前值 --> |
| | | <DaPointValue ref="pointValue" /> |
| | | |
| | | <!-- 测点导入对话框 --> |
| | | <PointImportForm ref="importFormRef" @success="getList" /> |
| | | </template> |
| | | <script lang="ts" setup> |
| | |
| | | import {DICT_TYPE, getDictOptions, getIntDictOptions, getStrDictOptions} from "@/utils/dict"; |
| | | import DaPointForm from './DaPointForm.vue' |
| | | import DaPointChart from './DaPointChart.vue' |
| | | import * as UserApi from "@/api/system/user"; |
| | | import DaPointValue from './DaPointValue.vue' |
| | | import PointImportForm from './PointImportForm.vue' |
| | | |
| | | defineOptions({name: 'DataPoint'}) |
| | |
| | | pageSize: 10, |
| | | pointNo: undefined, |
| | | pointName: undefined, |
| | | pointType: undefined, |
| | | tagNo: undefined, |
| | | collectQuality: undefined, |
| | | }) |
| | |
| | | getList() |
| | | } |
| | | |
| | | /** 查看数据操作 */ |
| | | /** 查看历史值操作 */ |
| | | const chartView = ref() |
| | | const chartHandle = (raw: object) => { |
| | | chartView.value.open(raw) |
| | | } |
| | | |
| | | /** 查看当前值操作 */ |
| | | const pointValue = ref() |
| | | const pointValueHandle = (raw: object) => { |
| | | pointValue.value.open(raw) |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="日志编号" align="center" prop="id" width="100" fix="right" /> |
| | | <el-table-column label="用户编号" align="center" prop="userId" /> |
| | | <el-table-column label="用户类型" align="center" prop="userType"> |
| | | <el-table-column label="用户编号" align="center" prop="userId" width="80"/> |
| | | <el-table-column label="用户类型" align="center" prop="userType" width="100"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="应用名" align="center" prop="applicationName" width="150" /> |
| | | <el-table-column label="应用名" align="center" prop="applicationName" width="120" /> |
| | | <el-table-column label="请求方法" align="center" prop="requestMethod" width="80" /> |
| | | <el-table-column label="请求地址" align="center" prop="requestUrl" width="500" /> |
| | | <el-table-column label="请求地址" align="center" prop="requestUrl" /> |
| | | <el-table-column label="请求时间" align="center" prop="beginTime" width="180"> |
| | | <template #default="scope"> |
| | | <span>{{ formatDate(scope.row.beginTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="执行时长" align="center" prop="duration" width="180"> |
| | | <el-table-column label="执行时长" align="center" prop="duration" width="100"> |
| | | <template #default="scope"> {{ scope.row.duration }} ms </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作结果" align="center" prop="status"> |
| | | <el-table-column label="操作结果" align="center" prop="status" width="120"> |
| | | <template #default="scope"> |
| | | {{ scope.row.resultCode === 0 ? '成功' : '失败(' + scope.row.resultMsg + ')' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作模块" align="center" prop="operateModule" width="180" /> |
| | | <el-table-column label="操作名" align="center" prop="operateName" width="180" /> |
| | | <el-table-column label="操作类型" align="center" prop="operateType"> |
| | | <el-table-column label="操作类型" align="center" prop="operateType" width="80"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.INFRA_OPERATE_TYPE" :value="scope.row.operateType" /> |
| | | </template> |
| | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="日志编号" align="center" prop="id" /> |
| | | <el-table-column label="用户编号" align="center" prop="userId" /> |
| | | <el-table-column label="用户类型" align="center" prop="userType"> |
| | | <el-table-column label="日志编号" align="center" prop="id" width="100"/> |
| | | <el-table-column label="用户编号" align="center" prop="userId" width="80"/> |
| | | <el-table-column label="用户类型" align="center" prop="userType" width="100"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="应用名" align="center" prop="applicationName" width="200" /> |
| | | <el-table-column label="应用名" align="center" prop="applicationName" width="120" /> |
| | | <el-table-column label="请求方法" align="center" prop="requestMethod" width="80" /> |
| | | <el-table-column label="请求地址" align="center" prop="requestUrl" width="180" /> |
| | | <el-table-column label="请求地址" align="center" prop="requestUrl" /> |
| | | <el-table-column |
| | | label="异常发生时间" |
| | | align="center" |
| | |
| | | width="180" |
| | | :formatter="dateFormatter" |
| | | /> |
| | | <el-table-column label="异常名" align="center" prop="exceptionName" width="180" /> |
| | | <el-table-column label="处理状态" align="center" prop="processStatus"> |
| | | <el-table-column label="异常名" align="center" prop="exceptionName" /> |
| | | <el-table-column label="处理状态" align="center" prop="processStatus" width="100"> |
| | | <template #default="scope"> |
| | | <dict-tag |
| | | :type="DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS" |
对比新文件 |
| | |
| | | <template> |
| | | <ContentWrap> |
| | | <!-- 搜索工作栏 --> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <!-- <el-form-item label="主机名称" prop="hostName">--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="queryParams.hostName"--> |
| | | <!-- placeholder="请输入主机名称"--> |
| | | <!-- clearable--> |
| | | <!-- @keyup.enter="handleQuery"--> |
| | | <!-- class="!w-240px"--> |
| | | <!-- />--> |
| | | <!-- </el-form-item>--> |
| | | <el-form-item label="服务器IP" prop="hostIp"> |
| | | <el-input |
| | | v-model="queryParams.hostIp" |
| | | placeholder="请输入服务器IP" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-120px" |
| | | /> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="盘符" prop="disk">--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="queryParams.disk"--> |
| | | <!-- placeholder="请输入盘符"--> |
| | | <!-- clearable--> |
| | | <!-- @keyup.enter="handleQuery"--> |
| | | <!-- class="!w-240px"--> |
| | | <!-- />--> |
| | | <!-- </el-form-item>--> |
| | | <el-form-item label="磁盘名" prop="diskName"> |
| | | <el-input |
| | | v-model="queryParams.diskName" |
| | | placeholder="请输入磁盘名" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-120px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间" prop="createTime"> |
| | | <el-date-picker |
| | | v-model="queryParams.createTime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetimerange" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" |
| | | class="!w-360px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px"/> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="openForm('create')" |
| | | v-hasPermi="['infra:monitor-disk:create']" |
| | | > |
| | | <Icon icon="ep:plus" class="mr-5px"/> |
| | | 新增 |
| | | </el-button> |
| | | <el-button |
| | | type="success" |
| | | plain |
| | | @click="handleExport" |
| | | :loading="exportLoading" |
| | | v-hasPermi="['infra:monitor-disk:export']" |
| | | > |
| | | <Icon icon="ep:download" class="mr-5px"/> |
| | | 导出 |
| | | </el-button> |
| | | </el-form-item> |
| | | <el-form-item style="float: right"> |
| | | <el-button |
| | | v-if="showType == 'chart'" |
| | | type="warning" |
| | | style="font-weight: bold" |
| | | plain |
| | | @click="switchShow('data')"> |
| | | <Icon icon="fa-solid:th-list" class="mr-5px"/> |
| | | 列表展示 |
| | | </el-button> |
| | | <el-button |
| | | v-if="showType == 'data'" |
| | | type="danger" |
| | | style="font-weight: bold" |
| | | plain |
| | | @click="switchShow('chart')"> |
| | | <Icon icon="fa-solid:chart-pie" class="mr-5px"/> |
| | | 图例展示 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <ContentWrap v-if="showType == 'chart'"> |
| | | <!-- 磁盘使用率折线图 --> |
| | | <el-skeleton :loading="echartsLoading" animated> |
| | | <Echart :height="320" :options="diskChartOptions"/> |
| | | </el-skeleton> |
| | | <!-- 磁盘使用率饼图 --> |
| | | <h3 style="margin-top: 20px; margin-bottom: 10px">主机磁盘使用率</h3> |
| | | <div v-for="host in hostList" :key="host.name" class="host"> |
| | | <div class="host-child"> |
| | | <h4>主机名:{{ host.name }} 主机IP:{{ host.ip }}</h4> |
| | | <el-skeleton :loading="echartsLoading" animated> |
| | | <div class="disks"> |
| | | <div v-for="disk in host.disks" :key="disk.name" class="disk"> |
| | | <h4 id="diskTitle">{{ disk.disk }}</h4> |
| | | <PieChart :used="disk.used" :total="disk.total" /> |
| | | <div class="disk-info"> |
| | | <div style="margin-bottom: 6px; font-size: 16px"><span style="color: #b9292b ;font-weight: bolder">{{ disk.total != 0 ? ((disk.used / disk.total) * 100).toFixed(1) : 0.0 }}% </span>已使用</div> |
| | | <div style="font-weight: bolder">{{ disk.used }}GB / {{ disk.total }}GB</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-skeleton> |
| | | </div> |
| | | </div> |
| | | <!-- <div v-for="(host, hostIndex) in hostList" :key="hostIndex">--> |
| | | <!-- <div style="margin-top: 10px">--> |
| | | <!-- <el-skeleton :loading="echartsLoading" animated>--> |
| | | <!-- {{ hostIndex }} 主机名: {{ host.name }} --> |
| | | <!-- 服务器IP:{{ host.ip }}--> |
| | | <!-- <div v-for="(disk, diskIndex) in host.disks" :key="diskIndex">--> |
| | | <!-- <h3>{{ disk.name }}</h3>--> |
| | | <!-- <div :ref="el => chartRefs[hostIndex][diskIndex] = el"--> |
| | | <!-- :style="{ width: '300px', height: '300px' }"></div>--> |
| | | <!-- </div>--> |
| | | <!-- </el-skeleton>--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap v-if="showType == 'data'"> |
| | | <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> |
| | | <el-table-column label="主机名称" align="center" prop="hostName"/> |
| | | <el-table-column label="服务器ip" align="center" prop="hostIp"/> |
| | | <el-table-column label="盘符" align="center" prop="disk"/> |
| | | <el-table-column label="磁盘名" align="center" prop="diskName"/> |
| | | <el-table-column label="总空间" align="center" prop="spaceTotal"/> |
| | | <el-table-column label="已用空间" align="center" prop="spaceUsed"/> |
| | | <el-table-column label="可用空间" align="center" prop="spaceUsable"/> |
| | | <el-table-column label="空间使用比例" align="center" prop="spaceRatio"/> |
| | | <el-table-column |
| | | label="创建时间" |
| | | align="center" |
| | | prop="createTime" |
| | | :formatter="dateFormatter" |
| | | width="180px" |
| | | /> |
| | | <el-table-column label="操作" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | v-hasPermi="['infra:monitor-disk:query']" |
| | | > |
| | | 详情 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | v-hasPermi="['infra:monitor-disk:delete']" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <MonitorDiskForm ref="formRef" @success="getList"/> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import {dateFormatter} from '@/utils/formatTime' |
| | | import download from '@/utils/download' |
| | | import {MonitorDiskApi, MonitorDiskVO} from '@/api/infra/monitordisk' |
| | | import MonitorDiskForm from './MonitorDiskForm.vue' |
| | | import {EChartsOption} from "echarts"; |
| | | import * as echarts from 'echarts'; |
| | | import {formatTime} from "@/utils"; |
| | | import {formatDate} from "@vueuse/core"; |
| | | import PieChart from '@/components/MonitorDiskPie/PieChart.vue'; |
| | | |
| | | /** 磁盘监控日志 列表 */ |
| | | defineOptions({name: 'MonitorDisk'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const list = ref<MonitorDiskVO[]>([]) // 列表的数据 |
| | | const total = ref(0) // 列表的总页数 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | hostName: undefined, |
| | | hostIp: undefined, |
| | | disk: undefined, |
| | | diskName: undefined, |
| | | spaceTotal: undefined, |
| | | spaceUsed: undefined, |
| | | spaceUsable: undefined, |
| | | spaceRatio: undefined, |
| | | createTime: [], |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | const exportLoading = ref(false) // 导出的加载中 |
| | | const echartsLoading = ref(true) // 图表加载中 |
| | | const showType = ref() //展示类型(chart-图例,data-数据) |
| | | |
| | | const hostList = ref([ |
| | | { |
| | | name: 'Thinkpad-E14', |
| | | ip: '172.16.216.133', |
| | | disks: [ |
| | | {disk: '磁盘C', used: 70, total: 200}, |
| | | {disk: '磁盘D', used: 40, total: 60} |
| | | ] |
| | | }, |
| | | { |
| | | name: 'Thinkpad-E16', |
| | | ip: '172.16.216.133', |
| | | disks: [ |
| | | {disk: '磁盘C', used: 80, total: 500}, |
| | | {disk: '磁盘D', used: 20, total: 500} |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | const chartRefs = ref([]); |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await MonitorDiskApi.getMonitorDiskPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNo = 1 |
| | | if (showType.value == 'data') { |
| | | getList() |
| | | } else { |
| | | getMonitorDiskDataList() |
| | | usedDiskInstance() |
| | | } |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number) => { |
| | | formRef.value.open(type, id) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await MonitorDiskApi.deleteMonitorDisk(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | /** 导出按钮操作 */ |
| | | const handleExport = async () => { |
| | | try { |
| | | // 导出的二次确认 |
| | | await message.exportConfirm() |
| | | // 发起导出 |
| | | exportLoading.value = true |
| | | const data = await MonitorDiskApi.exportMonitorDisk(queryParams) |
| | | download.excel(data, '磁盘监控日志.xls') |
| | | } catch { |
| | | } finally { |
| | | exportLoading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 堆叠面积图配置 */ |
| | | const diskChartOptions = reactive<EChartsOption>({ |
| | | title: { |
| | | text: '磁盘空间折线图' |
| | | }, |
| | | dataset: { |
| | | dimensions: [], |
| | | source: [] |
| | | }, |
| | | grid: { |
| | | left: 30, |
| | | right: 20, |
| | | bottom: 10, |
| | | top: 70, |
| | | containLabel: true |
| | | }, |
| | | legend: { |
| | | top: 0 |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'disk', type: 'line', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, smooth: false |
| | | } |
| | | ], |
| | | toolbox: { |
| | | feature: { |
| | | // 数据区域缩放 |
| | | dataZoom: { |
| | | yAxisIndex: false // Y轴不缩放 |
| | | }, |
| | | brush: { |
| | | type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 |
| | | }, |
| | | saveAsImage: {show: true, name: '物理内存日志图片'} // 保存为图片 |
| | | } |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label: { |
| | | backgroundColor: '#6a7985' |
| | | } |
| | | }, |
| | | padding: [5, 10] |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | axisTick: { |
| | | show: false |
| | | } |
| | | }, |
| | | yAxis: { |
| | | name: "单位(百分比)", |
| | | nameTextStyle: { |
| | | color: "#aaa", |
| | | nameLocation: "start", |
| | | }, |
| | | }, |
| | | }) as EChartsOption |
| | | |
| | | /** 查询统计数据列表 */ |
| | | const getMonitorDiskDataList = async () => { |
| | | const list = await MonitorDiskApi.getMonitorDiskList(queryParams) |
| | | if (list != null && list != undefined && list.length > 0) { |
| | | diskChartOptions.dataset['dimensions'] = Object.keys(list[0]) |
| | | diskChartOptions.series = diskChartOptions.dataset['dimensions'].map(item => ({ |
| | | name: item.name, |
| | | type: 'line', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | smooth: false |
| | | })); |
| | | diskChartOptions.series.splice(0, 1) |
| | | for (let item of list) { |
| | | item.createTime = formatTime(item.createTime, 'yyyy-MM-dd HH:mm:ss') |
| | | } |
| | | } |
| | | // 更新 Echarts 数据 |
| | | diskChartOptions.dataset['source'] = list |
| | | echartsLoading.value = false |
| | | } |
| | | |
| | | const usedDiskInstance = async () => { |
| | | const list = await MonitorDiskApi.getMonitorDiskInfo(queryParams) |
| | | hostList.value = list |
| | | // 仪表盘详情,用于显示数据。 |
| | | } |
| | | |
| | | /** 切换展示方式 */ |
| | | const switchShow = (type: String) => { |
| | | showType.value = type |
| | | if (showType.value == 'data') { |
| | | getList() |
| | | } else { |
| | | getMonitorDiskDataList() |
| | | usedDiskInstance() |
| | | } |
| | | } |
| | | |
| | | let intervalId; |
| | | /** 初始化 **/ |
| | | onMounted(() => { |
| | | showType.value = 'data'; |
| | | const currentDate = new Date(); |
| | | const previousDate = new Date(currentDate); |
| | | previousDate.setDate(currentDate.getDate() - 1); |
| | | queryParams.createTime[0] = formatDate(previousDate, 'YYYY-MM-DD HH:mm:ss'); |
| | | queryParams.createTime[1] = formatDate(currentDate, 'YYYY-MM-DD HH:mm:ss'); |
| | | intervalId = setInterval(() => { |
| | | if (showType.value == 'data') { |
| | | getList() |
| | | } else { |
| | | getMonitorDiskDataList() |
| | | usedDiskInstance() |
| | | } |
| | | }, 30000); |
| | | }) |
| | | |
| | | onUnmounted(() => { |
| | | clearInterval(intervalId); |
| | | }); |
| | | </script> |
| | | <style> |
| | | .host { |
| | | margin-bottom: 20px; |
| | | margin-right: 20px; |
| | | border-radius: 8px; |
| | | } |
| | | .host-child { |
| | | background: rgba(200, 200, 200, 0.3); |
| | | border-radius: 8px; |
| | | padding: 10px; |
| | | } |
| | | .disks { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); |
| | | gap: 20px; |
| | | margin-top: 20px; |
| | | } |
| | | .disk { |
| | | width: 250px; |
| | | background: rgba(100, 100, 150, 0.2); |
| | | padding: 15px; |
| | | border-radius: 16px; |
| | | text-align: center; |
| | | box-shadow: 0 2px 4px rgba(0,0,0,0.1); |
| | | } |
| | | |
| | | #diskTitle { |
| | | margin-bottom: 10px |
| | | } |
| | | |
| | | .disk-info { |
| | | margin-top: 10px; |
| | | font-size: 0.9em; |
| | | color: #666; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog :title="dialogTitle" v-model="dialogVisible"> |
| | | <el-form |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="100px" |
| | | v-loading="formLoading" |
| | | > |
| | | <el-form-item label="主机名称" prop="hostName"> |
| | | <el-input v-model="formData.hostName" placeholder="请输入主机名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="服务器ip" prop="hostIp"> |
| | | <el-input v-model="formData.hostIp" placeholder="请输入服务器ip" /> |
| | | </el-form-item> |
| | | <el-form-item label="盘符" prop="disk"> |
| | | <el-input v-model="formData.disk" placeholder="请输入盘符" /> |
| | | </el-form-item> |
| | | <el-form-item label="磁盘名" prop="diskName"> |
| | | <el-input v-model="formData.diskName" placeholder="请输入磁盘名" /> |
| | | </el-form-item> |
| | | <el-form-item label="总空间" prop="spaceTotal"> |
| | | <el-input v-model="formData.spaceTotal" placeholder="请输入总空间" /> |
| | | </el-form-item> |
| | | <el-form-item label="已用空间" prop="spaceUsed"> |
| | | <el-input v-model="formData.spaceUsed" placeholder="请输入已用空间" /> |
| | | </el-form-item> |
| | | <el-form-item label="可用空间" prop="spaceUsable"> |
| | | <el-input v-model="formData.spaceUsable" placeholder="请输入可用空间" /> |
| | | </el-form-item> |
| | | <el-form-item label="空间使用比例" prop="spaceRatio"> |
| | | <el-input v-model="formData.spaceRatio" placeholder="请输入空间使用比例" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import { MonitorDiskApi, MonitorDiskVO } from '@/api/infra/monitordisk' |
| | | |
| | | /** 磁盘监控日志 表单 */ |
| | | defineOptions({ name: 'MonitorDiskForm' }) |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | | hostName: undefined, |
| | | hostIp: undefined, |
| | | disk: undefined, |
| | | diskName: undefined, |
| | | spaceTotal: undefined, |
| | | spaceUsed: undefined, |
| | | spaceUsable: undefined, |
| | | spaceRatio: undefined, |
| | | }) |
| | | const formRules = reactive({ |
| | | hostName: [{ required: true, message: '主机名称不能为空', trigger: 'blur' }], |
| | | hostIp: [{ required: true, message: '服务器ip不能为空', trigger: 'blur' }], |
| | | }) |
| | | const formRef = ref() // 表单 Ref |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: number) => { |
| | | dialogVisible.value = true |
| | | dialogTitle.value = t('action.' + type) |
| | | formType.value = type |
| | | resetForm() |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | | try { |
| | | formData.value = await MonitorDiskApi.getMonitorDisk(id) |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | await formRef.value.validate() |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | const data = formData.value as unknown as MonitorDiskVO |
| | | if (formType.value === 'create') { |
| | | await MonitorDiskApi.createMonitorDisk(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await MonitorDiskApi.updateMonitorDisk(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | dialogVisible.value = false |
| | | // 发送操作成功的事件 |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | id: undefined, |
| | | hostName: undefined, |
| | | hostIp: undefined, |
| | | disk: undefined, |
| | | diskName: undefined, |
| | | spaceTotal: undefined, |
| | | spaceUsed: undefined, |
| | | spaceUsable: undefined, |
| | | spaceRatio: undefined, |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <ContentWrap> |
| | | <!-- 搜索工作栏 --> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <!-- <el-form-item label="主机名称" prop="hostName">--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="queryParams.hostName"--> |
| | | <!-- placeholder="请输入主机名称"--> |
| | | <!-- clearable--> |
| | | <!-- @keyup.enter="handleQuery"--> |
| | | <!-- class="!w-120px"--> |
| | | <!-- />--> |
| | | <!-- </el-form-item>--> |
| | | <el-form-item label="服务器IP" prop="hostIp"> |
| | | <el-input |
| | | v-model="queryParams.hostIp" |
| | | placeholder="请输入服务器IP" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-120px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="服务名" prop="serverName"> |
| | | <el-input |
| | | v-model="queryParams.serverName" |
| | | placeholder="请输入服务名" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-120px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间" prop="createTime"> |
| | | <el-date-picker |
| | | v-model="queryParams.createTime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetimerange" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" |
| | | class="!w-360px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px"/> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="openForm('create')" |
| | | v-hasPermi="['infra:monitor-mem:create']" |
| | | > |
| | | <Icon icon="ep:plus" class="mr-5px"/> |
| | | 新增 |
| | | </el-button> |
| | | <el-button |
| | | type="success" |
| | | plain |
| | | @click="handleExport" |
| | | :loading="exportLoading" |
| | | v-hasPermi="['infra:monitor-mem:export']" |
| | | > |
| | | <Icon icon="ep:download" class="mr-5px"/> |
| | | 导出 |
| | | </el-button> |
| | | </el-form-item> |
| | | <el-form-item style="float: right"> |
| | | <el-button |
| | | v-if="showType == 'chart'" |
| | | type="warning" |
| | | style="font-weight: bold" |
| | | plain |
| | | @click="switchShow('data')"> |
| | | <Icon icon="fa-solid:th-list" class="mr-5px"/> |
| | | 列表展示 |
| | | </el-button> |
| | | <el-button |
| | | v-if="showType == 'data'" |
| | | type="danger" |
| | | style="font-weight: bold" |
| | | plain |
| | | @click="switchShow('chart')"> |
| | | <Icon icon="fa-solid:chart-pie" class="mr-5px"/> |
| | | 图例展示 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <ContentWrap v-if="showType == 'chart'"> |
| | | <!-- 物理内存折线图 --> |
| | | <el-skeleton :loading="echartsLoading" animated> |
| | | <Echart :height="320" :options="physicalChartOptions"/> |
| | | </el-skeleton> |
| | | <!-- JVM内存折线图 --> |
| | | <el-skeleton :loading="echartsLoading" animated> |
| | | <Echart style="margin-top: 20px" :height="320" :options="JVMChartOptions"/> |
| | | </el-skeleton> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap v-if="showType == 'data'"> |
| | | <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> |
| | | <el-table-column label="主机名称" align="center" prop="hostName"/> |
| | | <el-table-column label="服务器ip" align="center" prop="hostIp"/> |
| | | <el-table-column label="服务名" align="center" prop="serverName" width="120"/> |
| | | <el-table-column label="总内存" align="center" prop="physicalTotal"/> |
| | | <el-table-column label="已用内存" align="center" prop="physicalUsed"/> |
| | | <el-table-column label="空闲内存" align="center" prop="physicalFree"/> |
| | | <el-table-column label="内存使用率" align="center" prop="physicalUsage" width="100"/> |
| | | <el-table-column label="JVM占用内存" align="center" prop="runtimeTotal"/> |
| | | <el-table-column label="JVM最大内存" align="center" prop="runtimeMax"/> |
| | | <el-table-column label="JVM可用内存" align="center" prop="runtimeUsed"/> |
| | | <el-table-column label="JVM空闲内存" align="center" prop="runtimeFree"/> |
| | | <el-table-column label="JVM内存使用率" align="center" prop="runtimeUsage"/> |
| | | <el-table-column |
| | | label="创建时间" |
| | | align="center" |
| | | prop="createTime" |
| | | :formatter="dateFormatter" |
| | | width="180px" |
| | | /> |
| | | <el-table-column label="操作" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | v-hasPermi="['infra:monitor-mem:query']" |
| | | > |
| | | 详情 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | v-hasPermi="['infra:monitor-mem:delete']" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <MonitorMemForm ref="formRef" @success="getList"/> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import {dateFormatter} from '@/utils/formatTime' |
| | | import download from '@/utils/download' |
| | | import {MonitorMemApi, MonitorMemVO} from '@/api/infra/monitormem' |
| | | import MonitorMemForm from './MonitorMemForm.vue' |
| | | import {EChartsOption} from "echarts"; |
| | | import {formatTime} from "@/utils"; |
| | | import {formatDate} from "@vueuse/core"; |
| | | |
| | | /** 内存监控日志 列表 */ |
| | | defineOptions({name: 'MonitorMem'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const list = ref<MonitorMemVO[]>([]) // 列表的数据 |
| | | const total = ref(0) // 列表的总页数 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | hostName: undefined, |
| | | hostIp: undefined, |
| | | serverName: undefined, |
| | | physicalTotal: undefined, |
| | | physicalUsed: undefined, |
| | | physicalFree: undefined, |
| | | physicalUsage: undefined, |
| | | runtimeTotal: undefined, |
| | | runtimeMax: undefined, |
| | | runtimeUsed: undefined, |
| | | runtimeFree: undefined, |
| | | runtimeUsage: undefined, |
| | | createTime: [], |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | const exportLoading = ref(false) // 导出的加载中 |
| | | const echartsLoading = ref(true) // 图表加载中 |
| | | const showType = ref() //展示类型(chart-图例,data-数据) |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await MonitorMemApi.getMonitorMemPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNo = 1 |
| | | if(showType.value == 'data') { |
| | | getList() |
| | | } else { |
| | | getMonitorMemDataList() |
| | | } |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number) => { |
| | | formRef.value.open(type, id) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await MonitorMemApi.deleteMonitorMem(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | /** 堆叠面积图配置 */ |
| | | const physicalChartOptions = reactive<EChartsOption>({ |
| | | title: { |
| | | text: '物理内存折线图' |
| | | }, |
| | | dataset: { |
| | | dimensions: ['createTime', 'physicalTotal', 'physicalUsed', 'physicalFree'], |
| | | source: [] |
| | | }, |
| | | grid: { |
| | | left: 20, |
| | | right: 20, |
| | | bottom: 10, |
| | | top: 70, |
| | | containLabel: true |
| | | }, |
| | | legend: { |
| | | top: 0 |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '总物理内存', type: 'line', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, smooth: false |
| | | }, |
| | | { |
| | | name: '已用物理内存', type: 'line', areaStyle: {}, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, smooth: false |
| | | }, |
| | | { |
| | | name: '剩余物理内存', type: 'line', areaStyle: {}, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, smooth: false |
| | | } |
| | | ], |
| | | toolbox: { |
| | | feature: { |
| | | // 数据区域缩放 |
| | | dataZoom: { |
| | | yAxisIndex: false // Y轴不缩放 |
| | | }, |
| | | brush: { |
| | | type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 |
| | | }, |
| | | saveAsImage: {show: true, name: '物理内存日志图片'} // 保存为图片 |
| | | } |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label: { |
| | | backgroundColor: '#6a7985' |
| | | } |
| | | }, |
| | | padding: [5, 10] |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | axisTick: { |
| | | show: false |
| | | } |
| | | }, |
| | | yAxis: { |
| | | name: "单位(MB)", |
| | | nameTextStyle: { |
| | | color: "#aaa", |
| | | nameLocation: "start", |
| | | }, |
| | | }, |
| | | }) as EChartsOption |
| | | |
| | | /** 堆叠面积图配置 */ |
| | | const JVMChartOptions = reactive<EChartsOption>({ |
| | | title: { |
| | | text: 'JVM内存折线图' |
| | | }, |
| | | dataset: { |
| | | dimensions: ['createTime', 'runtimeMax', 'runtimeTotal', 'runtimeUsed', 'runtimeFree'], |
| | | source: [] |
| | | }, |
| | | grid: { |
| | | left: 20, |
| | | right: 20, |
| | | bottom: 0, |
| | | top: 70, |
| | | containLabel: true |
| | | }, |
| | | legend: { |
| | | top: 0 |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'JVM最大内存', type: 'line', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, smooth: false |
| | | }, |
| | | { |
| | | name: 'JVM占用内存', type: 'line', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, smooth: false |
| | | }, |
| | | { |
| | | name: 'JVM可用内存', type: 'line', areaStyle: {}, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, smooth: false |
| | | }, |
| | | { |
| | | name: 'JVM空闲内存', type: 'line', areaStyle: {}, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, smooth: false |
| | | } |
| | | ], |
| | | toolbox: { |
| | | feature: { |
| | | // 数据区域缩放 |
| | | dataZoom: { |
| | | yAxisIndex: false // Y轴不缩放 |
| | | }, |
| | | brush: { |
| | | type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮 |
| | | }, |
| | | saveAsImage: {show: true, name: 'JVM内存日志图片'} // 保存为图片 |
| | | } |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label: { |
| | | backgroundColor: '#6a7985' |
| | | } |
| | | }, |
| | | padding: [5, 10] |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | axisTick: { |
| | | show: false |
| | | } |
| | | }, |
| | | yAxis: { |
| | | name: "单位(MB)", |
| | | nameTextStyle: { |
| | | color: "#aaa", |
| | | nameLocation: "start", |
| | | }, |
| | | }, |
| | | }) as EChartsOption |
| | | |
| | | /** 查询统计数据列表 */ |
| | | const getMonitorMemDataList = async () => { |
| | | const list = await MonitorMemApi.getMonitorMemList(queryParams) |
| | | for (let item of list) { |
| | | item.createTime = formatTime(item.createTime, 'yyyy-MM-dd HH:mm:ss') |
| | | } |
| | | // 更新 Echarts 数据 |
| | | if (physicalChartOptions.dataset && physicalChartOptions.dataset['source']) { |
| | | physicalChartOptions.dataset['source'] = list |
| | | } |
| | | if (JVMChartOptions.dataset && JVMChartOptions.dataset['source']) { |
| | | JVMChartOptions.dataset['source'] = list |
| | | } |
| | | echartsLoading.value = false |
| | | } |
| | | |
| | | /** 切换展示方式 */ |
| | | const switchShow = (type: String) => { |
| | | showType.value = type |
| | | if(showType.value == 'data') { |
| | | getList() |
| | | } else { |
| | | getMonitorMemDataList() |
| | | } |
| | | } |
| | | |
| | | /** 导出按钮操作 */ |
| | | const handleExport = async () => { |
| | | try { |
| | | // 导出的二次确认 |
| | | await message.exportConfirm() |
| | | // 发起导出 |
| | | exportLoading.value = true |
| | | const data = await MonitorMemApi.exportMonitorMem(queryParams) |
| | | download.excel(data, '内存监控日志.xls') |
| | | } catch { |
| | | } finally { |
| | | exportLoading.value = false |
| | | } |
| | | } |
| | | |
| | | let intervalId; |
| | | /** 初始化 **/ |
| | | onMounted(() => { |
| | | showType.value = 'data'; |
| | | const currentDate = new Date(); |
| | | const previousDate = new Date(currentDate); |
| | | previousDate.setDate(currentDate.getDate() - 1); |
| | | queryParams.createTime[0] = formatDate(previousDate, 'YYYY-MM-DD HH:mm:ss'); |
| | | queryParams.createTime[1] = formatDate(currentDate, 'YYYY-MM-DD HH:mm:ss'); |
| | | intervalId = setInterval(() => { |
| | | if(showType.value == 'data') { |
| | | getList() |
| | | } else { |
| | | getMonitorMemDataList() |
| | | } |
| | | }, 60000); |
| | | }) |
| | | |
| | | onUnmounted(() => { |
| | | clearInterval(intervalId); |
| | | }); |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog :title="dialogTitle" v-model="dialogVisible"> |
| | | <el-form |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="100px" |
| | | v-loading="formLoading" |
| | | > |
| | | <el-form-item label="主机名称" prop="hostName"> |
| | | <el-input v-model="formData.hostName" placeholder="请输入主机名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="服务器ip" prop="hostIp"> |
| | | <el-input v-model="formData.hostIp" placeholder="请输入服务器ip" /> |
| | | </el-form-item> |
| | | <el-form-item label="服务名" prop="serverName"> |
| | | <el-input v-model="formData.serverName" placeholder="请输入服务名" /> |
| | | </el-form-item> |
| | | <el-form-item label="总内存" prop="physicalTotal"> |
| | | <el-input v-model="formData.physicalTotal" placeholder="请输入总物理内存" /> |
| | | </el-form-item> |
| | | <el-form-item label="已用内存" prop="physicalUsed"> |
| | | <el-input v-model="formData.physicalUsed" placeholder="请输入已用物理内存" /> |
| | | </el-form-item> |
| | | <el-form-item label="空闲内存" prop="physicalFree"> |
| | | <el-input v-model="formData.physicalFree" placeholder="请输入空闲内存" /> |
| | | </el-form-item> |
| | | <el-form-item label="内存使用率" prop="physicalUsage"> |
| | | <el-input v-model="formData.physicalUsage" placeholder="请输入物理内存使用率" /> |
| | | </el-form-item> |
| | | <el-form-item label="jvm运行总内存" prop="runtimeTotal"> |
| | | <el-input v-model="formData.runtimeTotal" placeholder="请输入jvm运行总内存" /> |
| | | </el-form-item> |
| | | <el-form-item label="jvm最大内存" prop="runtimeMax"> |
| | | <el-input v-model="formData.runtimeMax" placeholder="请输入jvm最大内存" /> |
| | | </el-form-item> |
| | | <el-form-item label="jvm已用内存" prop="runtimeUsed"> |
| | | <el-input v-model="formData.runtimeUsed" placeholder="请输入jvm已用内存" /> |
| | | </el-form-item> |
| | | <el-form-item label="jvm空闲内存" prop="runtimeFree"> |
| | | <el-input v-model="formData.runtimeFree" placeholder="请输入jvm空闲内存" /> |
| | | </el-form-item> |
| | | <el-form-item label="jvm内存使用率" prop="runtimeUsage"> |
| | | <el-input v-model="formData.runtimeUsage" placeholder="请输入jvm内存使用率" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import { MonitorMemApi, MonitorMemVO } from '@/api/infra/monitormem' |
| | | |
| | | /** 内存监控日志 表单 */ |
| | | defineOptions({ name: 'MonitorMemForm' }) |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | | hostName: undefined, |
| | | hostIp: undefined, |
| | | serverName: undefined, |
| | | physicalTotal: undefined, |
| | | physicalUsed: undefined, |
| | | physicalFree: undefined, |
| | | physicalUsage: undefined, |
| | | runtimeTotal: undefined, |
| | | runtimeMax: undefined, |
| | | runtimeUsed: undefined, |
| | | runtimeFree: undefined, |
| | | runtimeUsage: undefined, |
| | | }) |
| | | const formRules = reactive({ |
| | | hostName: [{ required: true, message: '主机名称不能为空', trigger: 'blur' }], |
| | | hostIp: [{ required: true, message: '服务器ip不能为空', trigger: 'blur' }], |
| | | }) |
| | | const formRef = ref() // 表单 Ref |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: number) => { |
| | | dialogVisible.value = true |
| | | dialogTitle.value = t('action.' + type) |
| | | formType.value = type |
| | | resetForm() |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | | try { |
| | | formData.value = await MonitorMemApi.getMonitorMem(id) |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | await formRef.value.validate() |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | const data = formData.value as unknown as MonitorMemVO |
| | | if (formType.value === 'create') { |
| | | await MonitorMemApi.createMonitorMem(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await MonitorMemApi.updateMonitorMem(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | dialogVisible.value = false |
| | | // 发送操作成功的事件 |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | id: undefined, |
| | | hostName: undefined, |
| | | hostIp: undefined, |
| | | serverName: undefined, |
| | | physicalTotal: undefined, |
| | | physicalUsed: undefined, |
| | | physicalFree: undefined, |
| | | physicalUsage: undefined, |
| | | runtimeTotal: undefined, |
| | | runtimeMax: undefined, |
| | | runtimeUsed: undefined, |
| | | runtimeFree: undefined, |
| | | runtimeUsage: undefined, |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | import MonitorMem from './MonitorMem.vue' |
| | | import MonitorDisk from './MonitorDisk.vue' |
| | | export { MonitorMem, MonitorDisk } |
对比新文件 |
| | |
| | | <template> |
| | | <ContentWrap> |
| | | <el-tabs v-model="activeName"> |
| | | <el-tab-pane label="内存监控日志" name="monitorMem"> |
| | | <monitor-mem ref="memInfoRef" /> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="硬盘监控日志" name="colum"> |
| | | <monitor-disk ref="diskInfoRef" /> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </ContentWrap> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import { MonitorMem, MonitorDisk } from './components' |
| | | |
| | | defineOptions({ name: 'InfraMonitor' }) |
| | | |
| | | const activeName = ref('monitorMem') // Tag 激活的窗口 |
| | | |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="p-16px" style="background-color: #ffffff"> |
| | | <el-header> |
| | | {{title}} |
| | | </el-header> |
| | | <el-main> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="120px" |
| | | > |
| | | <el-divider content-position="left">模型信息</el-divider> |
| | | <el-row :gutter="8"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="模型类型" prop="modelType"> |
| | | <el-radio-group v-model="formData.modelType"> |
| | | <el-radio-button :disabled="actionType == 'edit'" |
| | | v-for="dict in getDictOptions(DICT_TYPE.MODEL_TYPE)" |
| | | :key="dict.label" |
| | | :label="dict.value" |
| | | > |
| | | {{ dict.label }} |
| | | </el-radio-button> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="8"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="模型名称" prop="modelName"> |
| | | <el-input v-model="formData.modelName" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="8"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="模型文件" prop="modelFileName"> |
| | | <el-input disabled v-model="formData.modelFileName" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-upload |
| | | ref="uploadRef" |
| | | v-model:file-list="fileList" |
| | | :show-file-list="false" |
| | | :action="importUrl" |
| | | :auto-upload="true" |
| | | :disabled="uploadLoading" |
| | | v-loading="uploadLoading" |
| | | :before-upload="beforeUpload" |
| | | :headers="uploadHeaders" |
| | | :on-error="submitFormError" |
| | | :on-success="submitFormSuccess" |
| | | accept=".jar" |
| | | > |
| | | <el-tooltip content="上传算法封装.jar文件" placement="top" effect="light"> |
| | | <el-button type="primary"> |
| | | <Icon icon="ep:upload"/> |
| | | 模型上传 |
| | | </el-button> |
| | | </el-tooltip> |
| | | </el-upload> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="8"> |
| | | <el-col :span="6"> |
| | | <el-form-item label="MATLAB平台" prop="matlabPlatform"> |
| | | <el-select v-model="formData.matlabPlatform"> |
| | | <el-option |
| | | v-for="item in getDictOptions(DICT_TYPE.MATLAB_PLATFORM)" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-form-item label="MATLAB版本" prop="matlabVersion"> |
| | | <el-select v-model="formData.matlabVersion"> |
| | | <el-option |
| | | v-for="item in getDictOptions(DICT_TYPE.MATLAB_VERSION)" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input v-model="formData.remark" placeholder="" type="textarea"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-divider content-position="left">模型方法</el-divider> |
| | | <!-- <el-row :gutter="20">--> |
| | | <!-- <el-col :span="4">--> |
| | | <!-- <el-button type="primary" size="small" @click="addRow()" >新增</el-button>--> |
| | | <!-- </el-col>--> |
| | | <!-- </el-row>--> |
| | | <el-table :data="formData.modelMethods" border |
| | | @expand-change="methodExpandChange" :expand-row-keys="methodExpandedRowKeys" :row-key="row => row.id"> |
| | | <el-table-column |
| | | prop="" |
| | | label="全类名" |
| | | align="center" |
| | | width="400"> |
| | | <template #default="scope"> |
| | | <el-input disabled size="small" v-model="scope.row.className" placeholder=""/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="" |
| | | label="方法名" |
| | | align="center" |
| | | width="250"> |
| | | <template #default="scope"> |
| | | <el-input disabled size="small" v-model="scope.row.methodName" placeholder=""/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="" |
| | | label="数据长度" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-input-number disabled size="small" step-strictly v-model="scope.row.dataLength" :min="1" |
| | | :max="50" value-on-clear="min"/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="" |
| | | label="输出长度" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-input-number disabled size="small" step-strictly v-model="scope.row.outLength" :min="1" |
| | | :max="50" value-on-clear="min"/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="方法参数" type="expand" width="100px"> |
| | | <template #default="props"> |
| | | <div class="m-16px"> |
| | | <el-button type="primary" size="small" @click="addSetting(props.row.methodSettings)">新增参数</el-button> |
| | | <el-table :data="props.row.methodSettings" border size="small"> |
| | | <el-table-column align="center" label="参数名称" prop="name"/> |
| | | <el-table-column align="center" label="key" prop="settingKey"/> |
| | | <el-table-column align="center" label="value" prop="settingValue"/> |
| | | <el-table-column align="center" label="参数类型" prop="valueType"/> |
| | | <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | @click="updateSetting(scope.row)" |
| | | key="danger" |
| | | type="primary" |
| | | link |
| | | >修改 |
| | | </el-button> |
| | | <el-button |
| | | @click="deleteSetting(props.row.methodSettings,scope.$index)" |
| | | key="danger" |
| | | type="danger" |
| | | link |
| | | >删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | @click="deleteRow(scope.$index)" |
| | | key="danger" |
| | | type="danger" |
| | | link |
| | | >删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form> |
| | | </el-main> |
| | | <el-footer> |
| | | <div class="flex flex-row justify-end items-center"> |
| | | <el-button type="primary" @click="submitForm">确 定</el-button> |
| | | </div> |
| | | </el-footer> |
| | | </div> |
| | | <SettingForm ref="settingFormRef"/> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import {DICT_TYPE,getDictOptions} from '@/utils/dict'; |
| | | import * as MatlabApi from '@/api/model/matlab/mlModel' |
| | | import {FormRules} from 'element-plus' |
| | | import {getAccessToken, getTenantId} from "@/utils/auth"; |
| | | import SettingForm from './MatlabModelSettingForm.vue' |
| | | import {generateUUID} from "@/utils"; |
| | | |
| | | const {t} = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | const title = ref('') // 弹窗的标题 |
| | | const actionType = ref('') // 操作类型 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const route = useRoute() // 路由 |
| | | const router = useRouter(); |
| | | |
| | | const staticDir = ref(import.meta.env.VITE_STATIC_DIR) |
| | | |
| | | /** settingForm弹窗 */ |
| | | const settingFormRef = ref() |
| | | // 添加setting |
| | | const addSetting = (methodSettings) => { |
| | | settingFormRef.value.open(undefined,methodSettings) |
| | | } |
| | | |
| | | // 修改setting |
| | | const updateSetting = (info) => { |
| | | settingFormRef.value.open(info) |
| | | } |
| | | // 删除setting |
| | | const deleteSetting = (methodSettings,index) => { |
| | | methodSettings.splice(index, 1); |
| | | } |
| | | |
| | | const methodExpandedRowKeys = ref([]) |
| | | const methodExpandChange = async (row: any, expandedRows: any[]) => { |
| | | methodExpandedRowKeys.value = expandedRows.map(e => e.id) |
| | | } |
| | | |
| | | const formData = ref({ |
| | | id: route.params.id, |
| | | modelName: undefined, |
| | | modelFileName: undefined, |
| | | modelFilePath: undefined, |
| | | modelType: 'predict', |
| | | matlabPlatform: undefined, |
| | | matlabVersion: undefined, |
| | | remark: undefined, |
| | | modelMethods: [], |
| | | }) |
| | | |
| | | const formRules = reactive<FormRules>({ |
| | | modelFileName: [ |
| | | {required: true, message: '模型名称不能为空,请上传模型jar文件', trigger: 'blur'} |
| | | ], |
| | | modelName: [ |
| | | {required: true, message: '模型中文名称不能为空', trigger: 'blur'} |
| | | ], |
| | | modelType: [ |
| | | {required: true, message: '模型类型不能为空', trigger: 'blur'} |
| | | ], |
| | | matlabPlatform: [ |
| | | {required: true, message: 'MATLAB平台不能为空', trigger: 'blur'} |
| | | ], |
| | | matlabVersion: [ |
| | | {required: true, message: 'MATLAB版本不能为空', trigger: 'blur'} |
| | | ], |
| | | }) |
| | | |
| | | const formRef = ref() // 表单 Ref |
| | | |
| | | /** 提交表单 */ |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | // 模型方法校验 |
| | | if (formData.value.modelMethods?.length <= 0) { |
| | | message.error('模型方法为空') |
| | | return |
| | | } |
| | | // 模型方法名称校验 |
| | | if (formData.value.modelMethods.some(e => e.methodName === undefined || e.methodName === '' || e.dataLength === undefined || e.dataLength === null)) { |
| | | message.error('存在不合法模型方法名') |
| | | return |
| | | } |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | const data = formData.value |
| | | if (formType.value === 'create') { |
| | | await MatlabApi.create(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await MatlabApi.update(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | // router.push({path:'/model/mpk'}) |
| | | router.back() |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | id: undefined, |
| | | modelFileName: undefined, |
| | | modelName: undefined, |
| | | modelType: 'predict', |
| | | remark: undefined, |
| | | modelMethods: [], |
| | | modelFilePath: undefined |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | |
| | | const handleChange = function () { |
| | | |
| | | } |
| | | |
| | | const addRow = function () { |
| | | formData.value.modelMethods.push({ |
| | | id: generateUUID(), |
| | | className: undefined, |
| | | methodName: undefined, |
| | | dataLength: 1, |
| | | outLength: 1, |
| | | methodSettings: [] |
| | | }) |
| | | } |
| | | const deleteRow = function (index) { |
| | | formData.value.modelMethods.splice(index, 1) |
| | | } |
| | | |
| | | const fileList = ref([]) // 文件列表 |
| | | const importUrl = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/model/matlab/model/upload' |
| | | const uploadLoading = ref(false) // 表单的加载中 |
| | | const uploadHeaders = ref() // 上传 Header 头 |
| | | const beforeUpload = function (file) { |
| | | // 提交请求 |
| | | uploadHeaders.value = { |
| | | Authorization: 'Bearer ' + getAccessToken(), |
| | | 'tenant-id': getTenantId() |
| | | } |
| | | uploadLoading.value = true |
| | | return true; |
| | | } |
| | | const submitFormError = (): void => { |
| | | message.error('上传失败!') |
| | | uploadLoading.value = false |
| | | } |
| | | const submitFormSuccess = (response: any) => { |
| | | if (response.code !== 0) { |
| | | message.error(response.msg) |
| | | uploadLoading.value = false |
| | | return |
| | | } |
| | | const data = response.data; |
| | | formData.value.modelFilePath = data.filePath |
| | | formData.value.modelFileName = data.fileName |
| | | const modelMethods = (data.classInfos || []).flatMap(e => { |
| | | return (e.methodInfos || []).map(m => { |
| | | return { ...m,id: generateUUID(), className: e.className,methodSettings: [] }; |
| | | }); |
| | | }); |
| | | |
| | | formData.value.modelMethods = modelMethods |
| | | message.success('上传成功') |
| | | uploadLoading.value = false |
| | | } |
| | | |
| | | onMounted(async () => { |
| | | const id = formData.value.id; |
| | | const type = id ? 'edit' : 'create' |
| | | actionType.value = type |
| | | title.value = t('action.' + type) |
| | | formType.value = type |
| | | resetForm() |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | | try { |
| | | debugger |
| | | formData.value = await MatlabApi.get(id) |
| | | debugger |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="80px" |
| | | > |
| | | <el-row :gutter="8"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="参数名称" prop="name"> |
| | | <el-input v-model="formData.name" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="参数类型" prop="valueType"> |
| | | <el-select v-model="formData.valueType"> |
| | | <el-option |
| | | v-for="item in getDictOptions(DICT_TYPE.MODEL_METHOD_SETTING_VALUE_TYPE)" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="8"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="key" prop="settingKey"> |
| | | <el-input v-model="formData.settingKey" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="value" prop="settingValue"> |
| | | <el-input v-model="formData.settingValue" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import {DICT_TYPE,getDictOptions} from '@/utils/dict'; |
| | | import {FormRules} from 'element-plus' |
| | | |
| | | |
| | | const {t} = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('参数设置') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formData = ref({ |
| | | settingKey: undefined, |
| | | settingValue: undefined, |
| | | name: undefined, |
| | | valueType: undefined |
| | | }) |
| | | |
| | | |
| | | const formRules = reactive<FormRules>({ |
| | | settingKey: [ |
| | | {required: true, message: 'key不能为空', trigger: 'blur'}, |
| | | ], |
| | | settingValue: [ |
| | | {required: true, message: 'value不能为空', trigger: 'blur'}, |
| | | ], |
| | | name: [ |
| | | {required: true, message: '参数名称不能为空', trigger: 'blur'}, |
| | | ], |
| | | valueType: [ |
| | | {required: true, message: '参数类型不能为空', trigger: 'blur'}, |
| | | ] |
| | | }) |
| | | |
| | | const formRef = ref() // 表单 Ref |
| | | |
| | | let methodSettingsRef = undefined |
| | | let infoRef = undefined |
| | | /** 打开弹窗 */ |
| | | const open = async (info,methodSettings) => { |
| | | dialogVisible.value = true |
| | | resetForm() |
| | | // 修改时,设置数据 |
| | | if (info) { |
| | | infoRef = info |
| | | formLoading.value = true |
| | | try { |
| | | formData.value = {...info} |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | }else { |
| | | methodSettingsRef = methodSettings |
| | | } |
| | | } |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | |
| | | // 数据回调 |
| | | const emit = defineEmits(['addSettingCallback']) |
| | | /** 提交表单 */ |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | if (infoRef) { |
| | | // 修改 |
| | | for (let key in formData.value) { |
| | | infoRef[key] = formData.value[key]; |
| | | } |
| | | infoRef = undefined; |
| | | }else { |
| | | // 新增 |
| | | methodSettingsRef.push({...formData.value}) |
| | | } |
| | | dialogVisible.value = false |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | settingKey: undefined, |
| | | settingValue: undefined, |
| | | name: undefined, |
| | | valueType: undefined, |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle"> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="formData" |
| | | ref="formRef" |
| | | :inline="true" |
| | | :rules="formRules" |
| | | label-width="68px" |
| | | v-loading="formLoading" |
| | | > |
| | | <el-form-item style="width: 100%"> |
| | | <el-divider content-position="left">模型信息</el-divider> |
| | | </el-form-item> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="全类名" style="width: 100%" prop="className"> |
| | | <el-input disabled v-model="formData.className" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="方法名" prop="methodName"> |
| | | <el-select v-model="formData.methodId" @change="methodChange" style="width: 240px"> |
| | | <el-option |
| | | v-for="item in methodList" |
| | | :key="item.id" |
| | | :label="item.className + '.' + item.methodName + '()'" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-divider content-position="left">模型参数信息</el-divider> |
| | | <div style="display:flex;flex-direction: row;align-items: center;margin-bottom: 6px"> |
| | | <el-button tag="a" :href="staticDir + '/template/模型参数导入模板.xlsx'" download="模型参数导入模板.xlsx" style="text-decoration: none;" type="primary" size="small" link>模板下载</el-button> |
| | | <el-upload |
| | | ref="uploadRef" |
| | | v-model:file-list="fileList" |
| | | :show-file-list="false" |
| | | :action="importUrl" |
| | | :auto-upload="true" |
| | | :disabled="formLoading" |
| | | :before-upload="beforeUpload" |
| | | :headers="uploadHeaders" |
| | | :on-error="submitFormError" |
| | | :on-success="submitFormSuccess" |
| | | accept=".xlsx" |
| | | > |
| | | <el-button type="primary" size="small" link>参数导入</el-button> |
| | | </el-upload> |
| | | </div> |
| | | <el-row v-for="(item,index) in datas" :key="index" :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item :label="'参数_' + (index)" required style="width: 100%"> |
| | | <el-input type="textarea" :disabled="true" :rows="3" v-model="datas[index]" placeholder="" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-divider content-position="left">模型设置信息</el-divider> |
| | | <!-- <el-row :gutter="20">--> |
| | | <!-- <el-col :span="4">--> |
| | | <!-- <el-button type="primary" size="small" @click="addRow()">新增</el-button>--> |
| | | <!-- </el-col>--> |
| | | <!-- </el-row>--> |
| | | <el-table :data="formData.modelSettings" border> |
| | | <el-table-column |
| | | prop="" |
| | | label="参数key" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-input size="small" v-model="scope.row.settingKey" :disabled="true" maxlength="50" clearable /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="" |
| | | label="参数名称" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-input size="small" v-model="scope.row.name" :disabled="true" maxlength="50" clearable /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="" |
| | | label="参数value" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-input size="small" v-model="scope.row.settingValue" :disabled="scope.row.settingKey === 'pyFile'" maxlength="50" clearable /> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100">--> |
| | | <!-- <template #default="scope">--> |
| | | <!-- <el-button--> |
| | | <!-- @click="deleteRow(scope.$index)"--> |
| | | <!-- key="danger"--> |
| | | <!-- type="danger"--> |
| | | <!-- :disabled="scope.row.settingKey === 'pyFile'"--> |
| | | <!-- link--> |
| | | <!-- >删除</el-button>--> |
| | | <!-- </template>--> |
| | | <!-- </el-table-column>--> |
| | | </el-table> |
| | | <el-divider content-position="left">模型运行结果</el-divider> |
| | | <el-input v-model="modelRunResult" placeholder="" rows="4" type="textarea" /> |
| | | <div style="display: flex;flex-direction: row;justify-content: end;margin-top: 16px"> |
| | | <el-button :loading="modelRunloading" type="primary" @click="modelRun()">运行</el-button> |
| | | </div> |
| | | </el-form> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as MlModelApi from '@/api/model/matlab/mlModel' |
| | | import {FormRules} from "element-plus"; |
| | | import {getAccessToken, getTenantId} from "@/utils/auth"; |
| | | import download from "@/utils/download"; |
| | | const staticDir = ref(import.meta.env.VITE_STATIC_DIR) |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('模型运行') // 弹窗的标题 |
| | | |
| | | const formData = reactive({ |
| | | modelFileName: '', |
| | | className: '', |
| | | methodName: '', |
| | | methodId: '', |
| | | uuids: [], |
| | | modelSettings: [], |
| | | outLength: 1 |
| | | }) |
| | | |
| | | const datas = ref([]) |
| | | |
| | | // 模型方法下拉列表 |
| | | const methodList = ref([]) |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (row) => { |
| | | dialogVisible.value = true |
| | | formData.modelFileName = row.modelFileName |
| | | const matlabModel = await MlModelApi.get(row.id) |
| | | methodList.value = matlabModel.modelMethods |
| | | formData.className = matlabModel.modelMethods[0].className |
| | | formData.methodId = matlabModel.modelMethods[0].id |
| | | formData.methodName = matlabModel.modelMethods[0].methodName |
| | | formData.outLength = matlabModel.modelMethods[0].outLength |
| | | datas.value = [] |
| | | formData.uuids = []; |
| | | for (let i = 0 ; i < matlabModel.modelMethods[0].dataLength ; i++) { |
| | | datas.value[i] = '[[]]'; |
| | | formData.uuids[i] = ''; |
| | | } |
| | | |
| | | // 回显参数 |
| | | if (matlabModel.modelMethods[0].methodSettings && matlabModel.modelMethods[0].methodSettings.length > 0) { |
| | | formData.modelSettings = matlabModel.modelMethods[0].methodSettings |
| | | } |
| | | |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | const formRules = reactive<FormRules>({ |
| | | methodName: [ |
| | | {required: true, message: '方法名不能为空', trigger: 'blur'} |
| | | ], |
| | | className: [ |
| | | {required: true, message: '全类名不能为空', trigger: 'blur'} |
| | | ] |
| | | }) |
| | | |
| | | const addRow = function () { |
| | | formData.modelSettings.push({ |
| | | settingKey: '', |
| | | settingValue: '' |
| | | }) |
| | | } |
| | | const deleteRow = function (index) { |
| | | formData.modelSettings.splice(index, 1) |
| | | } |
| | | const methodChange = function (value) { |
| | | datas.value = [] |
| | | formData.uuids = []; |
| | | var method = methodList.value.find(e => e.id === value); |
| | | formData.methodName = method.methodName |
| | | formData.className = method.className |
| | | for (let i = 0 ; i < method?.dataLength ; i++) { |
| | | datas.value[i] = '[[]]'; |
| | | formData.uuids[i] = ''; |
| | | } |
| | | // 回显参数 |
| | | if (method.methodSettings && method.methodSettings.length > 0) { |
| | | formData.modelSettings = method.methodSettings |
| | | }else { |
| | | formData.modelSettings = [] |
| | | } |
| | | } |
| | | |
| | | const fileList = ref([]) // 文件列表 |
| | | const importUrl = |
| | | import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/model/matlab/model/importData' |
| | | const formLoading = ref(false) // 表单的加载中 |
| | | const uploadHeaders = ref() // 上传 Header 头 |
| | | /** 上传错误提示 */ |
| | | const submitFormError = (): void => { |
| | | message.error('导入失败,请检查导入文件!') |
| | | formLoading.value = false |
| | | } |
| | | const submitFormSuccess = (response: any) => { |
| | | try { |
| | | if (response.code !== 0) { |
| | | message.error(response.msg) |
| | | return |
| | | } |
| | | const data = response.data; |
| | | if (datas.value.length > data.length) { |
| | | message.error("导入数据长度为" + data.length + ",应≥" + datas.value.length) |
| | | return |
| | | } |
| | | for (let i = 0; i < datas.value.length; i++) { |
| | | datas.value[i] = data[i].data |
| | | formData.uuids[i] = data[i].uuid; |
| | | } |
| | | message.success('导入成功') |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | const beforeUpload = function (file) { |
| | | // 提交请求 |
| | | uploadHeaders.value = { |
| | | Authorization: 'Bearer ' + getAccessToken(), |
| | | 'tenant-id': getTenantId() |
| | | } |
| | | formLoading.value = true |
| | | return true; |
| | | } |
| | | |
| | | // 模型运行结果 |
| | | const modelRunResult = ref('') |
| | | // 模型运行loading |
| | | const modelRunloading = ref(false) |
| | | // 表单 Ref |
| | | const formRef = ref() |
| | | // 运行 |
| | | const modelRun = async () => { |
| | | modelRunResult.value = '' |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | |
| | | |
| | | // 提交请求 |
| | | modelRunloading.value = true |
| | | try { |
| | | const data = { |
| | | ...formData |
| | | } |
| | | |
| | | //处理modelSettings |
| | | // let settingsPredict = {}; |
| | | // data.modelSettings.forEach(e => { |
| | | // settingsPredict[e.settingKey] = e.settingValue; |
| | | // }) |
| | | // data.modelSettings = settingsPredict |
| | | |
| | | let result = await MlModelApi.test(data) |
| | | |
| | | modelRunResult.value = result; |
| | | message.success('运行成功') |
| | | } finally { |
| | | modelRunloading.value = false |
| | | } |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <!-- 搜索工作栏 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | @submit.prevent |
| | | > |
| | | <el-form-item label="模型名称" prop="pyChineseName"> |
| | | <el-input |
| | | v-model="queryParams.modelName" |
| | | placeholder="请输入模型名称" |
| | | clearable |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="模型文件" prop="modelFileName"> |
| | | <el-input |
| | | v-model="queryParams.modelFileName" |
| | | placeholder="请输入模型文件名称" |
| | | clearable |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px"/> |
| | | 重置 |
| | | </el-button> |
| | | <div class="ml-12px"> |
| | | <router-link :to="'/matlab/model/form'"> |
| | | <el-button type="primary" plain v-hasPermi="['ml:model:create']"> |
| | | <Icon icon="ep:plus" class="mr-5px"/>新增</el-button> |
| | | </router-link> |
| | | </div> |
| | | |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="list" |
| | | row-key="id" |
| | | > |
| | | <el-table-column prop="modelName" label="模型名称" header-align="center" align="center" min-width="100" /> |
| | | <el-table-column prop="modelFileName" label="模型文件" header-align="center" align="center" min-width="250"/> |
| | | <el-table-column prop="modelType" label="模型类型" header-align="center" align="center" :formatter="(r,c,v) => getDictLabel(DICT_TYPE.MODEL_TYPE,v)"/> |
| | | <el-table-column prop="matlabPlatform" label="matlab平台" header-align="center" align="center"/> |
| | | <el-table-column prop="matlabVersion" label="matlab版本" header-align="center" align="center"/> |
| | | <!-- <el-table-column prop="remark" label="备注" header-align="center" align="center" min-width="100px"/>--> |
| | | <el-table-column prop="createDate" label="创建时间" header-align="center" align="center" :formatter="dateFormatter" width="180px"/> |
| | | <el-table-column prop="updateDate" label="修改时间" header-align="center" align="center" :formatter="dateFormatter" width="180px"/> |
| | | <el-table-column label="操作" align="center" width="200px"> |
| | | <template #default="scope"> |
| | | <div class="flex items-center justify-center"> |
| | | <router-link :to="'/matlab/model/form/' + scope.row.id"> |
| | | <el-button type="primary" link v-hasPermi="['ml:model:update']"> |
| | | <Icon icon="ep:edit"/>修改 |
| | | </el-button> |
| | | </router-link> |
| | | <el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['ml:model:delete']"> |
| | | <Icon icon="ep:delete"/>删除 |
| | | </el-button> |
| | | <div class="pl-12px"> |
| | | <el-dropdown @command="(command) => handleCommand(command, scope.row)" trigger="click"> |
| | | <el-button type="primary" link> |
| | | <Icon icon="ep:d-arrow-right" /> 更多 |
| | | </el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item |
| | | command="mpkRunDialog" |
| | | > |
| | | 运行 |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | v-model:limit="queryParams.limit" |
| | | v-model:page="queryParams.page" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <MatlabRun ref="matlabRun" /> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import {dateFormatter} from '@/utils/formatTime' |
| | | import * as MlModelApi from '@/api/model/matlab/mlModel' |
| | | import { DICT_TYPE, getDictLabel } from '@/utils/dict' |
| | | import MatlabRun from './MatlabRun.vue' |
| | | |
| | | defineOptions({name: 'MatlabModel'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 字典表格数据 |
| | | const queryParams = reactive({ |
| | | page: 1, |
| | | limit: 10, |
| | | modelName: '', |
| | | modelFileName: '' |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await MlModelApi.getPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 操作分发 */ |
| | | const handleCommand = (command: string, row) => { |
| | | switch (command) { |
| | | case 'mpkRunDialog': |
| | | matlabRunDialog(row) |
| | | break |
| | | default: |
| | | break |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryParams.page = 1 |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await MlModelApi.deleteModel(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | const matlabRun = ref(); |
| | | const matlabRunDialog = (row) => { |
| | | matlabRun.value.open(row); |
| | | } |
| | | |
| | | onActivated((to) => { |
| | | getList() |
| | | }) |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle" width="60%"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="80px" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="10"> |
| | | <el-form-item label="项目名称" prop="projectName"> |
| | | <el-input v-model="formData.projectName" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="10"> |
| | | <el-form-item label="项目编码" prop="projectCode"> |
| | | <el-input v-model="formData.projectCode" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="关联模型" prop="models"> |
| | | <el-transfer style="width: 100%" :props="{key: 'id',label: 'modelFileName'}" :titles="['未选模型', '已选模型']" target-order="unshift" filterable :filter-method="filterMethod" v-model="formData.models" :data="modelList"> |
| | | <template #default="{ option }"> |
| | | <span :title="option.modelFileName + '【' + option.modelName + '】'">{{ option.modelFileName}}</span> |
| | | </template> |
| | | </el-transfer> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as ProjectApi from '@/api/model/matlab/project' |
| | | import * as MlModelApi from '@/api/model/matlab/mlModel' |
| | | import {FormRules} from 'element-plus' |
| | | |
| | | |
| | | const {t} = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | | projectName: undefined, |
| | | projectCode: undefined, |
| | | models: undefined, |
| | | }) |
| | | |
| | | |
| | | const formRules = reactive<FormRules>({ |
| | | projectName: [ |
| | | {required: true, message: '项目名称不能为空', trigger: 'blur'}, |
| | | ], |
| | | projectCode: [ |
| | | {required: true, message: '项目编码不能为空', trigger: 'blur'}, |
| | | ], |
| | | }) |
| | | |
| | | const formRef = ref() // 表单 Ref |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: number) => { |
| | | dialogVisible.value = true |
| | | dialogTitle.value = t('action.' + type) |
| | | formType.value = type |
| | | getModelList(); |
| | | resetForm() |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | | try { |
| | | const data = await ProjectApi.getProject(id) |
| | | data.models = data.models.map(e => e.id) |
| | | formData.value = { |
| | | ...data |
| | | } |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | } |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | const data = { |
| | | ...formData.value |
| | | } |
| | | if (data.models && data.models.length > 0) { |
| | | data.models = data.models.map(e => { |
| | | return {id: e} |
| | | }) |
| | | } |
| | | if (formType.value === 'create') { |
| | | await ProjectApi.createProject(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await ProjectApi.updateProject(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | dialogVisible.value = false |
| | | // 发送操作成功的事件 |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | id: undefined, |
| | | projectName: undefined, |
| | | projectCode: undefined, |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | |
| | | // 所有模型列表 |
| | | const modelList = ref([]) |
| | | const getModelList = async () => { |
| | | modelList.value = await MlModelApi.list({}) |
| | | } |
| | | |
| | | // 模型筛选 |
| | | const filterMethod = function (query, item) { |
| | | return item.modelFileName.toLowerCase().indexOf(query.toLowerCase()) !== -1 |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | :deep(.el-transfer-panel) { |
| | | width: 40%; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle" width="80%"> |
| | | <!-- 搜索工作栏 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="模型名称" prop="modelFileName"> |
| | | <el-input |
| | | v-model="queryParams.modelFileName" |
| | | placeholder="请输入模型名称" |
| | | clearable |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="getList"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="list" |
| | | row-key="id" |
| | | border |
| | | > |
| | | <el-table-column prop="modelName" label="模型中文名称"/> |
| | | <el-table-column prop="modelFileName" label="模型名称"/> |
| | | <el-table-column prop="modelType" label="模型类型" :formatter="(r,c,v) => getDictLabel(DICT_TYPE.MODEL_TYPE,v)"/> |
| | | <el-table-column prop="remark" label="备注" width="300px"/> |
| | | <el-table-column label="模型方法" type="expand" width="100px"> |
| | | <template #default="props"> |
| | | <el-table :data="props.row.modelMethods"> |
| | | <el-table-column align="center" label="全类名" prop="className" /> |
| | | <el-table-column align="center" label="方法名" prop="methodName" /> |
| | | <el-table-column align="center" label="参数长度" prop="dataLength" /> |
| | | <el-table-column align="center" label="输出长度" prop="outLength" /> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | v-model:limit="queryParams.pageSize" |
| | | v-model:page="queryParams.page" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import download from "@/utils/download"; |
| | | import * as projectApi from '@/api/model/matlab/project' |
| | | import { dateFormatter } from '@/utils/formatTime' |
| | | import { DICT_TYPE, getDictLabel } from '@/utils/dict' |
| | | |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('关联模型') // 弹窗的标题 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 字典表格数据 |
| | | const queryParams = reactive({ |
| | | page: 1, |
| | | pageSize: 10, |
| | | projectId: undefined, |
| | | modelFileName: undefined, |
| | | }) |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (projectId: String) => { |
| | | dialogVisible.value = true |
| | | |
| | | queryParams.projectId = projectId; |
| | | getList() |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | let data = await projectApi.getProjectModel(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <!-- 搜索工作栏 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="项目名称" prop="projectName"> |
| | | <el-input |
| | | v-model="queryParams.projectName" |
| | | placeholder="请输入项目名称" |
| | | clearable |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="项目编码" prop="projectCode"> |
| | | <el-input |
| | | v-model="queryParams.projectCode" |
| | | placeholder="请输入项目编码" |
| | | clearable |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px"/> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="openForm('create')" |
| | | v-hasPermi="['mpk:project:create']" |
| | | > |
| | | <Icon icon="ep:plus" class="mr-5px"/> |
| | | 新增 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="list" |
| | | row-key="id" |
| | | > |
| | | <el-table-column prop="projectName" label="项目名称"/> |
| | | <el-table-column prop="projectCode" label="项目编码"/> |
| | | <el-table-column prop="createTime" label="创建时间" :formatter="dateFormatter" width="300px"/> |
| | | <el-table-column label="操作" align="center" width="300px"> |
| | | <template #default="scope"> |
| | | <div class="flex items-center justify-center"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | v-hasPermi="['mpk:project:update']" |
| | | > |
| | | <Icon icon="ep:edit"/> |
| | | 修改 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | v-hasPermi="['mpk:project:delete']" |
| | | > |
| | | <Icon icon="ep:delete"/> |
| | | 删除 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="viewRelevanceModel(scope.row.id)" |
| | | > |
| | | <Icon icon="ep:link"/> |
| | | 查看关联模型 |
| | | </el-button> |
| | | <div class="pl-12px"> |
| | | <el-dropdown @command="(command) => handleCommand(command, scope.row)" |
| | | trigger="click"> |
| | | <el-button type="primary" link> |
| | | <Icon icon="ep:d-arrow-right"/> |
| | | 更多 |
| | | </el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item |
| | | command="publish" |
| | | > |
| | | <el-button link>发布</el-button> |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | v-model:limit="queryParams.limit" |
| | | v-model:page="queryParams.page" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <ProjectForm ref="formRef" @success="getList"/> |
| | | <!-- 关联模型 --> |
| | | <RelevanceModel ref="relevanceModelRef"/> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import {dateFormatter} from '@/utils/formatTime' |
| | | import * as ProjectApi from '@/api/model/matlab/project' |
| | | import ProjectForm from './MatlabProjectForm.vue' |
| | | import RelevanceModel from './MatlabProjectModelDialog.vue' |
| | | |
| | | defineOptions({name: 'MatlabProject'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 字典表格数据 |
| | | const queryParams = reactive({ |
| | | page: 1, |
| | | limit: 10, |
| | | projectName: '', |
| | | projectCode: '' |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await ProjectApi.getPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 操作分发 */ |
| | | const handleCommand = (command: string, row) => { |
| | | switch (command) { |
| | | case 'publish': |
| | | publish(row.id,row.projectName) |
| | | break |
| | | default: |
| | | break |
| | | } |
| | | } |
| | | |
| | | // 发布 |
| | | const publish = async (projectId,projectName) => { |
| | | // 发布的二次确认 |
| | | await message.confirm('确认发布 ' + projectName) |
| | | |
| | | // 发布 |
| | | await ProjectApi.publish({projectId}) |
| | | |
| | | message.success('发布成功'); |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryParams.page = 1 |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number) => { |
| | | formRef.value.open(type, id) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await ProjectApi.deleteProject(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | // 查看关联模型 |
| | | const relevanceModelRef = ref() |
| | | const viewRelevanceModel = (id) => { |
| | | relevanceModelRef.value.open(id) |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | </script> |
| | |
| | | <!-- </el-table-column>--> |
| | | </el-table> |
| | | <el-divider content-position="left">模型运行结果</el-divider> |
| | | <el-button type="primary" size="small" link @click="saveModel" v-if="showSaveModel && formData.methodName === 'train'">下载模型(.miail)</el-button> |
| | | <el-input v-model="modelRunResult" placeholder="" rows="4" type="textarea" /> |
| | | <div style="display: flex;flex-direction: row;justify-content: end;margin-top: 16px"> |
| | | <el-button :loading="modelRunloading" type="primary" @click="modelRun()">运行</el-button> |
| | |
| | | import * as MpkApi from '@/api/model/mpk/mpk' |
| | | import {FormRules} from "element-plus"; |
| | | import {getAccessToken, getTenantId} from "@/utils/auth"; |
| | | import download from "@/utils/download"; |
| | | const staticDir = ref(import.meta.env.VITE_STATIC_DIR) |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | |
| | | return e; |
| | | }) |
| | | } |
| | | |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | |
| | | // 运行 |
| | | const modelRun = async () => { |
| | | modelRunResult.value = '' |
| | | // 校验表单 |
| | | showSaveModel.value = false |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | |
| | | data.model = undefined |
| | | } |
| | | |
| | | modelRunResult.value = await MpkApi.modelRun(data) |
| | | let result = await MpkApi.modelRun(data) |
| | | |
| | | modelRunResult.value = result; |
| | | message.success('运行成功') |
| | | // 训练方法 |
| | | if (formData.methodName === 'train') { |
| | | result = JSON.parse(result); |
| | | // 返回结果正确 |
| | | if (result?.status_code === '100' && result?.models?.model_path) { |
| | | // 有预测方法 |
| | | if (methodList.value.some(e => e.methodName === 'predict')) { |
| | | saveModelParams.modelResult = result |
| | | saveModelParams.model = result?.models |
| | | showSaveModel.value = true |
| | | } |
| | | } |
| | | } |
| | | } finally { |
| | | modelRunloading.value = false |
| | | } |
| | | } |
| | | |
| | | const showSaveModel = ref(false) |
| | | |
| | | const saveModelParams = reactive({ |
| | | pyName: '', |
| | | className: '', |
| | | methodName: '', |
| | | uuids: [], |
| | | modelSettings: [], |
| | | predModelSettings: [], |
| | | hasModel: false, |
| | | model: undefined, |
| | | modelResult: undefined, |
| | | dataLength: undefined, |
| | | resultKey: undefined, |
| | | }) |
| | | |
| | | const saveModel = async () => { |
| | | saveModelParams.className = formData.className |
| | | saveModelParams.pyName = formData.pyName |
| | | saveModelParams.modelSettings = formData.modelSettings |
| | | const predMethod = methodList.value.find(e => e.methodName === 'predict'); |
| | | saveModelParams.methodName = predMethod.methodName |
| | | saveModelParams.resultKey = predMethod.resultKey |
| | | //predModelSettings |
| | | if (predMethod.methodSettings && predMethod.methodSettings.length > 0) { |
| | | saveModelParams.predModelSettings = predMethod.methodSettings.map(e => { |
| | | e.settingValue = e.value; |
| | | return e; |
| | | }) |
| | | } |
| | | saveModelParams.hasModel = predMethod.model === 1 |
| | | |
| | | saveModelParams.dataLength = predMethod.dataLength |
| | | |
| | | const data = await MpkApi.saveModel(saveModelParams) |
| | | download.downloadFile(data, saveModelParams.pyName + '.miail') |
| | | } |
| | | </script> |
| | |
| | | <template> |
| | | <el-row :gutter="20"> |
| | | <!-- 左侧树 --> |
| | | <el-col :span="4" :xs="24"> |
| | | <el-col :span="3" :xs="24"> |
| | | <ContentWrap class="h-1/1"> |
| | | <el-tree |
| | | style="max-width: 600px" |
| | |
| | | /> |
| | | </ContentWrap> |
| | | </el-col> |
| | | <el-col :span="20" :xs="24"> |
| | | <el-col :span="21" :xs="24"> |
| | | <!-- 搜索工作栏 --> |
| | | <ContentWrap> |
| | | <el-form |
| | |
| | | :data="list" |
| | | row-key="id" |
| | | > |
| | | <el-table-column prop="pyChineseName" label="模型名称" header-align="center" align="left" min-width="100" /> |
| | | <el-table-column prop="pyName" label="模型文件" header-align="center" align="left" min-width="300"/> |
| | | <el-table-column prop="pyChineseName" label="模型名称" header-align="center" align="center" min-width="100" /> |
| | | <el-table-column prop="pyName" label="模型文件" header-align="center" align="center" min-width="200"/> |
| | | <el-table-column prop="pyType" label="模型类型" :formatter="(r,c,v) => getDictLabel(DICT_TYPE.MODEL_TYPE,v)"/> |
| | | <el-table-column prop="menuName" label="所属菜单" min-width="120px"/> |
| | | <el-table-column prop="groupName" label="所属组" min-width="120px"/> |
| | | <el-table-column prop="remark" label="备注" min-width="100px"/> |
| | | <el-table-column prop="createDate" label="创建时间" :formatter="dateFormatter" width="180px"/> |
| | | <!-- <el-table-column prop="menuName" label="所属菜单" min-width="120px"/>--> |
| | | <!-- <el-table-column prop="groupName" label="所属组" min-width="120px"/>--> |
| | | <!-- <el-table-column prop="remark" label="备注" min-width="100px"/>--> |
| | | <el-table-column prop="createDate" label="创建时间" align="center" :formatter="dateFormatter" width="180px"/> |
| | | <el-table-column prop="updateDate" label="修改时间" align="center" :formatter="dateFormatter" width="180px"/> |
| | | <el-table-column label="操作" align="center" width="200px"> |
| | | <template #default="scope"> |
| | | <div class="flex items-center justify-center"> |
对比新文件 |
| | |
| | | <template> |
| | | <el-drawer |
| | | v-model="drawer" |
| | | size="60%" |
| | | title="历史详情" |
| | | direction="rtl" |
| | | :before-close="handleClose" |
| | | > |
| | | <!-- 搜索工作栏 --> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="精准误差" prop="inDeviation"> |
| | | <el-input |
| | | v-model="queryParams.inDeviation" |
| | | placeholder="请输入精准误差" |
| | | clearable |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px"/> |
| | | 重置 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <!-- 列表 --> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="list" |
| | | row-key="id" |
| | | > |
| | | <el-table-column prop="inDeviation" label="精准误差"/> |
| | | <el-table-column prop="inAccuracyRate" label="精准度"/> |
| | | <el-table-column prop="outDeviation" label="不可信误差"/> |
| | | <el-table-column prop="outAccuracyRate" label="不可信率"/> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | v-model:limit="queryParams.limit" |
| | | v-model:page="queryParams.page" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </el-drawer> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as MmItemAccuracyHis from '@/api/model/pre/accuracy/his' |
| | | |
| | | defineOptions({name: 'ChartParam'}) |
| | | |
| | | const drawer = ref(false) |
| | | const loading = ref(false) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 字典表格数据 |
| | | const queryParams = reactive({ |
| | | page: 1, |
| | | limit: 10, |
| | | rateId: undefined, |
| | | inDeviation: undefined, |
| | | inAccuracyRate: undefined, |
| | | outDeviation: undefined, |
| | | outAccuracyRate: undefined, |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await MmItemAccuracyHis.getMmItemAccuracyHisPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (rateId?: string) => { |
| | | resetForm() |
| | | drawer.value = true |
| | | queryParams.rateId = rateId |
| | | if (rateId) { |
| | | getList() |
| | | } |
| | | } |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | queryParams.rateId = undefined |
| | | queryParams.inDeviation = undefined |
| | | queryParams.inAccuracyRate = undefined |
| | | queryParams.outDeviation = undefined |
| | | queryParams.outAccuracyRate = undefined |
| | | |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | const handleClose = (done: () => void) => { |
| | | drawer.value = false |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle" width="50%"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="120px" |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="预测项ID" prop="itemId"> |
| | | <el-input v-model="formData.itemId" placeholder="请输入预测项ID"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="输出ID" prop="outId"> |
| | | <el-input v-model="formData.outId" placeholder="请输入输出ID"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="取样长度" prop="sampleLength"> |
| | | <el-input-number v-model="formData.sampleLength" :min="1" clearable controls-position="right" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="值类型" prop="valueType"> |
| | | <el-input v-model="formData.valueType" placeholder="请输入值类型"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="开始统计时间" prop="beginTime"> |
| | | <el-input v-model="formData.beginTime" placeholder="请输入开始统计时间"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="精准误差" prop="inDeviation"> |
| | | <el-input v-model="formData.inDeviation" placeholder="请输入精准误差"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="精准度" prop="inAccuracyRate"> |
| | | <el-input v-model="formData.inAccuracyRate" placeholder="请输入精准度"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="不可信误差" prop="outDeviation"> |
| | | <el-input v-model="formData.outDeviation" placeholder="请输入不可信误差"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="不可信率" prop="outAccuracyRate"> |
| | | <el-input v-model="formData.outAccuracyRate" placeholder="请输入不可信率"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否启用" prop="isEnable"> |
| | | <el-select v-model="formData.isEnable" placeholder="请选择"> |
| | | <el-option |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.COM_IS_INT)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as MmItemAccuracyRate from '@/api/model/pre/accuracy/rate' |
| | | import {DICT_TYPE, getIntDictOptions} from "@/utils/dict"; |
| | | |
| | | defineOptions({name: 'DataMmItemAccuracyRateForm'}) |
| | | |
| | | const {t} = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const formData = ref({ |
| | | id: undefined, |
| | | itemId: undefined, |
| | | outId: undefined, |
| | | sampleLength: undefined, |
| | | valueType: undefined, |
| | | beginTime: undefined, |
| | | inDeviation: undefined, |
| | | inAccuracyRate: undefined, |
| | | outDeviation: undefined, |
| | | outAccuracyRate: undefined, |
| | | isEnable: undefined, |
| | | }) |
| | | const formRules = reactive({ |
| | | itemId: [{required: true, message: '预测项ID不能为空', trigger: 'blur'}], |
| | | outId: [{required: true, message: '输出ID不能为空', trigger: 'blur'}], |
| | | }) |
| | | const formRef = ref() // 表单 Ref |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: number) => { |
| | | dialogVisible.value = true |
| | | dialogTitle.value = t('action.' + type) |
| | | formType.value = type |
| | | resetForm() |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | | try { |
| | | formData.value = await MmItemAccuracyRate.getMmItemAccuracyRate(id) |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | } |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | const data = formData.value as unknown as MmItemAccuracyRate.MmItemAccuracyRateVO |
| | | if (formType.value === 'create') { |
| | | await MmItemAccuracyRate.createMmItemAccuracyRate(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await MmItemAccuracyRate.updateMmItemAccuracyRate(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | dialogVisible.value = false |
| | | // 发送操作成功的事件 |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | id: undefined, |
| | | itemId: undefined, |
| | | outId: undefined, |
| | | sampleLength: undefined, |
| | | valueType: undefined, |
| | | beginTime: undefined, |
| | | inDeviation: undefined, |
| | | inAccuracyRate: undefined, |
| | | outDeviation: undefined, |
| | | outAccuracyRate: undefined, |
| | | isEnable: undefined, |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <!-- 搜索 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="openForm('create')" |
| | | v-hasPermi="['item:accuracy-rate:create']" |
| | | > |
| | | <Icon icon="ep:plus" class="mr-5px" /> |
| | | 新增 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="预测项ID" header-align="center" align="center" min-width="150" prop="itemId" fixed/> |
| | | <el-table-column label="输出ID" header-align="center" align="center" min-width="150" prop="outId" /> |
| | | <el-table-column label="取样长度" header-align="center" align="center" min-width="100" prop="sampleLength" /> |
| | | <el-table-column label="值类型" header-align="center" align="center" min-width="50" prop="valueType" /> |
| | | <el-table-column label="开始统计时间" header-align="center" align="center" min-width="50" prop="beginTime" /> |
| | | <el-table-column label="精准误差" header-align="center" align="center" min-width="50" prop="inDeviation" /> |
| | | <el-table-column label="精准度" header-align="center" align="center" min-width="100" prop="inAccuracyRate" /> |
| | | <el-table-column label="不可信误差" header-align="center" align="center" min-width="100" prop="outDeviation" /> |
| | | <el-table-column label="不可信率" header-align="center" align="center" min-width="100" prop="outAccuracyRate" /> |
| | | <el-table-column label="是否启用" header-align="center" align="center" min-width="100" prop="isEnable" > |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.COM_IS_INT" :value="scope.row.isEnable" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="创建时间" header-align="center" align="center" min-width="100" prop="createTime" /> |
| | | <el-table-column label="操作" align="center" min-width="180" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | v-hasPermi="['item:accuracy-rate:update']" |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | v-hasPermi="['item:accuracy-rate:delete']" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleView(scope.row.id)" |
| | | > |
| | | 查看历史 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <MmItemAccuracyRateForm ref="formRef" @success="getList" /> |
| | | <MmItemAccuracyHis ref="MessageRef" /> |
| | | |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import MmItemAccuracyRateForm from './MmItemAccuracyRateForm.vue' |
| | | import MmItemAccuracyHis from './MmItemAccuracyHisForm.vue' |
| | | import * as MmItemAccuracyRate from '@/api/model/pre/accuracy/rate' |
| | | import {DICT_TYPE} from "@/utils/dict"; |
| | | |
| | | defineOptions({name: 'DataMmItemAccuracyRate'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 列表的数据 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const page = await MmItemAccuracyRate.getMmItemAccuracyRatePage(queryParams) |
| | | list.value = page.list |
| | | total.value = page.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number) => { |
| | | formRef.value.open(type, id) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await MmItemAccuracyRate.deleteMmItemAccuracyRate(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | /** 查看历史按钮操作 */ |
| | | const MessageRef = ref() |
| | | const handleView = (id?: string) => { |
| | | MessageRef.value.open(id) |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle" width="50%"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="120px" |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="消息标题" prop="title"> |
| | | <el-input v-model="formData.title" placeholder="请输入消息标题"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="监控对象" prop="alarmObj"> |
| | | <el-input v-model="formData.alarmObj" placeholder="请输入监控对象"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="预测项" prop="itemId"> |
| | | <el-select |
| | | v-model="formData.itemId" |
| | | filterable |
| | | @change="handleChange(formData.itemId)" |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="(item, index) in predictItemList" |
| | | :key="index" |
| | | :label="item.itemname" |
| | | :value="item.id"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="输出" prop="outId"> |
| | | <el-select |
| | | v-model="formData.outId" |
| | | filterable |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="(item, index) in outPutList" |
| | | :key="index" |
| | | :label="item.tagname" |
| | | :value="item.id"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="比较长度" prop="compLength"> |
| | | <el-input-number v-model="formData.compLength" :min="1" clearable controls-position="right" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="单位" prop="unit"> |
| | | <el-input v-model="formData.unit" placeholder="请输入单位"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="预测上限" prop="upperLimit"> |
| | | <el-input-number v-model="formData.upperLimit" clearable controls-position="right" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="预测下限" prop="lowerLimit"> |
| | | <el-input-number v-model="formData.lowerLimit" clearable controls-position="right" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="累计上限" prop="culUpper"> |
| | | <el-input-number v-model="formData.culUpper" clearable controls-position="right" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="累计下限" prop="culLower"> |
| | | <el-input-number v-model="formData.culLower" clearable controls-position="right" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="转换系数" prop="coefficient"> |
| | | <el-input-number v-model="formData.coefficient" :min="1" clearable controls-position="right" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="调度方案" prop="scheduleId"> |
| | | <el-input v-model="formData.scheduleId" placeholder="请输入调度方案"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否启用" prop="isEnable"> |
| | | <el-select v-model="formData.isEnable" placeholder="请选择"> |
| | | <el-option |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.COM_IS_INT)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="dialogVisible = false">取 消</el-button> |
| | | </template> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as MmPredictAlarmConfig from '@/api/model/pre/alarm/config' |
| | | import {DICT_TYPE, getIntDictOptions} from "@/utils/dict"; |
| | | import * as MmPredictItem from '@/api/model/pre/item' |
| | | |
| | | defineOptions({name: 'DataMmPredictAlarmConfigForm'}) |
| | | |
| | | const {t} = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
| | | const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
| | | const predictItemList = ref([]) |
| | | const outPutList = ref([]) |
| | | const formData = ref({ |
| | | id: undefined, |
| | | title: undefined, |
| | | alarmObj: undefined, |
| | | itemId: undefined, |
| | | itemName: undefined, |
| | | outId: undefined, |
| | | compLength: undefined, |
| | | upperLimit: undefined, |
| | | lowerLimit: undefined, |
| | | culUpper: undefined, |
| | | culLower: undefined, |
| | | unit: undefined, |
| | | coefficient: undefined, |
| | | scheduleId: undefined, |
| | | isEnable: undefined, |
| | | }) |
| | | const formRules = reactive({ |
| | | title: [{required: true, message: '消息标题不能为空', trigger: 'blur'}], |
| | | alarmObj: [{required: true, message: '监控对象不能为空', trigger: 'blur'}], |
| | | itemId: [{required: true, message: '预测项ID不能为空', trigger: 'blur'}], |
| | | outId: [{required: true, message: '输出ID不能为空', trigger: 'blur'}], |
| | | }) |
| | | const formRef = ref() // 表单 Ref |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (type: string, id?: number) => { |
| | | dialogVisible.value = true |
| | | dialogTitle.value = t('action.' + type) |
| | | formType.value = type |
| | | resetForm() |
| | | |
| | | // 获取normal列表 |
| | | predictItemList.value = await MmPredictItem.getMmPredictItemList({ |
| | | status: 1 |
| | | }) |
| | | // 修改时,设置数据 |
| | | if (id) { |
| | | formLoading.value = true |
| | | try { |
| | | formData.value = await MmPredictAlarmConfig.getMmPredictAlarmConfig(id) |
| | | await handleChange(formData.value.itemId) |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | } |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 提交表单 */ |
| | | const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
| | | const submitForm = async () => { |
| | | // 校验表单 |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | | const data = formData.value as unknown as MmPredictAlarmConfig.MmPredictAlarmConfigVO |
| | | if (formType.value === 'create') { |
| | | await MmPredictAlarmConfig.createMmPredictAlarmConfig(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await MmPredictAlarmConfig.updateMmPredictAlarmConfig(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | dialogVisible.value = false |
| | | // 发送操作成功的事件 |
| | | emit('success') |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | |
| | | async function handleChange(itemid) { |
| | | const queryParams = reactive({ |
| | | itemid: itemid, |
| | | }) |
| | | outPutList.value = await MmPredictItem.getMmItemOutputList(queryParams) |
| | | } |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | formData.value = { |
| | | id: undefined, |
| | | title: undefined, |
| | | alarmObj: undefined, |
| | | itemId: undefined, |
| | | outId: undefined, |
| | | compLength: 1, |
| | | upperLimit: undefined, |
| | | lowerLimit: undefined, |
| | | culUpper: undefined, |
| | | culLower: undefined, |
| | | unit: undefined, |
| | | coefficient: 1, |
| | | scheduleId: undefined, |
| | | isEnable: undefined, |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <el-drawer |
| | | v-model="drawer" |
| | | size="60%" |
| | | title="历史详情" |
| | | direction="rtl" |
| | | :before-close="handleClose" |
| | | > |
| | | <!-- 搜索工作栏 --> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="消息标题" prop="title"> |
| | | <el-input |
| | | v-model="queryParams.title" |
| | | placeholder="请输入消息标题" |
| | | clearable |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="监控对象" prop="alarmObj"> |
| | | <el-input |
| | | v-model="queryParams.alarmObj" |
| | | placeholder="请输入监控对象" |
| | | clearable |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px"/> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px"/> |
| | | 重置 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <!-- 列表 --> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="list" |
| | | row-key="id" |
| | | > |
| | | <el-table-column prop="title" label="消息标题" header-align="center" align="left" min-width="150"/> |
| | | <el-table-column prop="content" label="消息内容" header-align="center" align="left" min-width="200"/> |
| | | <el-table-column prop="alarmObj" label="监控对象" align="left" min-width="150"/> |
| | | <el-table-column prop="alarmType" label="预警类型" align="left" min-width="150"/> |
| | | <el-table-column prop="alarmTime" label="预警时间" align="left" min-width="150"/> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | v-model:limit="queryParams.pageSize" |
| | | v-model:page="queryParams.pageNo" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </el-drawer> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as MmPredictAlarmMessage from '@/api/model/pre/alarm/message' |
| | | |
| | | defineOptions({name: 'ChartParam'}) |
| | | |
| | | const drawer = ref(false) |
| | | const loading = ref(false) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 字典表格数据 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | configId: undefined, |
| | | title: undefined, |
| | | content: undefined, |
| | | alarmObj: undefined, |
| | | pointId: undefined, |
| | | itemId: undefined, |
| | | outId: undefined, |
| | | currentValue: undefined, |
| | | outTime: undefined, |
| | | outValue: undefined, |
| | | alarmType: undefined, |
| | | alarmTime: undefined, |
| | | createTime: undefined, |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await MmPredictAlarmMessage.getMmPredictAlarmMessagePage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (configId?: string) => { |
| | | resetForm() |
| | | drawer.value = true |
| | | queryParams.configId = configId |
| | | if (configId) { |
| | | getList() |
| | | } |
| | | } |
| | | defineExpose({open}) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | queryParams.title = undefined |
| | | queryParams.pointId = undefined |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | const handleClose = (done: () => void) => { |
| | | drawer.value = false |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <!-- 搜索 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="名称" prop="title"> |
| | | <el-input |
| | | v-model="queryParams.title" |
| | | placeholder="请输入名称" |
| | | clearable |
| | | @keyup.enter="handleQuery" |
| | | class="!w-240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleQuery"> |
| | | <Icon icon="ep:search" class="mr-5px" /> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <Icon icon="ep:refresh" class="mr-5px" /> |
| | | 重置 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | @click="openForm('create')" |
| | | v-hasPermi="['pre:alarm-config:create']" |
| | | > |
| | | <Icon icon="ep:plus" class="mr-5px" /> |
| | | 新增 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="消息标题" header-align="center" align="left" min-width="150" prop="title" fixed/> |
| | | <el-table-column label="监控对象" header-align="center" align="center" min-width="150" prop="alarmObj" /> |
| | | <el-table-column label="预测项" header-align="center" align="left" min-width="150" prop="itemName" /> |
| | | <el-table-column label="输出" header-align="center" align="center" min-width="150" prop="outName" /> |
| | | <el-table-column label="比较长度" header-align="center" align="center" min-width="100" prop="compLength" /> |
| | | <el-table-column label="预测上限" header-align="center" align="center" min-width="100" prop="upperLimit" /> |
| | | <el-table-column label="预测下限" header-align="center" align="center" min-width="100" prop="lowerLimit" /> |
| | | <el-table-column label="累计上限" header-align="center" align="center" min-width="100" prop="culUpper" /> |
| | | <el-table-column label="累计下限" header-align="center" align="center" min-width="100" prop="culLower" /> |
| | | <el-table-column label="单位" header-align="center" align="center" min-width="100" prop="unit" /> |
| | | <el-table-column label="转换系数" header-align="center" align="center" min-width="100" prop="coefficient" /> |
| | | <el-table-column label="是否启用" header-align="center" align="center" min-width="100" prop="isEnable" > |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.COM_IS_INT" :value="scope.row.isEnable" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" align="center" min-width="160" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openForm('update', scope.row.id)" |
| | | v-hasPermi="['pre:alarm-config:update']" |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row.id)" |
| | | v-hasPermi="['pre:alarm-config:delete']" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="handleView(scope.row.id)" |
| | | > |
| | | 记录 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <MmPredictAlarmConfigForm ref="formRef" @success="getList" /> |
| | | <MmPredictAlarmMessage ref="MessageRef" /> |
| | | |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import MmPredictAlarmConfigForm from './MmPredictAlarmConfigForm.vue' |
| | | import MmPredictAlarmMessage from './MmPredictAlarmMessageForm.vue' |
| | | import * as MmPredictAlarmConfig from '@/api/model/pre/alarm/config' |
| | | import {DICT_TYPE} from "@/utils/dict"; |
| | | |
| | | defineOptions({name: 'DataMmPredictAlarmConfig'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 列表的数据 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | title: undefined, |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const page = await MmPredictAlarmConfig.getMmPredictAlarmConfigPage(queryParams) |
| | | list.value = page.list |
| | | total.value = page.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNo = 1 |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 添加/修改操作 */ |
| | | const formRef = ref() |
| | | const openForm = (type: string, id?: number) => { |
| | | formRef.value.open(type, id) |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await MmPredictAlarmConfig.deleteMmPredictAlarmConfig(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | /** 查看历史按钮操作 */ |
| | | const MessageRef = ref() |
| | | const handleView = (id?: string) => { |
| | | MessageRef.value.open(id) |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | </script> |
| | |
| | | <template> |
| | | <el-card shadow="never" class="aui-card--fill"> |
| | | <div class="mod-his__index"> |
| | | <el-form :inline="true" :model="formData" label-width="80px"> |
| | | <el-form :inline="true" :model="formData" label-width="70px"> |
| | | <el-form-item label="开始时间"> |
| | | <el-date-picker |
| | | v-model="formData.startTime" |
| | |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button-group> |
| | | <el-button type="primary" plain :icon="ArrowLeft" |
| | | <el-button type="primary" plain :icon="DArrowLeft" |
| | | :loading="loading1" @click="leftSearchDataByRange()"/> |
| | | <el-button type="primary" plain :icon="Search" |
| | | :loading="loading1" @click="getList()">查询 |
| | | </el-button> |
| | | <el-button type="primary" plain :icon="ArrowRight" |
| | | <el-button type="primary" plain :icon="DArrowRight" |
| | | :loading="loading1" @click="rightSearchDataByRange()"/> |
| | | </el-button-group> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button-group> |
| | | <el-button type="primary" plain :icon="CaretLeft" |
| | | @click="playChart(true)"/> |
| | | <el-button type="primary" plain :icon="VideoPlay" v-if="!isPlay" |
| | | @click="playHandle('play')"/> |
| | | <el-button type="primary" plain :icon="VideoPause" v-if="isPlay" |
| | | @click="playHandle('pause')"/> |
| | | <el-button type="primary" plain :icon="CaretRight" |
| | | @click="playChart(false)"/> |
| | | </el-button-group> |
| | | </el-form-item> |
| | | |
| | |
| | | </el-form> |
| | | <el-form :inline="true" :model="formData" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-col :span="16"> |
| | | <el-form-item label="数据类型"> |
| | | <el-checkbox-group v-model="formData.chartCheck" @change="changeChartCheck"> |
| | | <el-checkbox v-for="item in formData.chartOptions" :label="item" |
| | |
| | | import {getYMDHMS} from "@/utils/dateUtil" |
| | | import * as McsApi from '@/api/model/mcs' |
| | | import * as echarts from "echarts"; |
| | | import {Search, ArrowLeft, ArrowRight,} from '@element-plus/icons-vue' |
| | | import {Search, DArrowLeft, DArrowRight, VideoPlay, VideoPause, CaretLeft, CaretRight} from '@element-plus/icons-vue' |
| | | |
| | | defineOptions({name: 'AnalysisformData'}) |
| | | |
| | |
| | | currentStamp60: '', |
| | | predictStamp: '', |
| | | chartCheck: ['T+L', '真实值'], |
| | | chartOptions: ['T+N', 'T+L', '当时', '真实值', '调整值'], |
| | | chartOptions: ['T+N', 'T+L', '当时', '真实值', '调整值', '预测累计', '真实累计'], |
| | | checkedItemData: [], |
| | | backItem: '', |
| | | backValue: 0, |
| | |
| | | queryStep: 2, |
| | | isMultipleYRadio: '单坐标轴', |
| | | isMultipleY: false, |
| | | predictFreq: 3, |
| | | predictFreq: 2, |
| | | }) |
| | | const calRateFormRef = ref() |
| | | const calRateForm = ref({ |
| | | calItem: undefined, |
| | | IN_DEVIATION: 0, |
| | | OUT_DEVIATION: 0, |
| | | IN_DEVIATION: 10, |
| | | OUT_DEVIATION: 50, |
| | | IN_ACCURACY_RATE: 0, |
| | | OUT_ACCURACY_RATE: 0, |
| | | itemAvg: 0, |
| | |
| | | const itemDataObject = ref() |
| | | const timer = ref() |
| | | let myChart = null; |
| | | const isPlay = ref(false) |
| | | |
| | | const formRules = reactive({ |
| | | calItem: [{required: true, message: '预测项不能为空', trigger: 'blur'}], |
| | |
| | | }) |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | const getList = async (isClear = true) => { |
| | | loading1.value = true |
| | | try { |
| | | if (!formData.value.chartCheck) { |
| | |
| | | formData.value.endTime = data.endTime |
| | | |
| | | let xAxisData = data.categories; |
| | | let defaultYAxis = [ |
| | | { |
| | | type: 'value', |
| | | name: "累计值", |
| | | splitLine: {show: false}, |
| | | axisLine: {show: true}, |
| | | position: 'right' |
| | | }, |
| | | { |
| | | type: 'value', |
| | | name: "", |
| | | splitLine: {show: false}, |
| | | axisLine: {show: true}, |
| | | position: 'left' |
| | | } |
| | | ]; |
| | | let yAxisData = []; |
| | | let offset = 0; |
| | | let yAxisIndex = 0; |
| | |
| | | }, |
| | | }); |
| | | itemDataObject.value = {} |
| | | yAxisData.push({ |
| | | type: 'value', |
| | | name: "累计值", |
| | | position: 'right', |
| | | splitLine: { |
| | | show: false |
| | | }, |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: {} |
| | | }, |
| | | axisLabel: { |
| | | formatter: '{value}' |
| | | } |
| | | }) |
| | | for (let i = 0; i < data.dataViewList.length; i++) { |
| | | let dataView = data.dataViewList[i] |
| | | itemDataObject.value[dataView.outId] = dataView; |
| | | let maxValue = dataView.maxValue; |
| | | let minValue = dataView.minValue; |
| | | yAxisIndex = formData.value.isMultipleY ? i : 0; |
| | | yAxisIndex = (formData.value.isMultipleY ? i : 0) + 1; |
| | | let yMax = maxValue; |
| | | if (maxValue < 0) { |
| | | maxValue = 1; |
| | |
| | | type: 'line', |
| | | yAxisIndex: yAxisIndex, |
| | | showSymbol: false, |
| | | smooth: true, |
| | | smooth: false, |
| | | lineStyle: { |
| | | width: 2 |
| | | } |
| | |
| | | } |
| | | if (chartCheckArray.indexOf('T+N') !== -1) { |
| | | let legendName = dataView.resultName + '(T+N)'; |
| | | legendData.push(legendName); |
| | | seriesData.push({ |
| | | name: legendName, |
| | | data: dataView.preDataN || [], |
| | | type: 'line', |
| | | yAxisIndex: yAxisIndex, |
| | | showSymbol: false, |
| | | smooth: true, |
| | | smooth: false, |
| | | lineStyle: { |
| | | width: 2 |
| | | } |
| | |
| | | showSymbol: false, |
| | | connectNulls: true, |
| | | yAxisIndex: yAxisIndex, |
| | | smooth: true, |
| | | smooth: false, |
| | | lineStyle: { |
| | | width: 2 |
| | | } |
| | |
| | | data: dataView.curData || [], |
| | | type: 'line', |
| | | yAxisIndex: yAxisIndex, |
| | | showSymbol: false, |
| | | smooth: true, |
| | | showSymbol: true, |
| | | smooth: false, |
| | | lineStyle: { |
| | | width: 2 |
| | | width: 3 |
| | | } |
| | | }); |
| | | } |
| | |
| | | yAxisIndex: yAxisIndex, |
| | | showSymbol: false, |
| | | connectNulls: true, |
| | | smooth: true, |
| | | smooth: false, |
| | | lineStyle: { |
| | | width: 2, |
| | | type: 'dashed' |
| | | } |
| | | }); |
| | | } |
| | | |
| | | if (chartCheckArray.indexOf('预测累计') !== -1) { |
| | | let legendName = dataView.resultName + '(预测累计)'; |
| | | legendData.push(legendName); |
| | | let seriesLeiJiData = [] |
| | | if (dataView.cumulantPreData) { |
| | | seriesLeiJiData = dataView.cumulantPreData |
| | | } |
| | | seriesData.push({ |
| | | name: legendName, |
| | | data: seriesLeiJiData, |
| | | type: 'line', |
| | | yAxisIndex: 0, |
| | | showSymbol: false, |
| | | connectNulls: true, |
| | | smooth: false, |
| | | lineStyle: { |
| | | width: 2, |
| | | type: 'dashed' |
| | | } |
| | | }); |
| | | } |
| | | |
| | | if (chartCheckArray.indexOf('真实累计') !== -1) { |
| | | let legendName = dataView.resultName + '(真实累计)'; |
| | | legendData.push(legendName); |
| | | let seriesLeiJiData = [] |
| | | if (dataView.cumulantRealData) { |
| | | seriesLeiJiData = dataView.cumulantRealData |
| | | } |
| | | seriesData.push({ |
| | | name: legendName, |
| | | data: seriesLeiJiData, |
| | | type: 'line', |
| | | yAxisIndex: 0, |
| | | showSymbol: false, |
| | | connectNulls: true, |
| | | smooth: false, |
| | | lineStyle: { |
| | | width: 2, |
| | | type: 'dashed' |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | myChart = echarts.init(dataAnalysisChart.value); |
| | | let option = { |
| | | title: { |
| | |
| | | boundaryGap: false, |
| | | data: xAxisData |
| | | }, |
| | | yAxis: formData.value.isMultipleY ? yAxisData : { |
| | | type: 'value', |
| | | splitLine: {show: false}, |
| | | axisLine: {show: true} |
| | | }, |
| | | yAxis: formData.value.isMultipleY ? yAxisData : defaultYAxis, |
| | | dataZoom: [ |
| | | { |
| | | type: 'inside', |
| | |
| | | ], |
| | | series: seriesData |
| | | } |
| | | myChart.clear() |
| | | if (isClear) { |
| | | myChart.clear() |
| | | } |
| | | myChart.setOption(option) |
| | | } finally { |
| | | loading1.value = false |
| | | } |
| | | |
| | | calItemBaseVale() |
| | | } |
| | | |
| | | onMounted(() => { |
| | |
| | | treeData.value = await McsApi.getPredictItemTree() |
| | | } |
| | | |
| | | function changeChartCheck(value) { |
| | | getList(true) |
| | | } |
| | | |
| | | function onChangeMultipleY() { |
| | | getList(true) |
| | | } |
| | | |
| | | function playChart(isBack = false) { |
| | | let mins = isBack ? formData.value.predictFreq * -1 : formData.value.predictFreq |
| | | let startTime = formData.value.startTime; |
| | | let endTime = formData.value.endTime; |
| | | let predictTime = formData.value.predictTime; |
| | | if (predictTime) { |
| | | predictTime = getYMDHMS(new Date(predictTime).getTime() + 1000 * 60 * mins); |
| | | formData.value.predictTime = predictTime; |
| | | } |
| | | if (startTime) { |
| | | startTime = getYMDHMS(new Date(startTime).getTime() + 1000 * 60 * mins); |
| | | formData.value.startTime = startTime; |
| | | } |
| | | if (endTime) { |
| | | endTime = getYMDHMS(new Date(endTime).getTime() + 1000 * 60 * mins); |
| | | formData.value.endTime = endTime; |
| | | } |
| | | getList(false); |
| | | } |
| | | |
| | | function playHandle(type) { |
| | | isPlay.value = 'play' === type |
| | | let doPlay = setInterval(function () { |
| | | if (isPlay.value) { |
| | | playChart() |
| | | } else { |
| | | clearInterval(doPlay); |
| | | } |
| | | if (new Date().getTime() - new Date(formData.value.predictTime).getTime() < 1000 * 60 ) { |
| | | isPlay.value = false |
| | | clearInterval(doPlay); |
| | | } |
| | | }, 1000) |
| | | } |
| | | |
| | | function leftSearchDataByRange() { |
| | | let mins = getRangeMins(); |
| | | let startTime = formData.value.startTime; |
| | | let endTime = formData.value.endTime; |
| | | let predictTime = formData.value.predictTime; |
| | | if (predictTime) { |
| | | predictTime = getYMDHMS(new Date(predictTime) - 1000 * 60 * mins); |
| | | predictTime = getYMDHMS(new Date(predictTime).getTime() - 1000 * 60 * mins); |
| | | formData.value.predictTime = predictTime; |
| | | } |
| | | if (startTime) { |
| | | startTime = getYMDHMS(new Date(startTime) - 1000 * 60 * mins); |
| | | startTime = getYMDHMS(new Date(startTime).getTime() - 1000 * 60 * mins); |
| | | formData.value.startTime = startTime; |
| | | } |
| | | if (endTime) { |
| | | endTime = getYMDHMS(new Date(endTime) - 1000 * 60 * mins); |
| | | endTime = getYMDHMS(new Date(endTime).getTime() - 1000 * 60 * mins); |
| | | formData.value.endTime = endTime; |
| | | } |
| | | getList(); |
| | | getList(false); |
| | | } |
| | | |
| | | function getRangeMins() { |
| | |
| | | function onCheckTree(data, checked, indeterminate) { |
| | | formData.value.checkedItemData = []; |
| | | if (checked.checkedNodes) { |
| | | formData.value.checkedItemData = [...checked.checkedNodes] |
| | | let cns = [...checked.checkedNodes] |
| | | for (let i = 0; i < cns.length; i++) { |
| | | if (cns[i].id.indexOf('-') !== -1) { |
| | | continue |
| | | } |
| | | formData.value.checkedItemData.push(cns[i]) |
| | | } |
| | | } |
| | | debounce(getList, 1000); |
| | | } |
| | |
| | | calRateForm.value.itemAvg = dataView.hisAvg; |
| | | calRateForm.value.realCumulant = dataView.hisCumulant; |
| | | } |
| | | calAccuracyRate() |
| | | } |
| | | |
| | | function calAccuracyRate() { |
| | | this.$refs['calRateForm'].validate((valid) => { |
| | | if (!valid) { |
| | | return false |
| | | } |
| | | let dataView = itemDataObject[calRateForm.value.calItem] |
| | | let seriesReaData = dataView.realData; |
| | | let seriesPreData = dataView.preDataL; |
| | | if (seriesReaData == null || seriesPreData == null || |
| | | seriesReaData.length === 0 || seriesPreData.length === 0) { |
| | | loading2.value = false; |
| | | return; |
| | | } |
| | | let predictValueMap = {}; |
| | | seriesPreData.forEach(function (item) { |
| | | predictValueMap[item[0]] = item[1]; |
| | | }) |
| | | let pointValueMap = {}; |
| | | seriesReaData.forEach(function (item) { |
| | | pointValueMap[item[0]] = item[1]; |
| | | }) |
| | | let inDeviation = Number(calRateForm.value.IN_DEVIATION); |
| | | let outDeviation = Number(calRateForm.value.OUT_DEVIATION); |
| | | if (inDeviation === 0 && outDeviation === 0) { |
| | | loading2.value = false; |
| | | return; |
| | | } |
| | | let inDeviationCount = 0; |
| | | let outDeviationCount = 0; |
| | | let totalCount = 0; |
| | | for (let key in predictValueMap) { |
| | | let predictValue = predictValueMap[key]; |
| | | let pointValue = pointValueMap[key]; |
| | | if (pointValue == null || "" === pointValue || predictValue == null || "" === predictValue) { |
| | | continue; |
| | | } |
| | | let deviationAbs = (predictValue - pointValue) >= 0 ? (predictValue - pointValue) : (predictValue - pointValue) * -1; |
| | | if (deviationAbs < inDeviation) { |
| | | inDeviationCount = inDeviationCount + 1; |
| | | } |
| | | if (deviationAbs > outDeviation) { |
| | | outDeviationCount = outDeviationCount + 1; |
| | | } |
| | | totalCount = totalCount + 1; |
| | | } |
| | | const valid = calRateFormRef.value.validate() |
| | | if (!valid) return |
| | | |
| | | let rateIn = (inDeviationCount / totalCount * 100).toFixed(2); |
| | | let rateOut = (outDeviationCount / totalCount * 100).toFixed(2); |
| | | calRateForm.value.IN_ACCURACY_RATE = Number(rateIn); |
| | | calRateForm.value.OUT_ACCURACY_RATE = Number(rateOut); |
| | | let dataView = itemDataObject.value[calRateForm.value.calItem] |
| | | let seriesReaData = dataView.realData; |
| | | let seriesPreData = dataView.preDataL; |
| | | if (seriesReaData == null || seriesPreData == null || |
| | | seriesReaData.length === 0 || seriesPreData.length === 0) { |
| | | loading2.value = false; |
| | | return; |
| | | } |
| | | let predictValueMap = {}; |
| | | seriesPreData.forEach(function (item) { |
| | | predictValueMap[item[0]] = item[1]; |
| | | }) |
| | | let pointValueMap = {}; |
| | | seriesReaData.forEach(function (item) { |
| | | pointValueMap[item[0]] = item[1]; |
| | | }) |
| | | let inDeviation = Number(calRateForm.value.IN_DEVIATION); |
| | | let outDeviation = Number(calRateForm.value.OUT_DEVIATION); |
| | | if (inDeviation === 0 && outDeviation === 0) { |
| | | loading2.value = false; |
| | | return; |
| | | } |
| | | let inDeviationCount = 0; |
| | | let outDeviationCount = 0; |
| | | let totalCount = 0; |
| | | for (let key in predictValueMap) { |
| | | let predictValue = predictValueMap[key]; |
| | | let pointValue = pointValueMap[key]; |
| | | if (pointValue == null || "" === pointValue || predictValue == null || "" === predictValue) { |
| | | continue; |
| | | } |
| | | let deviationAbs = (predictValue - pointValue) >= 0 ? (predictValue - pointValue) : (predictValue - pointValue) * -1; |
| | | if (deviationAbs < inDeviation) { |
| | | inDeviationCount = inDeviationCount + 1; |
| | | } |
| | | if (deviationAbs > outDeviation) { |
| | | outDeviationCount = outDeviationCount + 1; |
| | | } |
| | | totalCount = totalCount + 1; |
| | | } |
| | | |
| | | let rateIn = (inDeviationCount / totalCount * 100).toFixed(2); |
| | | let rateOut = (outDeviationCount / totalCount * 100).toFixed(2); |
| | | calRateForm.value.IN_ACCURACY_RATE = Number(rateIn); |
| | | calRateForm.value.OUT_ACCURACY_RATE = Number(rateOut); |
| | | loading2.value = false; |
| | | } |
| | | |
| | | function rightSearchDataByRange() { |
| | |
| | | let endTime = formData.value.endTime; |
| | | let predictTime = formData.value.predictTime; |
| | | if (predictTime) { |
| | | predictTime = getYMDHMS(new Date(predictTime) - 0 + 1000 * 60 * mins); |
| | | predictTime = getYMDHMS(new Date(predictTime).getTime() + 1000 * 60 * mins); |
| | | formData.value.predictTime = predictTime; |
| | | } |
| | | if (startTime) { |
| | | startTime = getYMDHMS(new Date(startTime) - 0 + 1000 * 60 * mins); |
| | | startTime = getYMDHMS(new Date(startTime).getTime() + 1000 * 60 * mins); |
| | | formData.value.startTime = startTime; |
| | | } |
| | | if (endTime) { |
| | | endTime = getYMDHMS(new Date(endTime) - 0 + 1000 * 60 * mins); |
| | | endTime = getYMDHMS(new Date(endTime).getTime() + 1000 * 60 * mins); |
| | | formData.value.endTime = endTime; |
| | | } |
| | | getList(); |
| | | getList(false); |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | |
| | | currentStamp60: '', |
| | | predictStamp: '', |
| | | chartCheck: ['T+L', '真实值'], |
| | | chartOptions: ['T+N', 'T+L', '当时', '真实值', '调整值'], |
| | | chartOptions: ['T+N', 'T+L', '当时', '真实值', '调整值', '预测累计', '真实累计'], |
| | | checkedItemData: [], |
| | | backItem: '', |
| | | backValue: 0, |
| | |
| | | queryStep: 2, |
| | | isMultipleYRadio: '单坐标轴', |
| | | isMultipleY: false, |
| | | predictFreq: 3, |
| | | predictFreq: 2, |
| | | } |
| | | calRateForm.value = { |
| | | calItem: undefined, |
| | | IN_DEVIATION: 0, |
| | | OUT_DEVIATION: 0, |
| | | IN_DEVIATION: 10, |
| | | OUT_DEVIATION: 50, |
| | | IN_ACCURACY_RATE: 0, |
| | | OUT_ACCURACY_RATE: 0, |
| | | itemAvg: 0, |
| | |
| | | }, |
| | | }, |
| | | }) |
| | | //累计点 |
| | | if(viewData.cumulantRealData) { |
| | | legendData.push(key + "累计:" + '真实值') |
| | | seriesData.push({ |
| | | name: key + "累计:" + '真实值', |
| | | type: "line", |
| | | data: viewData.cumulantRealData, |
| | | showSymbol: false, |
| | | smooth: false, |
| | | lineStyle: { |
| | | normal: { |
| | | width: 1, |
| | | }, |
| | | }, |
| | | yAxisIndex: 1 |
| | | }) |
| | | } |
| | | if(viewData.cumulantPreData) { |
| | | legendData.push(key + "累计:" + '预测值') |
| | | seriesData.push({ |
| | | name: key + "累计:" + '预测值', |
| | | type: "line", |
| | | data: viewData.cumulantPreData, |
| | | showSymbol: false, |
| | | smooth: false, |
| | | lineStyle: { |
| | | normal: { |
| | | width: 1, |
| | | }, |
| | | }, |
| | | yAxisIndex: 1 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | |
| | | boundaryGap: false, |
| | | data: data.categories, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | }, |
| | | yAxis: [ |
| | | { |
| | | type: "value", |
| | | name: '预测值/真实值' |
| | | }, |
| | | { |
| | | type: "value", |
| | | splitLine: { |
| | | show: false |
| | | }, |
| | | name: '累计值' |
| | | } |
| | | ], |
| | | dataZoom: [ |
| | | { |
| | | type: "inside", |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle" width="60%"> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle" width="75%"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-if="dataForm.itemtypename === 'MergeItem'"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="预测长度" prop="mmPredictItem.predictlength"> |
| | | <el-input |
| | | @change="clearExpressionList" |
| | | v-model="dataForm.mmPredictItem.predictlength" placeholder="预测长度" |
| | | maxlength="5"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="真实数据点"> |
| | | <el-select |
| | | v-model="dataForm.pointId" |
| | | filterable |
| | | clearable |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="item in pointList" |
| | | :key="item.id" |
| | | :label="item.pointName" |
| | | :value="item.id"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <div v-if="dataForm.itemtypename === 'MergeItem'"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="预测长度" prop="mmPredictItem.predictlength"> |
| | | <el-input |
| | | v-model="dataForm.mmPredictItem.predictlength" placeholder="预测长度" |
| | | maxlength="5"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="真实数据点"> |
| | | <el-select |
| | | v-model="dataForm.pointId" |
| | | filterable |
| | | clearable |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="item in pointList" |
| | | :key="item.id" |
| | | :label="item.pointName" |
| | | :value="item.id"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-divider content-position="left">累计配置</el-divider> |
| | | <el-row> |
| | | <el-col :span="6"> |
| | | <el-form-item label="是否累计" prop="iscumulant"> |
| | | <el-select v-model="dataForm.iscumulant" placeholder="请选择" @change="(value) => iscumulantChange(dataForm)"> |
| | | <el-option |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.COM_IS_INT)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-form-item label="累计除数" prop="cumuldivisor"> |
| | | <el-input-number v-model="dataForm.cumuldivisor" style="width: 100%" :disabled="dataForm.iscumulant !== 1" |
| | | :min="1" :max="60" |
| | | :controls="false"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="累计测点"> |
| | | <el-select |
| | | v-model="dataForm.cumulpoint" :disabled="dataForm.iscumulant !== 1" |
| | | filterable |
| | | clearable |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="item in pointList.filter(e => e.pointType === 'CUMULATE')" |
| | | :key="item.id" |
| | | :label="item.pointName" |
| | | :value="item.id"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <el-divider content-position="left" v-if="dataForm.itemtypename === 'NormalItem'">模型信息 |
| | | </el-divider> |
| | | <el-row :gutter="8" v-if="dataForm.itemtypename === 'NormalItem'"> |
| | |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="是否累计" align="center" width="150px"> |
| | | <template #default="scope"> |
| | | <el-select v-model="scope.row.iscumulant" placeholder="请选择" @change="(value) => iscumulantChange(scope.row)"> |
| | | <el-option |
| | | v-for="dict in getIntDictOptions(DICT_TYPE.COM_IS_INT)" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="累计除数" align="center" width="100px"> |
| | | <template #default="scope"> |
| | | <el-input-number v-model="scope.row.cumuldivisor" style="width: 100%" |
| | | :min="1" :max="60" :disabled="scope.row.iscumulant !== 1" |
| | | :controls="false"/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="累计数据点" align="center"> |
| | | <template #default="scope"> |
| | | <el-select |
| | | v-model="scope.row.cumulpoint" |
| | | :disabled="scope.row.iscumulant !== 1" |
| | | filterable |
| | | clearable |
| | | placeholder="请选择"> |
| | | <el-option |
| | | v-for="item in pointList.filter(e => e.pointType === 'CUMULATE')" |
| | | :key="item.id" |
| | | :label="item.pointName" |
| | | :value="item.id"/> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="" label="操作" width="80" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | |
| | | v-model="scope.row.point" |
| | | placeholder="请选择" |
| | | filterable |
| | | :no-data-text="'无数据(预测长度:' + dataForm.mmPredictItem.predictlength + ';管网:' + moduleList.find(e => e.id === dataForm.dmModuleItem.moduleid)?.modulename + ')'" |
| | | :no-data-text="'无数据(管网:' + moduleList.find(e => e.id === dataForm.dmModuleItem.moduleid)?.modulename + ')'" |
| | | @change="changeNormalItemSelect" |
| | | style="width: 100%"> |
| | | <el-option-group |
| | | v-for="group in modelparamListMap['NormalItem'].filter(e => e.predictlength == dataForm.mmPredictItem.predictlength && e.moduleid === dataForm.dmModuleItem.moduleid)" |
| | | v-for="group in modelparamListMap['NormalItem'].filter(e => e.moduleid === dataForm.dmModuleItem.moduleid)" |
| | | :key="group.value" |
| | | :label="group.label" |
| | | > |
| | |
| | | import * as DaPoint from '@/api/data/da/point' |
| | | import {useUpload} from '@/api/model/pre/item' |
| | | import * as ScheduleModelApi from '@/api/model/sche/model' |
| | | import {getPointSimpleList} from "@/api/data/da/point"; |
| | | |
| | | const {uploadUrl, httpRequest} = useUpload() |
| | | |
| | |
| | | predictphase: undefined, |
| | | workchecked: 0, |
| | | unittransfactor: undefined, |
| | | saveindex: undefined |
| | | saveindex: undefined, |
| | | }, |
| | | dmModuleItem: { |
| | | id: undefined, |
| | |
| | | }, |
| | | mmModelArithSettingsList: [], |
| | | mmModelParamList: [], |
| | | pointId: undefined |
| | | pointId: undefined, |
| | | iscumulant: 0, |
| | | cumuldivisor: undefined, |
| | | cumulpoint: undefined, |
| | | }) |
| | | const formRules = reactive({ |
| | | 'mmPredictItem.itemname': [{required: true, message: '预测项名不能为空', trigger: 'blur'}], |
| | |
| | | trigger: 'blur' |
| | | }], |
| | | 'mmPredictItem.status': [{required: true, message: '是否启用不能为空', trigger: 'blur'}], |
| | | 'iscumulant': [{required: true, message: '是否累计不能为空', trigger: 'blur'}], |
| | | 'dmModuleItem.moduleid': [{required: true, message: '管网不能为空', trigger: 'blur'}], |
| | | 'dmModuleItem.itemorder': [{required: true, message: '排序不能为空', trigger: 'blur'}], |
| | | 'mmPredictItem.predictlength': [{required: true, message: '预测长度不能为空', trigger: 'blur'}], |
| | |
| | | mpkProjectList.value = await ProjectApi.list() |
| | | |
| | | // 获取数据点列表 |
| | | pointNoList.value = await DaPoint.getPointList(queryParams) |
| | | pointNoList.value = await DaPoint.getPointSimpleList(queryParams) |
| | | if (pointNoList.value.length > 0) { |
| | | pointList.value = [] |
| | | pointNoList.value.forEach(function (value) { |
| | |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | //校验累计配置 |
| | | if (dataForm.value.iscumulant === 1) { |
| | | if (dataForm.value.cumuldivisor == undefined) { |
| | | message.error("累计除数不为空") |
| | | return |
| | | } |
| | | } |
| | | //校验模型输出 |
| | | if (dataForm.value.itemtypename === 'NormalItem') { |
| | | if (dataForm.value.mmItemOutputList == undefined || dataForm.value.mmItemOutputList.length <= 0) { |
| | |
| | | return |
| | | } |
| | | |
| | | let flag = false |
| | | dataForm.value.mmItemOutputList.forEach(e => { |
| | | if (e.resultstr == undefined || e.resultstr === '' || e.resultType == undefined || e.resultType === '' || (e.resultType === 2 && (e.resultIndex == undefined || e.resultIndex === ''))) { |
| | | message.error("模型输出数据异常") |
| | | flag = true |
| | | return |
| | | if (e.resultstr == undefined || e.resultstr === '' || e.resultType == undefined || e.resultType === '' |
| | | || (e.resultType === 2 && (e.resultIndex == undefined || e.resultIndex === '')) |
| | | || (e.iscumulant === 1 && e.cumuldivisor == undefined) |
| | | ) { |
| | | message.error("输出数据异常") |
| | | throw new Error('输出数据异常'); |
| | | } |
| | | }) |
| | | if (flag) return |
| | | |
| | | //校验模型输入 |
| | | dataForm.value.mmModelParamList.forEach(e => { |
| | | if (e.modelparamid == undefined || e.modelparamid == '') { |
| | | message.error("输入数据异常") |
| | | throw new Error('输入数据异常'); |
| | | } |
| | | // ind_ascii类型输出的序号必须是1,且所在端口序号最大为1(一个ind_ascii类型输入独占一个端口) |
| | | if (e.modelparamtype === 'IND_ASCII') { |
| | | if (e.modelparamorder != 1 || dataForm.value.mmModelParamList.filter(p => p.modelparamportorder === e.modelparamportorder).length != 1) { |
| | | message.error("输入数据异常:IND_ASCII类型输入独占一个端口") |
| | | throw new Error('输入数据异常:IND_ASCII类型输入独占一个端口'); |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | if (dataForm.value.itemtypename === 'MergeItem') { |
| | | if (expressionList.value == undefined || expressionList.value.length <= 1) { |
| | |
| | | |
| | | let flag = false |
| | | expressionList.value.forEach((e,index) => { |
| | | if (e.point == undefined || e.point === '' || e.operator == undefined || (e.operator === '' && index != expressionList.value.length - 1)) { |
| | | if (e.point == undefined || e.point === '' || ((e.operator == undefined || e.operator === '') && index != expressionList.value.length - 1)) { |
| | | message.error("表达式数据异常") |
| | | flag = true |
| | | return |
| | |
| | | }) |
| | | if (flag) return |
| | | } |
| | | |
| | | |
| | | // 提交请求 |
| | | formLoading.value = true |
| | |
| | | row.resultIndex = 0 |
| | | } |
| | | } |
| | | function iscumulantChange(row) { |
| | | row.cumuldivisor = undefined |
| | | row.cumulpoint = undefined |
| | | } |
| | | |
| | | function orderRow(rows) { |
| | | let modelparamorder = 0 |
| | |
| | | predictphase: '', |
| | | workchecked: 0, |
| | | unittransfactor: '', |
| | | saveindex: '' |
| | | saveindex: '', |
| | | }, |
| | | dmModuleItem: { |
| | | id: '', |
| | |
| | | itemid: '', |
| | | expression: '', |
| | | num: '' |
| | | } |
| | | }, |
| | | iscumulant: 0, |
| | | cumuldivisor: undefined, |
| | | cumulpoint: '', |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | |
| | | width="100" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.modelparamportorder" maxlength="5" clearable :disabled="true" |
| | | <el-input v-model="scope.row.modelparamportorder" maxlength="5" clearable |
| | | style="width:100%; hight:100%"/> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | import { CommonStatusEnum } from '@/utils/constants' |
| | | import * as MpkApi from "@/api/model/mpk/mpk"; |
| | | import {generateUUID} from "@/utils"; |
| | | import { ElMessage,ElMessageBox } from 'element-plus' |
| | | import { Refresh } from '@element-plus/icons-vue' |
| | | |
| | | defineOptions({ name: 'ScheduleModelForm' }) |
| | | |
| | |
| | | resultStrId: undefined, |
| | | invocation: undefined, |
| | | status: CommonStatusEnum.ENABLE, |
| | | paramList: [], |
| | | paramList: [{ |
| | | modelparamportorder: 1 + '', |
| | | modelparamorder: '1', |
| | | modelparamtype: '', |
| | | modelparamid: '', |
| | | datalength: 0 |
| | | }], |
| | | settingList: [], |
| | | modelOut: [] |
| | | }) |
| | |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | //校验模型输入 |
| | | formData.value.paramList.forEach(e => { |
| | | if (e.modelparamid == undefined || e.modelparamid == '') { |
| | | message.error("输入数据异常") |
| | | throw new Error('输入数据异常'); |
| | | } |
| | | // ind_ascii类型输出的序号必须是1,且所在端口序号最大为1(一个ind_ascii类型输入独占一个端口) |
| | | if (e.modelparamtype === 'IND_ASCII') { |
| | | if (e.modelparamorder != 1 || formData.value.paramList.filter(p => p.modelparamportorder === e.modelparamportorder).length != 1) { |
| | | message.error("输入数据异常:IND_ASCII类型输入独占一个端口") |
| | | throw new Error('输入数据异常:IND_ASCII类型输入独占一个端口'); |
| | | } |
| | | } |
| | | }) |
| | | |
| | | // 提交请求 |
| | | formLoading.value = true |
| | | try { |
| | |
| | | resultStrId: undefined, |
| | | invocation: undefined, |
| | | status: CommonStatusEnum.ENABLE, |
| | | paramList: [], |
| | | paramList: [{ |
| | | modelparamportorder: 1 + '', |
| | | modelparamorder: '1', |
| | | modelparamtype: '', |
| | | modelparamid: '', |
| | | datalength: 0 |
| | | }], |
| | | settingList: [], |
| | | modelOut: [] |
| | | } |
| | |
| | | const changeModel = async () => { |
| | | // 校验 |
| | | if (model.value && model.value.length > 0) { |
| | | const modelInfo = model.value[0] |
| | | const methodInfo = model.value[1] |
| | | formData.value.modelName = modelInfo.pyChineseName |
| | | formData.value.className = modelInfo.pkgName + '.impl.' + modelInfo.pyName + 'Impl'; |
| | | formData.value.methodName = methodInfo.methodName |
| | | formData.value.portLength = methodInfo.dataLength |
| | | // 参数构造 |
| | | let paramStructure = [] |
| | | for (let i = 0; i < methodInfo.dataLength; i++) { |
| | | paramStructure.push('[[D') |
| | | } |
| | | if (methodInfo.model === 1) { |
| | | paramStructure.push('java.util.HashMap') |
| | | } |
| | | ElMessageBox.confirm( |
| | | '是否更新输入参数?', |
| | | '提示', |
| | | {confirmButtonText: '是', cancelButtonText: '否', type: 'success',icon: markRaw(Refresh),closeOnClickModal:false,closeOnPressEscape:false} |
| | | ).then(() => { |
| | | relevanceModel(true) |
| | | }).catch(() => { |
| | | relevanceModel(false) |
| | | }) |
| | | }else { |
| | | message.error("请先选择模型") |
| | | } |
| | | } |
| | | |
| | | function relevanceModel(refreshParam) { |
| | | const modelInfo = model.value[0] |
| | | const methodInfo = model.value[1] |
| | | formData.value.modelName = modelInfo.pyChineseName |
| | | formData.value.className = modelInfo.pkgName + '.impl.' + modelInfo.pyName + 'Impl'; |
| | | formData.value.methodName = methodInfo.methodName |
| | | formData.value.portLength = methodInfo.dataLength |
| | | // 参数构造 |
| | | let paramStructure = [] |
| | | for (let i = 0; i < methodInfo.dataLength; i++) { |
| | | paramStructure.push('[[D') |
| | | } |
| | | if (methodInfo.model === 1) { |
| | | paramStructure.push('java.util.HashMap') |
| | | formData.value.paramStructure = paramStructure.join(',') |
| | | formData.value.modelPath = modelInfo.pyModule |
| | | } |
| | | paramStructure.push('java.util.HashMap') |
| | | formData.value.paramStructure = paramStructure.join(',') |
| | | formData.value.modelPath = modelInfo.pyModule |
| | | if (refreshParam) { |
| | | // 输入参数 |
| | | let paramList = [] |
| | | for (let i = 0; i < methodInfo.dataLength; i++) { |
| | |
| | | datalength: 0 |
| | | }) |
| | | } |
| | | |
| | | formData.value.paramList = paramList |
| | | // 设置参数 |
| | | let settingList = [] |
| | | methodInfo.methodSettings.forEach(e => { |
| | | settingList.push({ |
| | | key: e.settingKey, |
| | | value: e.value, |
| | | valuetype: e.valueType, |
| | | name: e.name |
| | | }) |
| | | }) |
| | | formData.value.settingList = settingList |
| | | modelPopover.value.hide() |
| | | }else { |
| | | message.error("请先选择模型") |
| | | } |
| | | // 设置参数 |
| | | let settingList = [] |
| | | methodInfo.methodSettings.forEach(e => { |
| | | settingList.push({ |
| | | key: e.settingKey, |
| | | value: e.value, |
| | | valuetype: e.valueType, |
| | | name: e.name |
| | | }) |
| | | }) |
| | | formData.value.settingList = settingList |
| | | modelPopover.value.hide() |
| | | } |
| | | |
| | | function changeModelparamtype(row) { |
| | |
| | | </ContentWrap> |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table v-loading="loading" :data="list" max-height="300px"> |
| | | <el-table-column |
| | | prop="scheduleTime" |
| | | label="调度时间" |
| | |
| | | <el-descriptions-item label="浏览器"> |
| | | {{ detailData.userAgent }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="登陆结果"> |
| | | <el-descriptions-item label="登录结果"> |
| | | <dict-tag :type="DICT_TYPE.SYSTEM_LOGIN_RESULT" :value="detailData.result" /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="登录日期"> |
| | |
| | | plain |
| | | @click="handleExport" |
| | | :loading="exportLoading" |
| | | v-hasPermi="['infra:login-log:export']" |
| | | v-hasPermi="['system:login-log:export']" |
| | | > |
| | | <Icon icon="ep:download" class="mr-5px" /> 导出 |
| | | </el-button> |
| | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="日志编号" align="center" prop="id" /> |
| | | <el-table-column label="操作类型" align="center" prop="logType"> |
| | | <el-table-column label="日志编号" align="center" prop="id" width="100" /> |
| | | <el-table-column label="操作类型" align="center" prop="logType" width="100"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.SYSTEM_LOGIN_TYPE" :value="scope.row.logType" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="用户名称" align="center" prop="username" width="180" /> |
| | | <el-table-column label="登录地址" align="center" prop="userIp" width="180" /> |
| | | <el-table-column label="浏览器" align="center" prop="userAgent" /> |
| | | <el-table-column label="登陆结果" align="center" prop="result"> |
| | | <el-table-column label="浏览器" align="center" prop="userAgent" :show-overflow-tooltip="true"/> |
| | | <el-table-column label="登录结果" align="center" prop="result" width="100"> |
| | | <template #default="scope"> |
| | | <dict-tag :type="DICT_TYPE.SYSTEM_LOGIN_RESULT" :value="scope.row.result" /> |
| | | </template> |
| | |
| | | width="180" |
| | | :formatter="dateFormatter" |
| | | /> |
| | | <el-table-column label="操作" align="center"> |
| | | <el-table-column label="操作" align="center" width="80"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="openDetail(scope.row)" |
| | | v-hasPermi="['infra:login-log:query']" |
| | | v-hasPermi="['system:login-log:query']" |
| | | > |
| | | 详情 |
| | | </el-button> |
| | |
| | | plain |
| | | @click="handleExport" |
| | | :loading="exportLoading" |
| | | v-hasPermi="['infra:operate-log:export']" |
| | | v-hasPermi="['system:operate-log:export']" |
| | | > |
| | | <Icon icon="ep:download" class="mr-5px" /> 导出 |
| | | </el-button> |
| | |
| | | link |
| | | type="primary" |
| | | @click="openDetail(scope.row)" |
| | | v-hasPermi="['infra:operate-log:query']" |
| | | v-hasPermi="['system:operate-log:query']" |
| | | > |
| | | 详情 |
| | | </el-button> |