26 changed files with 1123 additions and 25 deletions
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
@ -0,0 +1,52 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { Card, List } from 'ant-design-vue' |
||||
|
import { dynamicInfoItems } from './data' |
||||
|
import { Icon } from '@/components/Icon' |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
data: { |
||||
|
type: Object, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}) |
||||
|
const ListItem = List.Item |
||||
|
const ListItemMeta = List.Item.Meta |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<Card id="www" :title="props.data.Header" v-bind="$attrs" class-name="spcard"> |
||||
|
<template #extra> |
||||
|
<a-button type="link"> |
||||
|
更多 |
||||
|
</a-button> |
||||
|
</template> |
||||
|
<List item-layout="horizontal" :data-source="props.data.Content"> |
||||
|
<template #renderItem="{ item }"> |
||||
|
<ListItem> |
||||
|
<ListItemMeta> |
||||
|
<template #description> |
||||
|
{{ item.StartTime }} {{ item.Duration }} |
||||
|
</template> |
||||
|
<!-- eslint-disable-next-line --> |
||||
|
<!-- <template #title> {{ item.Text }} <span v-html="item.desc"> </span> </template> --> |
||||
|
<template #title> |
||||
|
{{ item.Text }} |
||||
|
</template> |
||||
|
|
||||
|
<!-- <template #avatar> |
||||
|
<Icon :icon="item.avatar" :size="30" /> |
||||
|
</template> --> |
||||
|
</ListItemMeta> |
||||
|
</ListItem> |
||||
|
</template> |
||||
|
</List> |
||||
|
</Card> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
::v-deep(.ant-card-body) { |
||||
|
height:80%; |
||||
|
padding:10px; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,69 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { Card, Comment, List, ListItem } from 'ant-design-vue' |
||||
|
|
||||
|
import dayjs from 'dayjs' |
||||
|
import { DislikeFilled, DislikeOutlined, LikeFilled, LikeOutlined } from '@ant-design/icons-vue' |
||||
|
import { ref } from 'vue' |
||||
|
import relativeTime from 'dayjs/plugin/relativeTime' |
||||
|
import { navItems } from './data' |
||||
|
import { Icon } from '@/components/Icon' |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
data: { |
||||
|
type: Object, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}) |
||||
|
dayjs.extend(relativeTime) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<Card :title="props.data.Header" v-bind="$attrs"> |
||||
|
<template #extra> |
||||
|
<a-button type="link"> |
||||
|
{{ props.data.Content.length }} 条指导建议 |
||||
|
</a-button> |
||||
|
</template> |
||||
|
<List |
||||
|
class="comment-list" |
||||
|
item-layout="horizontal" |
||||
|
:data-source="props.data.Content" |
||||
|
> |
||||
|
<template #renderItem="{ item }"> |
||||
|
<ListItem> |
||||
|
<Comment> |
||||
|
<template #author> |
||||
|
<a>{{ item.FaultDesc }}</a> |
||||
|
</template> |
||||
|
<template #content> |
||||
|
<p> |
||||
|
{{ item.Guide }} |
||||
|
</p> |
||||
|
</template> |
||||
|
<template #datetime> |
||||
|
<a-tooltip :title="dayjs().format('YYYY-MM-DD HH:mm:ss')"> |
||||
|
<span>{{ dayjs().fromNow() }}</span> |
||||
|
</a-tooltip> |
||||
|
</template> |
||||
|
</Comment> |
||||
|
</ListItem> |
||||
|
</template> |
||||
|
</List> |
||||
|
</Card> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
::v-deep(.ant-card-body) { |
||||
|
height:80%; |
||||
|
padding:5px; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
|
||||
|
::v-deep(.ant-list-item) { |
||||
|
padding:5px; |
||||
|
} |
||||
|
|
||||
|
::v-deep(.ant-list-header) { |
||||
|
padding:5px |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,39 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { Card } from 'ant-design-vue' |
||||
|
import { BasicTable, useTable } from '@/components/Table' |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
data: { |
||||
|
type: Object, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}) |
||||
|
|
||||
|
const [registerTable] = useTable({ |
||||
|
dataSource: props.data.Content, |
||||
|
rowKey: 'id', |
||||
|
size: 'small', |
||||
|
immediate: false, |
||||
|
columns: props.data.Columns, |
||||
|
useSearchForm: false, |
||||
|
showTableSetting: false, |
||||
|
showIndexColumn: false, |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<Card :title="props.data.Header" v-bind="$attrs"> |
||||
|
<!-- <template #extra> |
||||
|
<a-button type="link"> |
||||
|
更多 |
||||
|
</a-button> |
||||
|
</template> --> |
||||
|
<BasicTable @register="registerTable" /> |
||||
|
</Card> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
::v-deep(.ant-card-body) { |
||||
|
padding:5px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,49 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { Card, CardGrid } from 'ant-design-vue' |
||||
|
import { groupItems } from './data' |
||||
|
import { Icon } from '@/components/Icon' |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
data: { |
||||
|
type: Object, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<Card :title="props.data.Header" v-bind="$attrs"> |
||||
|
<template #extra> |
||||
|
<a-button type="link"> |
||||
|
更多 |
||||
|
</a-button> |
||||
|
</template> |
||||
|
|
||||
|
<CardGrid v-for="item in props.data.Content" :key="item.Point" class="!h-1/3 !w-full !md:w-1/2"> |
||||
|
<!-- <Icon :icon="item.icon" :color="item.color" size="30" /> --> |
||||
|
<div class="text-center text-lg"> |
||||
|
{{ item.Point }} |
||||
|
</div> |
||||
|
|
||||
|
<div class="text-secondary mt-2 h-10 flex"> |
||||
|
{{ item.FaultDesc }} |
||||
|
</div> |
||||
|
<!-- <div class="text-secondary flex justify-between"> |
||||
|
<span>{{ item.group }}</span> |
||||
|
<span>{{ item.date }}</span> |
||||
|
</div> --> |
||||
|
</CardGrid> |
||||
|
</Card> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped> |
||||
|
::v-deep(.ant-card-grid) { |
||||
|
padding:15px; |
||||
|
} |
||||
|
|
||||
|
::v-deep(.ant-card-body) { |
||||
|
height:80%; |
||||
|
overflow-y: auto; |
||||
|
|
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,16 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { Card, CardGrid } from 'ant-design-vue' |
||||
|
import { navItems } from './data' |
||||
|
import { Icon } from '@/components/Icon' |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<Card title="快捷导航"> |
||||
|
<CardGrid v-for="item in navItems" :key="item.title"> |
||||
|
<span class="flex flex-col items-center"> |
||||
|
<Icon :icon="item.icon" :color="item.color" size="20" /> |
||||
|
<span class="text-md mt-2 truncate">{{ item.title }}</span> |
||||
|
</span> |
||||
|
</CardGrid> |
||||
|
</Card> |
||||
|
</template> |
||||
@ -0,0 +1,91 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import type { Ref } from 'vue' |
||||
|
import { ref, watch } from 'vue' |
||||
|
import { Card } from 'ant-design-vue' |
||||
|
import { useECharts } from '@/hooks/web/useECharts' |
||||
|
import { propTypes } from '@/utils/propTypes' |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
loading: Boolean, |
||||
|
width: propTypes.string.def('100%'), |
||||
|
height: propTypes.string.def('400px'), |
||||
|
}) |
||||
|
|
||||
|
const chartRef = ref<HTMLDivElement | null>(null) |
||||
|
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>) |
||||
|
watch( |
||||
|
() => props.loading, |
||||
|
() => { |
||||
|
if (props.loading) |
||||
|
return |
||||
|
|
||||
|
setOptions({ |
||||
|
legend: { |
||||
|
bottom: 0, |
||||
|
data: ['Visits', 'Sales'], |
||||
|
}, |
||||
|
tooltip: {}, |
||||
|
radar: { |
||||
|
radius: '60%', |
||||
|
splitNumber: 8, |
||||
|
indicator: [ |
||||
|
{ |
||||
|
name: '2017', |
||||
|
}, |
||||
|
{ |
||||
|
name: '2017', |
||||
|
}, |
||||
|
{ |
||||
|
name: '2018', |
||||
|
}, |
||||
|
{ |
||||
|
name: '2019', |
||||
|
}, |
||||
|
{ |
||||
|
name: '2020', |
||||
|
}, |
||||
|
{ |
||||
|
name: '2021', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
series: [ |
||||
|
{ |
||||
|
type: 'radar', |
||||
|
symbolSize: 0, |
||||
|
areaStyle: { |
||||
|
shadowBlur: 0, |
||||
|
shadowColor: 'rgba(0,0,0,.2)', |
||||
|
shadowOffsetX: 0, |
||||
|
shadowOffsetY: 10, |
||||
|
opacity: 1, |
||||
|
}, |
||||
|
data: [ |
||||
|
{ |
||||
|
value: [90, 50, 86, 40, 50, 20], |
||||
|
name: 'Visits', |
||||
|
itemStyle: { |
||||
|
color: '#b6a2de', |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
value: [70, 75, 70, 76, 20, 85], |
||||
|
name: 'Sales', |
||||
|
itemStyle: { |
||||
|
color: '#67e0e3', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
], |
||||
|
}) |
||||
|
}, |
||||
|
{ immediate: true }, |
||||
|
) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<Card title="销售统计" :loading="loading"> |
||||
|
<div ref="chartRef" :style="{ width, height }" /> |
||||
|
</Card> |
||||
|
</template> |
||||
@ -0,0 +1,36 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
const props = defineProps({ |
||||
|
data: { |
||||
|
type: Object, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<div> |
||||
|
<!-- <Avatar :src="userinfo.user.avatar || headerImg" :size="72" class="!mx-auto !block" /> --> |
||||
|
<div class="mt-2 md:mt-0"> |
||||
|
<h1 class="text-center text-lg md:text-2xl"> |
||||
|
<!-- 早安, {{ userinfo.user.nickname }}, 开始您一天的工作吧! --> |
||||
|
{{ props.data.title }} |
||||
|
</h1> |
||||
|
<!-- <span class="text-secondary"> 今日晴,20℃ - 32℃! </span> --> |
||||
|
</div> |
||||
|
<!-- <div class="mt-4 flex flex-1 justify-end md:mt-0"> |
||||
|
<div class="flex flex-col justify-center text-right"> |
||||
|
<span class="text-secondary"> 待办 </span> |
||||
|
<span class="text-2xl">2/10</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="mx-12 flex flex-col justify-center text-right md:mx-16"> |
||||
|
<span class="text-secondary"> 项目 </span> |
||||
|
<span class="text-2xl">8</span> |
||||
|
</div> |
||||
|
<div class="mr-4 flex flex-col justify-center text-right md:mr-10"> |
||||
|
<span class="text-secondary"> 团队 </span> |
||||
|
<span class="text-2xl">300</span> |
||||
|
</div> |
||||
|
</div> --> |
||||
|
</div> |
||||
|
</template> |
||||
@ -0,0 +1,156 @@ |
|||||
|
interface GroupItem { |
||||
|
title: string |
||||
|
icon: string |
||||
|
color: string |
||||
|
desc: string |
||||
|
date: string |
||||
|
group: string |
||||
|
} |
||||
|
|
||||
|
interface NavItem { |
||||
|
title: string |
||||
|
icon: string |
||||
|
color: string |
||||
|
} |
||||
|
|
||||
|
interface DynamicInfoItem { |
||||
|
avatar: string |
||||
|
name: string |
||||
|
date: string |
||||
|
desc: string |
||||
|
} |
||||
|
|
||||
|
export const navItems: NavItem[] = [ |
||||
|
{ |
||||
|
title: '首页', |
||||
|
icon: 'ion:home-outline', |
||||
|
color: '#1fdaca', |
||||
|
}, |
||||
|
{ |
||||
|
title: '仪表盘', |
||||
|
icon: 'ion:grid-outline', |
||||
|
color: '#bf0c2c', |
||||
|
}, |
||||
|
{ |
||||
|
title: '组件', |
||||
|
icon: 'ion:layers-outline', |
||||
|
color: '#e18525', |
||||
|
}, |
||||
|
{ |
||||
|
title: '系统管理', |
||||
|
icon: 'ion:settings-outline', |
||||
|
color: '#3fb27f', |
||||
|
}, |
||||
|
{ |
||||
|
title: '权限管理', |
||||
|
icon: 'ion:key-outline', |
||||
|
color: '#4daf1bc9', |
||||
|
}, |
||||
|
{ |
||||
|
title: '图表', |
||||
|
icon: 'ion:bar-chart-outline', |
||||
|
color: '#00d8ff', |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
export const dynamicInfoItems: DynamicInfoItem[] = [ |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-1|svg', |
||||
|
name: '威廉', |
||||
|
date: '刚刚', |
||||
|
desc: '在 <a>开源组</a> 创建了项目 <a>Vue</a>', |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-2|svg', |
||||
|
name: '艾文', |
||||
|
date: '1个小时前', |
||||
|
desc: '关注了 <a>威廉</a> ', |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-3|svg', |
||||
|
name: '克里斯', |
||||
|
date: '1天前', |
||||
|
desc: '发布了 <a>个人动态</a> ', |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-4|svg', |
||||
|
name: 'XingyuV', |
||||
|
date: '2天前', |
||||
|
desc: '发表文章 <a>如何编写一个Vite插件</a> ', |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-5|svg', |
||||
|
name: '皮特', |
||||
|
date: '3天前', |
||||
|
desc: '回复了 <a>杰克</a> 的问题 <a>如何进行项目优化?</a>', |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-6|svg', |
||||
|
name: '杰克', |
||||
|
date: '1周前', |
||||
|
desc: '关闭了问题 <a>如何运行项目</a> ', |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-1|svg', |
||||
|
name: '威廉', |
||||
|
date: '1周前', |
||||
|
desc: '发布了 <a>个人动态</a> ', |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-1|svg', |
||||
|
name: '威廉', |
||||
|
date: '2021-04-01 20:00', |
||||
|
desc: '推送了代码到 <a>Github</a>', |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
export const groupItems: GroupItem[] = [ |
||||
|
{ |
||||
|
title: 'Github', |
||||
|
icon: 'carbon:logo-github', |
||||
|
color: '', |
||||
|
desc: '不要等待机会,而要创造机会。', |
||||
|
group: '开源组', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Vue', |
||||
|
icon: 'ion:logo-vue', |
||||
|
color: '#3fb27f', |
||||
|
desc: '现在的你决定将来的你。', |
||||
|
group: '算法组', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Html5', |
||||
|
icon: 'ion:logo-html5', |
||||
|
color: '#e18525', |
||||
|
desc: '没有什么才能比努力更重要。', |
||||
|
group: '上班摸鱼', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Angular', |
||||
|
icon: 'ion:logo-angular', |
||||
|
color: '#bf0c2c', |
||||
|
desc: '热情和欲望可以突破一切难关。', |
||||
|
group: 'UI', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'React', |
||||
|
icon: 'bx:bxl-react', |
||||
|
color: '#00d8ff', |
||||
|
desc: '健康的身体是实现目标的基石。', |
||||
|
group: '技术牛', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Js', |
||||
|
icon: 'ion:logo-javascript', |
||||
|
color: '#EBD94E', |
||||
|
desc: '路是走出来的,而不是空想出来的。', |
||||
|
group: '架构组', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
] |
||||
@ -0,0 +1,130 @@ |
|||||
|
{ |
||||
|
"title": "示例设备展示", |
||||
|
"LeftUp": { |
||||
|
"Header": "设备静态图", |
||||
|
"pathq": "/src/assets/images/header.jpg", |
||||
|
"path": "/src/assets/svg/illustration.svg", |
||||
|
"Content": "" |
||||
|
}, |
||||
|
"LeftMidUp": { |
||||
|
"Header": "故障诊断", |
||||
|
"Content": [{ |
||||
|
"FaultDesc": "故障1故障1故障1故障1故障1", |
||||
|
"Point": "Diagnosis1" |
||||
|
}, { |
||||
|
"FaultDesc": "故障2", |
||||
|
"Point": "Diagnosis2" |
||||
|
}, |
||||
|
{ |
||||
|
"FaultDesc": "故障2", |
||||
|
"Point": "Diagnosis2" |
||||
|
}, { |
||||
|
"FaultDesc": "故障2", |
||||
|
"Point": "Diagnosis2" |
||||
|
}, { |
||||
|
"FaultDesc": "故障2", |
||||
|
"Point": "Diagnosis2" |
||||
|
}, { |
||||
|
"FaultDesc": "故障2", |
||||
|
"Point": "Diagnosis2" |
||||
|
}] |
||||
|
}, |
||||
|
"RightMidUp": { |
||||
|
"Header": "报警记录", |
||||
|
"Content": [{ |
||||
|
"Text": "故障1", |
||||
|
"StartTime": "Diagnosis1", |
||||
|
"Duration": 12.3 |
||||
|
}, { |
||||
|
"Text": "故障1", |
||||
|
"StartTime": "Diagnosis1", |
||||
|
"Duration": 12.3 |
||||
|
}] |
||||
|
}, |
||||
|
"RightUp": { |
||||
|
"Header": "大模型-操作指导", |
||||
|
"Content": [{ |
||||
|
"FaultDesc": "故障1", |
||||
|
"Guide": "如何处理故障1" |
||||
|
}, { |
||||
|
"FaultDesc": "故障2", |
||||
|
"Guide": "如何处理故障2" |
||||
|
}] |
||||
|
}, |
||||
|
"LeftDown": { |
||||
|
"Header": "生产流程", |
||||
|
"path": "/src/assets/svg/illustration.svg", |
||||
|
"Content": "/api/v1/assets/production_flow.svg" |
||||
|
}, |
||||
|
"RightDown": { |
||||
|
"Header": "参数信息", |
||||
|
"Columns": [{ |
||||
|
"title": "序号", |
||||
|
"dataIndex": "序号", |
||||
|
"width": 40 |
||||
|
}, { |
||||
|
"title": "描述", |
||||
|
"dataIndex": "描述", |
||||
|
"width": 200 |
||||
|
}, { |
||||
|
"title": "点号", |
||||
|
"dataIndex": "点号", |
||||
|
"width": 100 |
||||
|
}, { |
||||
|
"title": "测量值", |
||||
|
"dataIndex": "测量值", |
||||
|
"width": 80 |
||||
|
}, { |
||||
|
"title": "预测值", |
||||
|
"dataIndex": "预测值", |
||||
|
"width": 100 |
||||
|
}, { |
||||
|
"title": "安全区域", |
||||
|
"dataIndex": "安全区域", |
||||
|
"width": 140 |
||||
|
}], |
||||
|
"Content": [{ |
||||
|
"序号": 1, |
||||
|
"描述": "", |
||||
|
"点号": "", |
||||
|
"测量值": 0.0, |
||||
|
"预测值": 0.0, |
||||
|
"安全区域": "" |
||||
|
}, { |
||||
|
"序号": 2, |
||||
|
"描述": "", |
||||
|
"点号": "", |
||||
|
"测量值": 0.0, |
||||
|
"预测值": 0.0, |
||||
|
"安全区域": "" |
||||
|
}, { |
||||
|
"序号": 3, |
||||
|
"描述": "", |
||||
|
"点号": "", |
||||
|
"测量值": 0.0, |
||||
|
"预测值": 0.0, |
||||
|
"安全区域": "" |
||||
|
}, { |
||||
|
"序号": 4, |
||||
|
"描述": "", |
||||
|
"点号": "", |
||||
|
"测量值": 0.0, |
||||
|
"预测值": 0.0, |
||||
|
"安全区域": "" |
||||
|
}, { |
||||
|
"序号": 5, |
||||
|
"描述": "", |
||||
|
"点号": "", |
||||
|
"测量值": 0.0, |
||||
|
"预测值": 0.0, |
||||
|
"安全区域": "" |
||||
|
}, { |
||||
|
"序号": 6, |
||||
|
"描述": "", |
||||
|
"点号": "", |
||||
|
"测量值": 0.0, |
||||
|
"预测值": 0.0, |
||||
|
"安全区域": "" |
||||
|
}] |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { Card, CardGrid } from 'ant-design-vue' |
||||
|
import { navItems } from './data' |
||||
|
import { Icon } from '@/components/Icon' |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
data: { |
||||
|
type: Object, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<Card class="enter-y !my-1" :title="props.data.Header"> |
||||
|
<img class="mx-auto h-50 w-full" :src="props.data.path"> |
||||
|
</Card> |
||||
|
</template> |
||||
@ -0,0 +1,54 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { ref } from 'vue' |
||||
|
import WorkbenchHeader from './components/WorkbenchHeader.vue' |
||||
|
import ProjectCard from './components/ProjectCard.vue' |
||||
|
import DynamicInfo from './components/DynamicInfo.vue' |
||||
|
import StaticImg from './components/staticImg.vue' |
||||
|
import ParameterInfo from './components/ParameterInfo.vue' |
||||
|
import Operation from './components/Operation.vue' |
||||
|
import data from './components/demo.json' |
||||
|
import { PageWrapper } from '@/components/Page' |
||||
|
|
||||
|
const loading = ref(true) |
||||
|
|
||||
|
setTimeout(() => { |
||||
|
loading.value = false |
||||
|
}, 500) |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<PageWrapper class="m-1"> |
||||
|
<template #headerContent> |
||||
|
<WorkbenchHeader :data="data" /> |
||||
|
</template> |
||||
|
<div class="bg-[#f5f5f5]"> |
||||
|
<div class="enter-y h-90 md:flex"> |
||||
|
<StaticImg class="m-1 w-full md:w-1/4" :loading="loading" :data="data.LeftUp" /> |
||||
|
<ProjectCard class="enter-y m-1 w-full md:w-1/4" :loading="loading" :data="data.LeftMidUp" /> |
||||
|
<DynamicInfo :loading="loading" class="enter-y m-1 w-full md:w-1/4" :data="data.RightMidUp" /> |
||||
|
<Operation class="m-1 w-full md:w-1/4" :loading="loading" :data="data.RightUp" /> |
||||
|
</div> |
||||
|
<div class="enter-y h-95 md:flex"> |
||||
|
<StaticImg class="m-1 w-full md:w-1/2" :loading="loading" :data="data.LeftDown" /> |
||||
|
<ParameterInfo class="m-1 w-full md:w-1/2" :loading="loading" :data="data.RightDown" /> |
||||
|
</div> |
||||
|
<!-- <div class="enter-y w-full !mr-4 lg:w-7/10"> |
||||
|
<StaticImg :loading="loading" :data="data.LeftUp" class="enter-y" /> |
||||
|
</div> --> |
||||
|
|
||||
|
<!-- <div class="enter-y w-full !mr-4 lg:w-7/10"> |
||||
|
<ProjectCard :loading="loading" class="enter-y" /> |
||||
|
<DynamicInfo :loading="loading" class="enter-y !my-4" /> |
||||
|
</div> |
||||
|
<div class="enter-y w-full lg:w-3/10"> |
||||
|
<QuickNav :loading="loading" class="enter-y" /> |
||||
|
|
||||
|
<Card class="enter-y !my-4" :loading="loading"> |
||||
|
<img class="mx-auto h-30 xl:h-50" src="@/assets/svg/illustration.svg"> |
||||
|
</Card> |
||||
|
|
||||
|
<SaleRadar :loading="loading" class="enter-y" /> |
||||
|
</div> --> |
||||
|
</div> |
||||
|
</PageWrapper> |
||||
|
</template> |
||||
@ -0,0 +1,188 @@ |
|||||
|
import moment from 'moment' |
||||
|
|
||||
|
import { ref } from 'vue' |
||||
|
import type { BasicColumn, FormSchema } from '@/components/Table' |
||||
|
import { DICT_TYPE, getDictOptions } from '@/utils/dict' |
||||
|
import { optionListApi, subSystemListApi } from '@/api/alert/model/select' |
||||
|
import type { systemSelectParams } from '@/api/alert/model/model/optionsModel' |
||||
|
|
||||
|
export const columns: BasicColumn[] = [ |
||||
|
{ |
||||
|
title: '编号', |
||||
|
dataIndex: 'id', |
||||
|
width: 80, |
||||
|
fixed: 'left', |
||||
|
}, |
||||
|
{ |
||||
|
title: '模型名称', |
||||
|
dataIndex: 'modelName', |
||||
|
width: 250, |
||||
|
className: 'instant', |
||||
|
slots: { customRender: 'detail' }, |
||||
|
fixed: 'left', |
||||
|
}, |
||||
|
{ |
||||
|
title: '算法', |
||||
|
dataIndex: 'Algorithm', |
||||
|
width: 200, |
||||
|
|
||||
|
}, |
||||
|
{ |
||||
|
title: '模式覆盖率', |
||||
|
dataIndex: 'CoveredPercent', |
||||
|
width: 200, |
||||
|
}, |
||||
|
{ |
||||
|
title: '报警次数', |
||||
|
dataIndex: 'AlarmNumber', |
||||
|
width: 200, |
||||
|
}, |
||||
|
{ |
||||
|
title: '总报警时间(m)', |
||||
|
dataIndex: 'AlarmToatlMinutes', |
||||
|
width: 200, |
||||
|
}, |
||||
|
{ |
||||
|
title: '系统维度', |
||||
|
dataIndex: 'Dimension', |
||||
|
width: 200, |
||||
|
}, |
||||
|
{ |
||||
|
title: '计算耗时(s)', |
||||
|
dataIndex: 'CalcSeconds', |
||||
|
width: 200, |
||||
|
}, |
||||
|
{ |
||||
|
title: '状态', |
||||
|
dataIndex: 'status', |
||||
|
width: 100, |
||||
|
slots: { customRender: 'status' }, |
||||
|
fixed: 'right', |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
const optionList = await optionListApi() |
||||
|
|
||||
|
const systemOptions = ref<any>([]) |
||||
|
systemOptions.value = optionList.systems |
||||
|
export const searchFormSchema: FormSchema[] = [ |
||||
|
{ |
||||
|
label: '机组', |
||||
|
field: 'unit', |
||||
|
component: 'Select', |
||||
|
defaultValue: optionList.units[0].id || null, |
||||
|
colProps: { span: 4 }, |
||||
|
|
||||
|
componentProps: ({ formModel }) => { |
||||
|
return { |
||||
|
// xxxx props
|
||||
|
allowClear: false, |
||||
|
placeholder: '请选择机组', |
||||
|
options: optionList.units.map(unit => ({ value: unit.id, label: unit.name })), |
||||
|
onChange: async (e: any) => { |
||||
|
// const { reload } = tableAction
|
||||
|
// reload()
|
||||
|
// or
|
||||
|
console.log(e) |
||||
|
const param: systemSelectParams = { |
||||
|
unitId: e, |
||||
|
typeId: formModel.type, |
||||
|
} |
||||
|
systemOptions.value = await subSystemListApi(param) |
||||
|
formModel.system = systemOptions.value[0].id |
||||
|
}, |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
label: '系统', |
||||
|
field: 'type', |
||||
|
component: 'Select', |
||||
|
defaultValue: optionList.types[0].id || null, |
||||
|
colProps: { span: 4 }, |
||||
|
componentProps: ({ formModel }) => { |
||||
|
return { |
||||
|
allowClear: false, |
||||
|
placeholder: '请选择系统', |
||||
|
options: optionList.types.map(type => ({ value: type.id, label: type.name })), |
||||
|
onChange: async (e: any) => { |
||||
|
// const { reload } = tableAction
|
||||
|
// reload()
|
||||
|
// or
|
||||
|
console.log(e) |
||||
|
const param: systemSelectParams = { |
||||
|
unitId: formModel.unit, |
||||
|
typeId: e, |
||||
|
} |
||||
|
systemOptions.value = await subSystemListApi(param) |
||||
|
}, |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
label: '子系统', |
||||
|
field: 'system', |
||||
|
component: 'Select', |
||||
|
defaultValue: systemOptions.value[0].id || null, |
||||
|
colProps: { span: 4 }, |
||||
|
componentProps: () => { |
||||
|
return { |
||||
|
allowClear: false, |
||||
|
placeholder: '请选择子系统', |
||||
|
options: systemOptions.value.map(system => ({ value: system.id, label: system.name })), |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
label: '模型名称', |
||||
|
field: 'modelName', |
||||
|
component: 'Input', |
||||
|
|
||||
|
defaultValue: '', |
||||
|
componentProps: { |
||||
|
placeholder: '请输入模型名称', |
||||
|
}, |
||||
|
colProps: { span: 4 }, |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
export const calcFormSchemas: FormSchema[] = [ |
||||
|
{ |
||||
|
label: '回算时间', |
||||
|
field: 'time', |
||||
|
component: 'RangePicker', |
||||
|
componentProps: { |
||||
|
placeholder: ['开始时间', '结束时间'], |
||||
|
defaultValue: [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')], |
||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss', |
||||
|
showTime: { |
||||
|
defaultValue: [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')], |
||||
|
}, |
||||
|
|
||||
|
onChange: (e: any) => { |
||||
|
console.log(e) |
||||
|
}, |
||||
|
}, |
||||
|
required: true, |
||||
|
|
||||
|
colProps: { |
||||
|
span: 8, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
label: '回算采样周期', |
||||
|
field: 'interval', |
||||
|
component: 'Select', |
||||
|
defaultValue: 60, |
||||
|
|
||||
|
componentProps: { |
||||
|
options: [{ value: 10, label: '10秒' }, { value: 60, label: '60秒' }, { value: 300, label: '300秒' }], |
||||
|
}, |
||||
|
required: true, |
||||
|
colProps: { |
||||
|
span: 4, |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
] |
||||
@ -0,0 +1,185 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { Badge, Button, Divider, Switch } from 'ant-design-vue' |
||||
|
import { onMounted, ref } from 'vue' |
||||
|
import moment from 'moment' |
||||
|
import HistoryModal from '../../exa/config/HistoryModal.vue' |
||||
|
import { calcFormSchemas, columns, searchFormSchema } from './calc.data' |
||||
|
|
||||
|
import { BasicTable, TableAction, useTable } from '@/components/Table' |
||||
|
import { BasicForm, useForm } from '@/components/Form' |
||||
|
|
||||
|
import { getInstantCount, getInstantPage, updateInstant } from '@/api/alert/run/instant' |
||||
|
import { getExaNow } from '@/api/alert/exa' |
||||
|
import { useI18n } from '@/hooks/web/useI18n' |
||||
|
import { router } from '@/router' |
||||
|
import { useMessage } from '@/hooks/web/useMessage' |
||||
|
import { IconEnum } from '@/enums/appEnum' |
||||
|
import { useModal } from '@/components/Modal' |
||||
|
|
||||
|
defineOptions({ name: 'InstantCalc' }) |
||||
|
const { createMessage } = useMessage() |
||||
|
const { t } = useI18n() |
||||
|
|
||||
|
const [registerHistoryModal, { openModal: openHistoryModal }] = useModal() |
||||
|
const [registerCreateModal, { openModal: openCreateModal }] = useModal() |
||||
|
const [registerUpdateModal, { openModal: openUpdateModal }] = useModal() |
||||
|
|
||||
|
const [registerTable, { getForm, reload, getDataSource, updateTableDataRecord }] = useTable({ |
||||
|
title: '实例列表', |
||||
|
api: getInstantPage, |
||||
|
rowKey: 'id', |
||||
|
immediate: true, |
||||
|
columns, |
||||
|
formConfig: { |
||||
|
labelWidth: 70, |
||||
|
schemas: searchFormSchema, |
||||
|
showResetButton: false, |
||||
|
actionColOptions: { |
||||
|
span: 2, |
||||
|
}, |
||||
|
|
||||
|
}, |
||||
|
useSearchForm: true, |
||||
|
showTableSetting: true, |
||||
|
showIndexColumn: false, |
||||
|
actionColumn: { |
||||
|
width: 100, |
||||
|
title: t('common.action'), |
||||
|
dataIndex: 'action', |
||||
|
fixed: 'right', |
||||
|
}, |
||||
|
}) |
||||
|
|
||||
|
const isShow = ref<boolean>(false) |
||||
|
|
||||
|
function handleCreate() { |
||||
|
openCreateModal(true, { isUpdate: false }) |
||||
|
isShow.value = true |
||||
|
} |
||||
|
|
||||
|
function handleEdit(record: Recordable) { |
||||
|
openUpdateModal(true, { record, isUpdate: true }) |
||||
|
} |
||||
|
async function handleDelete(record: Recordable) { |
||||
|
await deleteRole(record.id) |
||||
|
createMessage.success(t('common.delSuccessText')) |
||||
|
reload() |
||||
|
} |
||||
|
|
||||
|
const itemName = ref<string>() |
||||
|
const legendName = ref<string[]>() |
||||
|
function handleHistory(record: Recordable) { |
||||
|
itemName.value = (JSON.parse(record.instantInfo)).model_state |
||||
|
legendName.value = [] |
||||
|
legendName.value.push(`${record.mpName}-${itemName.value}`) |
||||
|
openHistoryModal(true, { record }) |
||||
|
} |
||||
|
|
||||
|
function handleWarnConfig(record: Recordable) { |
||||
|
router.push(`/run/warnConfig?id=${record.id}`) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* BasicForm绑定注册; |
||||
|
*/ |
||||
|
const [registerForm] = useForm({ |
||||
|
// 注册表单列 |
||||
|
schemas: calcFormSchemas, |
||||
|
// 是否显示展开收起按钮,默认false |
||||
|
// showAdvancedButton: true, |
||||
|
// // // 超过指定行数折叠,默认3行 |
||||
|
// autoAdvancedLine: 1, |
||||
|
// // // 折叠时默认显示行数,默认1行 |
||||
|
// alwaysShowLines: 1, |
||||
|
layout: 'horizontal', |
||||
|
model: { time: [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')] }, |
||||
|
fieldMapToTime: [ |
||||
|
// data为时间组件在表单内的字段,startTime,endTime为转化后的开始时间于结束时间 |
||||
|
['time', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'], |
||||
|
], |
||||
|
actionColOptions: { span: 2 }, |
||||
|
showSubmitButton: false, |
||||
|
showResetButton: false, |
||||
|
}) |
||||
|
|
||||
|
/** |
||||
|
* 点击提交按钮的value值----改为导出按钮 |
||||
|
* @param values |
||||
|
*/ |
||||
|
function handleSubmit(values: any) { |
||||
|
console.log('提交按钮数据::::', values) |
||||
|
} |
||||
|
// 回算 |
||||
|
function handleCalc(values: any) { |
||||
|
console.log('提交按钮数据::::', values) |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<div> |
||||
|
<BasicTable @register="registerTable"> |
||||
|
<template #form-formFooter> |
||||
|
<!-- <a-button v-auth="['run:instant:create']" type="primary" :pre-icon="IconEnum.ADD" @click="handleCreate"> |
||||
|
{{ t('action.create') }} |
||||
|
</a-button> --> |
||||
|
<Divider orientation="left"> |
||||
|
回算 |
||||
|
</Divider> |
||||
|
<!-- 自定义表单 --> |
||||
|
<BasicForm @register="registerForm"> |
||||
|
<template #advanceBefore> |
||||
|
<a-button v-auth="['run:instant:create']" type="primary" :pre-icon="IconEnum.ADD" @click="handleCreate"> |
||||
|
{{ t('action.create') }} |
||||
|
</a-button> |
||||
|
</template> |
||||
|
</BasicForm> |
||||
|
</template> |
||||
|
|
||||
|
<!-- 统计量点击跳转历史曲线 --> |
||||
|
<template #history="{ record }"> |
||||
|
<a @click="handleHistory(record)"> |
||||
|
{{ record.pointSte }} |
||||
|
</a> |
||||
|
<!-- <SlidersOutlined class="click-status" /> --> |
||||
|
</template> |
||||
|
|
||||
|
<template #bodyCell="{ column, record }"> |
||||
|
<template v-if="column.key === 'action'"> |
||||
|
<TableAction |
||||
|
:actions="[ |
||||
|
{ icon: IconEnum.BACK_CALC, label: t('action.backCalc'), onClick: handleWarnConfig.bind(null, record) }, |
||||
|
]" |
||||
|
/> |
||||
|
</template> |
||||
|
</template> |
||||
|
</BasicTable> |
||||
|
<HistoryModal :item-name="itemName" :legend-name="legendName" @register="registerHistoryModal" /> |
||||
|
<CreateModal :item-name="itemName" :legend-name="legendName" @register="registerCreateModal" @success="reload" /> |
||||
|
<UpdateModal @register="registerUpdateModal" @success="reload" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
:deep(.instant) { |
||||
|
font-weight: bold; |
||||
|
color: #0B55A4 |
||||
|
} |
||||
|
|
||||
|
:deep(.alarm .ant-badge-status-dot) { |
||||
|
animation: flash 1s linear infinite; |
||||
|
} |
||||
|
|
||||
|
@keyframes flash { |
||||
|
from { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.runningStatus { |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
</style> |
||||
Loading…
Reference in new issue