🐛 修复代码检查提示的缺陷
This commit is contained in:
parent
a7172a2d8b
commit
58cd837553
@ -3,7 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class PontCoreManager {
|
class PontCoreManager {
|
||||||
static singleInstance = null as PontCoreManager;
|
// static singleInstance = undefined as PontCoreManager;
|
||||||
|
private static singleInstance: PontCoreManager | null = null;
|
||||||
|
|
||||||
static getSignleInstance() {
|
static getSignleInstance() {
|
||||||
if (!PontCoreManager.singleInstance) {
|
if (!PontCoreManager.singleInstance) {
|
||||||
@ -36,12 +37,12 @@ class PontCoreManager {
|
|||||||
this.fetch = fetch;
|
this.fetch = fetch;
|
||||||
}
|
}
|
||||||
|
|
||||||
getUrl(path: string, queryParams: any, method: string) {
|
getUrl(path: string, queryParams: any) {
|
||||||
const params = {
|
const params = {
|
||||||
...(queryParams || ({} as any)),
|
...(queryParams || ({} as any)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const url = path.replace(/\{([^\\}]*(?:\\.[^\\}]*)*)\}/gm, (match, key) => {
|
const url = path.replace(/\{([^\\}]*(?:\\.[^\\}]*)*)\}/gm, ( key) => {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
key = key.trim();
|
key = key.trim();
|
||||||
|
|
||||||
|
6
src/components.d.ts
vendored
6
src/components.d.ts
vendored
@ -7,6 +7,7 @@ export {}
|
|||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
|
AAlert: typeof import('ant-design-vue/es')['Alert']
|
||||||
AAvatar: typeof import('ant-design-vue/es')['Avatar']
|
AAvatar: typeof import('ant-design-vue/es')['Avatar']
|
||||||
AButton: typeof import('ant-design-vue/es')['Button']
|
AButton: typeof import('ant-design-vue/es')['Button']
|
||||||
ACard: typeof import('ant-design-vue/es')['Card']
|
ACard: typeof import('ant-design-vue/es')['Card']
|
||||||
@ -21,6 +22,7 @@ declare module 'vue' {
|
|||||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||||
AImage: typeof import('ant-design-vue/es')['Image']
|
AImage: typeof import('ant-design-vue/es')['Image']
|
||||||
AInput: typeof import('ant-design-vue/es')['Input']
|
AInput: typeof import('ant-design-vue/es')['Input']
|
||||||
|
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||||
AInputSearch: typeof import('ant-design-vue/es')['InputSearch']
|
AInputSearch: typeof import('ant-design-vue/es')['InputSearch']
|
||||||
ALayout: typeof import('ant-design-vue/es')['Layout']
|
ALayout: typeof import('ant-design-vue/es')['Layout']
|
||||||
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
|
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
|
||||||
@ -48,9 +50,11 @@ declare module 'vue' {
|
|||||||
ATabPane: typeof import('ant-design-vue/es')['TabPane']
|
ATabPane: typeof import('ant-design-vue/es')['TabPane']
|
||||||
ATabs: typeof import('ant-design-vue/es')['Tabs']
|
ATabs: typeof import('ant-design-vue/es')['Tabs']
|
||||||
ATag: typeof import('ant-design-vue/es')['Tag']
|
ATag: typeof import('ant-design-vue/es')['Tag']
|
||||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
|
||||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||||
|
ATransfer: typeof import('ant-design-vue/es')['Transfer']
|
||||||
|
ATree: typeof import('ant-design-vue/es')['Tree']
|
||||||
ATypographyLink: typeof import('ant-design-vue/es')['TypographyLink']
|
ATypographyLink: typeof import('ant-design-vue/es')['TypographyLink']
|
||||||
|
ATypographyParagraph: typeof import('ant-design-vue/es')['TypographyParagraph']
|
||||||
ATypographyTitle: typeof import('ant-design-vue/es')['TypographyTitle']
|
ATypographyTitle: typeof import('ant-design-vue/es')['TypographyTitle']
|
||||||
AuxiliaryItemRender: typeof import('./components/form-render/auxiliary-item-render.vue')['default']
|
AuxiliaryItemRender: typeof import('./components/form-render/auxiliary-item-render.vue')['default']
|
||||||
AWatermark: typeof import('ant-design-vue/es')['Watermark']
|
AWatermark: typeof import('ant-design-vue/es')['Watermark']
|
||||||
|
@ -48,7 +48,7 @@ export const routes = [
|
|||||||
path: '/stock/inbound', //入库
|
path: '/stock/inbound', //入库
|
||||||
name: 'Inbound',
|
name: 'Inbound',
|
||||||
meta: {title: 'menus.stock.inbound',icon: 'icon-permission'},
|
meta: {title: 'menus.stock.inbound',icon: 'icon-permission'},
|
||||||
component: ()=> import('../views/stock/inboud/inboud-page.vue'),
|
component: ()=> import('../views/stock/inboud/inboud-page.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/stock/outbound', //出库
|
path: '/stock/outbound', //出库
|
||||||
@ -107,11 +107,6 @@ export default createRouter({
|
|||||||
name: 'Index',
|
name: 'Index',
|
||||||
redirect: '/login',
|
redirect: '/login',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/dashboard',
|
|
||||||
name: 'Dashboard',
|
|
||||||
component: () => import('../views/dashboard/dashboard-page.vue'),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'Login',
|
name: 'Login',
|
||||||
|
@ -1,383 +0,0 @@
|
|||||||
<template>
|
|
||||||
<page-container>
|
|
||||||
<a-row :gutter="[16, 16]">
|
|
||||||
<a-col :span="8">
|
|
||||||
<a-card title="XXX项目档案目录">
|
|
||||||
<template #extra>
|
|
||||||
<a-select ref="select" v-model:value="value1" style="width: 120px" :options="options1"></a-select>
|
|
||||||
</template>
|
|
||||||
<a-directory-tree
|
|
||||||
v-model:expanded-keys="expandedKeys"
|
|
||||||
v-model:selected-keys="selectedKeys"
|
|
||||||
:tree-data="treeData"
|
|
||||||
></a-directory-tree>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="16">
|
|
||||||
<a-card title="XXX项目 一、勘测定界图或拟征地红线图 电子档案">
|
|
||||||
<a-row :gutter="[16, 16]">
|
|
||||||
<a-col v-for="item in 32" :key="item" span="3">
|
|
||||||
<a-card hoverable>
|
|
||||||
<template #cover>
|
|
||||||
<img alt="example" :src="pics[Math.floor(Math.random() * 10) % 4]" />
|
|
||||||
</template>
|
|
||||||
<a-card-meta>
|
|
||||||
<template #title>
|
|
||||||
<span style="font-size: 12px">xxx 公告第{{ Math.floor(Math.random() * 10) }}页</span>
|
|
||||||
</template>
|
|
||||||
</a-card-meta>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</page-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { SelectProps, TreeProps } from 'ant-design-vue'
|
|
||||||
import excel from '@/assets/excel.png'
|
|
||||||
import word from '@/assets/WORD.png'
|
|
||||||
import pdf from '@/assets/PDF.png'
|
|
||||||
import image from '@/assets/image.png'
|
|
||||||
const pics = ref<string[]>([excel, word, pdf, image])
|
|
||||||
const value1 = ref('lucy')
|
|
||||||
const options1 = ref<SelectProps['options']>([
|
|
||||||
{
|
|
||||||
value: 'jack',
|
|
||||||
label: '项目一',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'lucy',
|
|
||||||
label: '项目二',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'yiminghe',
|
|
||||||
label: '项目三',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const expandedKeys = ref<string[]>(['0-0', '0-1'])
|
|
||||||
const selectedKeys = ref<string[]>([])
|
|
||||||
const treeData: TreeProps['treeData'] = [
|
|
||||||
{
|
|
||||||
title: '征地档案',
|
|
||||||
key: '0-0',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '一、勘测定界图或拟征地红线图',
|
|
||||||
key: '0-0-0',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '二、关于征收土地预公告(附件1)',
|
|
||||||
key: '0-0-1',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '三、征地动员和政策宣传影像资料和相关文字记录',
|
|
||||||
key: '0-0-2',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '四、拟征收土地现状调查',
|
|
||||||
key: '0-0-3',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '凤凰镇双凤村1社',
|
|
||||||
key: '3-0-0',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '四(一)、人口调查表(附件2-1)', key: '3-1-0', isLeaf: true },
|
|
||||||
{ title: '四(二)、拟征收土地分户调查表(附件2-2)', key: '3-1-1', isLeaf: true },
|
|
||||||
{ title: '四(三)、其他地上附着物和青苗分户现状调查表(附件2-3)', key: '3-1-2', isLeaf: true },
|
|
||||||
{
|
|
||||||
title: '张三(例)',
|
|
||||||
key: '3-1-3',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '四(四)、构筑物分户调查表(附件2-4)', key: '3-1-3-0', isLeaf: true },
|
|
||||||
{ title: '四(五)、农村房屋分户现状调查表(附件2-5)', key: '3-1-3-1', isLeaf: true },
|
|
||||||
{ title: '四(六)、生产经营活动现状调查表(附件2-6)', key: '3-1-3-2', isLeaf: true },
|
|
||||||
{ title: '四(七)、未取得不动产权证书房屋产权面积认定表(附件9-2)', key: '3-1-3-3', isLeaf: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ title: '李四(例)', key: '3-1-4', isLeaf: false },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ title: '凤凰镇双凤村2社', key: '3-0-1', isLeaf: false },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '五、征地社会稳定风险评估报告及县信访办备案文书',
|
|
||||||
key: '0-0-4',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '六、征地补偿安置方案',
|
|
||||||
key: '0-0-5',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '六(一)、征地补偿安置方案公告(附件3)',
|
|
||||||
key: '5-0-1',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '六(二)、提出异议的书面材料或听证申请书',
|
|
||||||
key: '5-0-2',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '六(三)、异议答复材料或召开听证会相关材料',
|
|
||||||
key: '5-0-3',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '七、补偿登记',
|
|
||||||
key: '0-0-6',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '凤凰镇双凤村1社',
|
|
||||||
key: '6-0-0',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '七(一)、被征收土地及土地补偿费补偿登记表(附件5-1)', key: '6-1-0', isLeaf: true },
|
|
||||||
{ title: '七(二)、其他地上附着物和青苗补偿登记表(附件5-2)', key: '6-1-1', isLeaf: true },
|
|
||||||
{ title: '七(三)、农村房屋补偿登记表(附件5-3)', key: '6-1-2', isLeaf: true },
|
|
||||||
{
|
|
||||||
title: '七(四)、林地上的林木及附着物分户现状调查和补偿登记表(附件9-1)',
|
|
||||||
key: '6-1-3',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '张三(例)',
|
|
||||||
key: '6-1-3-1',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '1.住房安置特殊对象调查表(附件9-3)', key: '6-1-3-1-0', isLeaf: true },
|
|
||||||
{ title: '2.增加安置住房申请书', key: '6-1-3-1-1', isLeaf: true },
|
|
||||||
{ title: '3.准生证', key: '6-1-3-1-2', isLeaf: true },
|
|
||||||
{ title: '4.结婚证', key: '6-1-3-1-3', isLeaf: true },
|
|
||||||
{ title: '5.无房申明和家庭成员住房查询记录', key: '6-1-3-1-4', isLeaf: true },
|
|
||||||
{ title: '6.集体经济组织出具的长期居住证明', key: '6-1-3-1-5', isLeaf: true },
|
|
||||||
{
|
|
||||||
title: '7.户籍所在地集体经济组织出具的不享有宅基地权利的证明',
|
|
||||||
key: '6-1-3-1-6',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ title: '李四(例)', key: '6-1-3-2', isLeaf: false },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ title: '七(五)、住房安置特殊对象资料', key: '6-1-4', isLeaf: true },
|
|
||||||
{ title: '七(六)、征地集体资产汇总公示表(附件9-4)', key: '6-1-5', isLeaf: true },
|
|
||||||
{ title: '七(七)、对补偿登记情况提出异议的书面材料', key: '6-1-6', isLeaf: true },
|
|
||||||
{ title: '七(八)、对异议的核实、决议及公布材料', key: '6-1-7', isLeaf: true },
|
|
||||||
{
|
|
||||||
title: '七(九)、土地承包经营权证、房屋不动产权证',
|
|
||||||
key: '6-1-8',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '张三(例)', key: '6-1-8-1', isLeaf: true },
|
|
||||||
{ title: '李四(例)', key: '6-1-8-2', isLeaf: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '七(十)、被征地农户的身份证、户口簿及银行卡',
|
|
||||||
key: '6-1-9',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '张三(例)', key: '6-1-9-1', isLeaf: true },
|
|
||||||
{ title: '李四(例)', key: '6-1-9-2', isLeaf: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ title: '凤凰镇双凤村2社', key: '6-0-1', isLeaf: false },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '八、确定征地补偿安置方案公告(附件4)',
|
|
||||||
key: '0-0-7',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '九、补偿安置协议',
|
|
||||||
key: '0-0-8',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '凤凰镇双凤村1社',
|
|
||||||
key: '8-0-0',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '九(一)、征地补偿安置协议书', key: '8-1-0', isLeaf: true },
|
|
||||||
{
|
|
||||||
title: '九(二)、被征地农户签订的土地、青苗及附着物分户补偿协议书',
|
|
||||||
key: '8-1-1',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '张三(例)', key: '8-1-8-1', isLeaf: true },
|
|
||||||
{ title: '李四(例)', key: '8-1-8-2', isLeaf: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '九(三)、同被征地农户签订的住房补偿安置协议书',
|
|
||||||
key: '8-1-2',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '张三(例)', key: '8-1-9-1', isLeaf: true },
|
|
||||||
{ title: '李四(例)', key: '8-1-9-2', isLeaf: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ title: '凤凰镇双凤村2社', key: '6-0-1', isLeaf: false },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十、确定具体人员安置对象',
|
|
||||||
key: '0-0-9',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '凤凰镇双凤村1社',
|
|
||||||
key: '9-0-0',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '十(一)、召开村民大会确定具体安置人员安置对象的会议记录及影像资料',
|
|
||||||
key: '9-1-0',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十(二)、征地人员安置对象名单及公示照片',
|
|
||||||
key: '9-1-1',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十(三)、征地人员安置对象核准表(附件6)',
|
|
||||||
key: '9-1-2',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ title: '凤凰镇双凤村2社', key: '6-0-1', isLeaf: false },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十一、市人民政府关于农用地转用和土地征收的批复',
|
|
||||||
key: '0-1-0',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十二、征收土地的公告(附件7)',
|
|
||||||
key: '0-1-1',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十三、支付补偿安置费用',
|
|
||||||
key: '0-1-2',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '凤凰镇双凤村1社',
|
|
||||||
key: '9-0-0',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '十三(一)、领取征地补偿安置费通知书及送达登记表',
|
|
||||||
key: '12-1-0',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十三(二)、安置补助费发放表(附件8-2)',
|
|
||||||
key: '12-1-1',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十三(三)、集体对公账户详细信息',
|
|
||||||
key: '12-1-2',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十三(四)、征地补偿安置费用发放记录',
|
|
||||||
key: '12-1-3',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ title: '凤凰镇双凤村2社', key: '6-0-1', isLeaf: false },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十四、作出征地补偿安置决定资料',
|
|
||||||
key: '0-1-3',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: '十四(一)、征地补偿安置决定书',
|
|
||||||
key: '13-1-0',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十四(二)、被征收人申请行政复议或提起行政诉讼有关资料',
|
|
||||||
key: '13-1-1',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十四(三)、行政复议或行政诉讼判决书',
|
|
||||||
key: '13-1-2',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十四(四)、申请强制执行资料',
|
|
||||||
key: '13-1-3',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十五、基本养老保险缴费补贴对象及补贴年限确认表(附件8-1)',
|
|
||||||
key: '0-1-4',
|
|
||||||
isLeaf: false,
|
|
||||||
children: [
|
|
||||||
{ title: '凤凰镇双凤村1社', key: '14-0-0', isLeaf: true },
|
|
||||||
{ title: '凤凰镇双凤村2社', key: '14-0-1', isLeaf: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '十六、其他资料',
|
|
||||||
key: '0-1-5',
|
|
||||||
isLeaf: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '项目建设档案',
|
|
||||||
key: '0-1',
|
|
||||||
disabled: true,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: 'leaf 1-0',
|
|
||||||
key: '0-1-0',
|
|
||||||
isLeaf: true,
|
|
||||||
disabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'leaf 1-1',
|
|
||||||
key: '0-1-1',
|
|
||||||
isLeaf: true,
|
|
||||||
disabled: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
</script>
|
|
@ -1,73 +0,0 @@
|
|||||||
import { FormItem, FormConfig } from '@/components/form-render/form-render-types'
|
|
||||||
|
|
||||||
export const config: FormConfig = {
|
|
||||||
layout: 'horizontal',
|
|
||||||
colon: true,
|
|
||||||
hideRequiredMark: false,
|
|
||||||
labelAlign: 'right',
|
|
||||||
scrollToFirstError: false,
|
|
||||||
validateOnRuleChange: true,
|
|
||||||
labelCol: {
|
|
||||||
span: 4,
|
|
||||||
offset: 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const formItems: FormItem[] = [
|
|
||||||
{
|
|
||||||
group: 'form',
|
|
||||||
type: 'input',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '设备编号',
|
|
||||||
name: 'key',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
type: 'text',
|
|
||||||
allowClear: false,
|
|
||||||
bordered: true,
|
|
||||||
showCount: false,
|
|
||||||
placeholder: '请输入设备编号',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
group: 'form',
|
|
||||||
type: 'input',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '设备名称',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
type: 'text',
|
|
||||||
allowClear: false,
|
|
||||||
bordered: true,
|
|
||||||
showCount: false,
|
|
||||||
placeholder: '请输入设备名称',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input-number',
|
|
||||||
group: 'form',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '设备通道数',
|
|
||||||
name: 'channels',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
controls: true,
|
|
||||||
placeholder: '请填写设备通道数',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
]
|
|
@ -1,95 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-card size="small" :title="`通道 ${item.key} 数据情况`">
|
|
||||||
<template #extra>
|
|
||||||
<a-badge v-if="station" status="success" :text="station?.name" :style="{ cursor: 'pointer' }" @click="toDetail" />
|
|
||||||
<a-badge v-else status="default" text="未绑定工位" />
|
|
||||||
</template>
|
|
||||||
<v-chart class="chart" :option="option" autoresize />
|
|
||||||
</a-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
const props = defineProps({
|
|
||||||
item: {
|
|
||||||
type: Object as PropType<{ key: number; value: sensor.SensorLog[] }>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
station: {
|
|
||||||
type: Object as PropType<sensor.Station>,
|
|
||||||
required: false,
|
|
||||||
default: () => null,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const { item, station } = toRefs(props)
|
|
||||||
const option = computed(() => {
|
|
||||||
return {
|
|
||||||
// grid: { top: '10px', left: '10px', right: '10px', bottom: '20px', containLable: true },
|
|
||||||
grid: { top: '35px', left: '55px', right: '35px', bottom: '35px', containLable: true },
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
formatter: '{b0}<br> 电流: {c0} A<br /> 电压: {c1} V<br /> 温度: {c2} ℃',
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: item.value.value.map((l) => l.createdTime?.split(' ')[1]),
|
|
||||||
},
|
|
||||||
yAxis: [
|
|
||||||
{
|
|
||||||
position: 'left',
|
|
||||||
type: 'value',
|
|
||||||
nameLocation: 'start',
|
|
||||||
offset: 25,
|
|
||||||
name: '电流(A)',
|
|
||||||
// show: false,
|
|
||||||
// min: 5,
|
|
||||||
// max: 15,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 'left',
|
|
||||||
type: 'value',
|
|
||||||
name: '电压(V)',
|
|
||||||
// show: false,
|
|
||||||
min: 0,
|
|
||||||
max: 400,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 'right',
|
|
||||||
type: 'value',
|
|
||||||
name: '温度(℃)',
|
|
||||||
// show: false,
|
|
||||||
min: -10,
|
|
||||||
max: 60,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: item.value.value.map((l) => l.ampere),
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
yAxisIndex: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: item.value.value.map((l) => l.voltage),
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
yAxisIndex: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: item.value.value.map((l) => l.temperature),
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
yAxisIndex: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const router = useRouter()
|
|
||||||
const toDetail = () => {
|
|
||||||
router.push({ name: 'station-detail', params: { key: station.value.uid } })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
.chart {
|
|
||||||
height: 230px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,84 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-drawer v-model:open="open" title="设备详情" placement="right" width="45%" :body-style="{ padding: '6px 12px' }">
|
|
||||||
<template #extra>
|
|
||||||
已持续工作
|
|
||||||
<a-badge status="success" color="cyan" :count="info.value" :overflow-count="9999999"></a-badge>
|
|
||||||
{{ info.unit === 'day' ? '天' : '小时' }}
|
|
||||||
</template>
|
|
||||||
<a-row v-if="detailGroup.length" :gutter="[16, 4]">
|
|
||||||
<a-col v-for="item in detailGroup" :key="item.key" :span="24">
|
|
||||||
<sensor-channel
|
|
||||||
:item="item"
|
|
||||||
:station="detail?.stations.filter((s) => s.channel === item.key)[0]"
|
|
||||||
></sensor-channel>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
<a-flex v-else :style="{ height: 'calc( 100vh - 80px )' }" justify="center" align="center">
|
|
||||||
<a-spin tip="数据加载中..."></a-spin>
|
|
||||||
</a-flex>
|
|
||||||
</a-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import SensorChannel from './sensor-channel.vue'
|
|
||||||
import api from '@/api'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
import { PropType } from 'vue'
|
|
||||||
const props = defineProps({
|
|
||||||
show: {
|
|
||||||
type: Boolean,
|
|
||||||
default: () => false,
|
|
||||||
},
|
|
||||||
sensor: {
|
|
||||||
type: Object as PropType<sensor.Sensor>,
|
|
||||||
default: () => null,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const emit = defineEmits<{
|
|
||||||
'update:show': [value: boolean]
|
|
||||||
}>()
|
|
||||||
const { show, sensor } = toRefs(props)
|
|
||||||
const open = computed({
|
|
||||||
get: () => show.value,
|
|
||||||
set: (val) => emit('update:show', val),
|
|
||||||
})
|
|
||||||
const info = computed(() => {
|
|
||||||
const days = dayjs().diff(dayjs(sensor.value.createdTime), 'day')
|
|
||||||
if (days > 0) {
|
|
||||||
return { value: days, unit: 'day' }
|
|
||||||
}
|
|
||||||
return { value: dayjs().diff(dayjs(sensor.value.createdTime), 'hour'), unit: 'hour' }
|
|
||||||
})
|
|
||||||
const detail = ref<sensor.SensorDetail>()
|
|
||||||
const detailGroup = computed(() => {
|
|
||||||
const items = detail.value?.logs || []
|
|
||||||
return Object.values({
|
|
||||||
...Array.from(new Set(items.map((item) => item.channel))),
|
|
||||||
})
|
|
||||||
.sort((a, b) => Number(a) - Number(b))
|
|
||||||
.map((channel) => ({
|
|
||||||
key: Number(channel),
|
|
||||||
value: items
|
|
||||||
.filter(({ channel: c }) => channel === c)
|
|
||||||
.sort((a, b) => String(a.createdTime)?.localeCompare(String(b.createdTime))),
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
const timer = ref()
|
|
||||||
watch(
|
|
||||||
sensor,
|
|
||||||
(val) => {
|
|
||||||
if (val && show.value) {
|
|
||||||
clearInterval(timer.value)
|
|
||||||
timer.value = setInterval(() => {
|
|
||||||
loadData(Number(val.id))
|
|
||||||
}, 5000)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: false, deep: true },
|
|
||||||
)
|
|
||||||
const loadData = async (_id: number) => {
|
|
||||||
api.sensorApi.sensor.detail(Number(_id), (data) => {
|
|
||||||
detail.value = data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,187 +0,0 @@
|
|||||||
<template>
|
|
||||||
<page-container>
|
|
||||||
<template #ops>
|
|
||||||
<a-row>
|
|
||||||
<a-col :span="18">
|
|
||||||
<a-input-search
|
|
||||||
v-model:value="searchKey"
|
|
||||||
:placeholder="`请输入设备号/名称`"
|
|
||||||
allow-clear
|
|
||||||
enter-button
|
|
||||||
@search="loadData()"
|
|
||||||
></a-input-search>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="6">
|
|
||||||
<a-button type="primary" style="margin-left: 10px" @click="addOrEdit()">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-plus" />
|
|
||||||
</template>
|
|
||||||
添加
|
|
||||||
</a-button>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
|
||||||
<div style="min-height: calc(100vh - 305px)">
|
|
||||||
<a-table
|
|
||||||
:columns="columns"
|
|
||||||
:data-source="sensorPage?.records"
|
|
||||||
bordered
|
|
||||||
:pagination="pagination"
|
|
||||||
:loading="loading"
|
|
||||||
row-key="key"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.dataIndex === 'key'">
|
|
||||||
<a-typography-link
|
|
||||||
href="javascript:;"
|
|
||||||
:style="{ color: token.colorPrimary }"
|
|
||||||
@click="showDetail(record as sensor.Sensor)"
|
|
||||||
>
|
|
||||||
{{ record.key }}
|
|
||||||
</a-typography-link>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.dataIndex === 'operation'">
|
|
||||||
<a-button type="link" :style="{ color: token.colorPrimary }" @click="addOrEdit(record)">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-edit" />
|
|
||||||
</template>
|
|
||||||
编辑
|
|
||||||
</a-button>
|
|
||||||
<a-popconfirm :title="`确定需要删除设备 ${record.name}(${record.key}) 吗?`" @confirm="remove(record.id)">
|
|
||||||
<a-button type="link" danger style="margin-left: 10px">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-delete" />
|
|
||||||
</template>
|
|
||||||
删除
|
|
||||||
</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</div>
|
|
||||||
</page-container>
|
|
||||||
<form-drawer
|
|
||||||
ref="formDrawer"
|
|
||||||
v-model="sensor"
|
|
||||||
:form-items="items"
|
|
||||||
:config="formConfig"
|
|
||||||
:title="modalTitle"
|
|
||||||
@ok="doSave"
|
|
||||||
/>
|
|
||||||
<sensor-detail-drawer ref="sensorDetailDrawer" v-model:show="show" :sensor="currentSensor" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import FormDrawer from '@/components/form-render/form-drawer.vue'
|
|
||||||
import SensorDetailDrawer from './sensor-detail-drawer.vue'
|
|
||||||
import api from '@/api'
|
|
||||||
import { IPage } from '@/api/api'
|
|
||||||
import { notification, theme } from 'ant-design-vue'
|
|
||||||
import { config, formItems } from './form'
|
|
||||||
import { FormDataType } from '@/components/form-render/form-render-types'
|
|
||||||
const { useToken } = theme
|
|
||||||
const { token } = useToken()
|
|
||||||
const searchKey = ref('')
|
|
||||||
|
|
||||||
const sensorPage = ref<IPage<sensor.Sensor>>()
|
|
||||||
const loading = ref(false)
|
|
||||||
|
|
||||||
const loadData = async (page = 1, size = 10) => {
|
|
||||||
loading.value = true
|
|
||||||
api.sensorApi.sensor.sensors(
|
|
||||||
{ page: page || sensorPage.value?.current, size: size || sensorPage.value?.size, key: searchKey.value },
|
|
||||||
(data) => {
|
|
||||||
loading.value = false
|
|
||||||
sensorPage.value = data
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
loadData()
|
|
||||||
|
|
||||||
//表格列
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: '设备编号',
|
|
||||||
dataIndex: 'key',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '设备名称',
|
|
||||||
dataIndex: 'name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '设备通道数',
|
|
||||||
dataIndex: 'channels',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
dataIndex: 'operation',
|
|
||||||
width: 400,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
//分页信息
|
|
||||||
const pagination = computed(() => {
|
|
||||||
return {
|
|
||||||
current: sensorPage.value?.current,
|
|
||||||
pageSize: sensorPage.value?.size,
|
|
||||||
total: sensorPage.value?.total,
|
|
||||||
onChange: (page: number, pageSize: number) => {
|
|
||||||
loadData(page, pageSize)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const sensor = ref<Partial<sensor.Sensor>>({})
|
|
||||||
//表单
|
|
||||||
const formDrawer = ref<typeof FormDrawer>()
|
|
||||||
|
|
||||||
const formConfig = computed(() => {
|
|
||||||
return config
|
|
||||||
})
|
|
||||||
//表单配置
|
|
||||||
const items = computed(() => {
|
|
||||||
return formItems
|
|
||||||
})
|
|
||||||
|
|
||||||
//弹窗标题
|
|
||||||
const modalTitle = computed(() => {
|
|
||||||
return sensor.value.id ? '编辑设备' : '添加设备'
|
|
||||||
})
|
|
||||||
|
|
||||||
const addOrEdit = (u?: Record<string, unknown>) => {
|
|
||||||
sensor.value = { ...(u ?? { channels: 3 }) }
|
|
||||||
formDrawer.value?.show()
|
|
||||||
}
|
|
||||||
const doSave = (_data: FormDataType) => {
|
|
||||||
const f = sensor.value.id ? api.sensorApi.sensor.update : api.sensorApi.sensor.add
|
|
||||||
f(_data as unknown as sensor.Sensor, (data) => {
|
|
||||||
console.log(data)
|
|
||||||
formDrawer.value?.close()
|
|
||||||
notification.success({
|
|
||||||
message: '操作成功',
|
|
||||||
description: '设备信息保存成功,页面将自动刷新!',
|
|
||||||
onClose: () => {
|
|
||||||
loadData(1)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const remove = (id: number) => {
|
|
||||||
api.sensorApi.sensor.deleteSensor(id, () => {
|
|
||||||
notification.success({
|
|
||||||
message: '操作成功',
|
|
||||||
description: '设备信息删除成功,页面将自动刷新!',
|
|
||||||
onClose: () => {
|
|
||||||
loadData(1)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentSensor = ref<sensor.Sensor>()
|
|
||||||
const show = ref(false)
|
|
||||||
const showDetail = (_s: sensor.Sensor) => {
|
|
||||||
currentSensor.value = _s
|
|
||||||
show.value = true
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,119 +0,0 @@
|
|||||||
import { FormItem, FormConfig } from '@/components/form-render/form-render-types'
|
|
||||||
|
|
||||||
export const config: FormConfig = {
|
|
||||||
layout: 'horizontal',
|
|
||||||
colon: true,
|
|
||||||
hideRequiredMark: false,
|
|
||||||
labelAlign: 'right',
|
|
||||||
scrollToFirstError: false,
|
|
||||||
validateOnRuleChange: true,
|
|
||||||
labelCol: {
|
|
||||||
span: 4,
|
|
||||||
offset: 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const formItems: FormItem[] = [
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
group: 'auxiliary',
|
|
||||||
properties: {
|
|
||||||
showText: true,
|
|
||||||
type: 'horizontal',
|
|
||||||
orientation: 'left',
|
|
||||||
text: '工位信息',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
group: 'form',
|
|
||||||
type: 'input',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '工位名称',
|
|
||||||
name: 'name',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
type: 'text',
|
|
||||||
allowClear: true,
|
|
||||||
bordered: true,
|
|
||||||
showCount: true,
|
|
||||||
placeholder: '请输入工位名称',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'divider',
|
|
||||||
group: 'auxiliary',
|
|
||||||
properties: {
|
|
||||||
showText: true,
|
|
||||||
type: 'horizontal',
|
|
||||||
orientation: 'left',
|
|
||||||
text: '工位参数',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input-number',
|
|
||||||
group: 'form',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '待机电流',
|
|
||||||
name: 'standby',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
controls: true,
|
|
||||||
placeholder: '请输入待机电流',
|
|
||||||
precision: 2,
|
|
||||||
step: 0.01,
|
|
||||||
addonAfter: 'A',
|
|
||||||
decimalSeparator: '',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input-number',
|
|
||||||
group: 'form',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '工作电流',
|
|
||||||
name: 'working',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
controls: true,
|
|
||||||
placeholder: '请输入工作电流',
|
|
||||||
precision: 2,
|
|
||||||
step: 0.01,
|
|
||||||
addonAfter: 'A',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input-number',
|
|
||||||
group: 'form',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '工作间歇',
|
|
||||||
name: 'maxGap',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
controls: true,
|
|
||||||
placeholder: '请输入最大工作间隙时长',
|
|
||||||
min: 15,
|
|
||||||
step: 1,
|
|
||||||
prefix: '',
|
|
||||||
addonAfter: '秒',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
]
|
|
@ -1,255 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-row :gutter="[16, 16]">
|
|
||||||
<a-col :span="12">
|
|
||||||
<v-chart :loading="monthStatistics.length == 0" class="chart" :option="monthOption" autoresize />
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="12">
|
|
||||||
<v-chart :loading="yearStatistics.length == 0" class="chart" :option="yearOption" autoresize />
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="24">
|
|
||||||
<v-chart :loading="sensorLogs.length == 0" class="chart" :option="sensorOption" autoresize />
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import api from '@/api'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
stationId: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: () => 0,
|
|
||||||
},
|
|
||||||
teamId: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: () => 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const { stationId, teamId } = toRefs(props)
|
|
||||||
const monthStatistics = ref<station.Statistic[]>([])
|
|
||||||
const monthOption = computed(() => {
|
|
||||||
return {
|
|
||||||
title: {
|
|
||||||
text: '月开机/工作',
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
data: ['开机', '工作'],
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '3%',
|
|
||||||
right: '4%',
|
|
||||||
bottom: '3%',
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
toolbox: {
|
|
||||||
feature: {
|
|
||||||
saveAsImage: { title: '保存为图片' },
|
|
||||||
dataView: { title: '数据视图' },
|
|
||||||
magicType: {
|
|
||||||
type: ['line', 'bar'],
|
|
||||||
title: {
|
|
||||||
line: '切换为折线图',
|
|
||||||
bar: '切换为柱状图',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
data: monthStatistics.value.map((s) => s.scale),
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '开机',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
data: monthStatistics.value.map((s) => s.powerHours),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '工作',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
data: monthStatistics.value.map((s) => s.workingHours),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const yearStatistics = ref<station.Statistic[]>([])
|
|
||||||
const yearOption = computed(() => {
|
|
||||||
return {
|
|
||||||
title: {
|
|
||||||
text: '年开机/工作',
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
data: ['开机', '工作'],
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '3%',
|
|
||||||
right: '4%',
|
|
||||||
bottom: '3%',
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
toolbox: {
|
|
||||||
feature: {
|
|
||||||
saveAsImage: { title: '保存为图片' },
|
|
||||||
dataView: { title: '数据视图' },
|
|
||||||
magicType: {
|
|
||||||
type: ['line', 'bar'],
|
|
||||||
title: {
|
|
||||||
line: '切换为折线图',
|
|
||||||
bar: '切换为柱状图',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
data: yearStatistics.value.map((s) => s.scale),
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '开机',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
data: yearStatistics.value.map((s) => s.powerHours),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '工作',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
data: yearStatistics.value.map((s) => s.workingHours),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const sensorLogs = ref<station.SensorLog[]>([])
|
|
||||||
|
|
||||||
const timer = setInterval(() => {
|
|
||||||
api.stationApi.station.sensorLogs(stationId.value, (data) => {
|
|
||||||
sensorLogs.value = data.sort((a, b) => String(a.createdTime)?.localeCompare(String(b.createdTime)))
|
|
||||||
})
|
|
||||||
}, 5000)
|
|
||||||
|
|
||||||
watch(
|
|
||||||
teamId,
|
|
||||||
(val) => {
|
|
||||||
api.stationApi.station.monthStatistics(stationId.value, { teamId: val }, (data) => {
|
|
||||||
monthStatistics.value = data.sort((a, b) => String(a.scale).localeCompare(String(b.scale)))
|
|
||||||
})
|
|
||||||
api.stationApi.station.yearStatistics(stationId.value, { teamId: val }, (data) => {
|
|
||||||
yearStatistics.value = data.sort((a, b) => String(a.scale).localeCompare(String(b.scale)))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
|
|
||||||
const sensorOption = computed(() => {
|
|
||||||
return {
|
|
||||||
title: {
|
|
||||||
text: '设备原始采样',
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
data: ['电流', '电压', '温度'],
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '3%',
|
|
||||||
right: '4%',
|
|
||||||
bottom: '3%',
|
|
||||||
containLabel: true,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
formatter: '{b0}<br> 电流: {c0} A<br /> 电压: {c1} V<br /> 温度: {c2} ℃',
|
|
||||||
},
|
|
||||||
toolbox: {
|
|
||||||
feature: {
|
|
||||||
saveAsImage: { title: '保存为图片' },
|
|
||||||
dataView: { title: '数据视图' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
data: sensorLogs.value.map((l) => l.createdTime?.split(' ')[1]),
|
|
||||||
},
|
|
||||||
yAxis: [
|
|
||||||
{
|
|
||||||
position: 'left',
|
|
||||||
type: 'value',
|
|
||||||
nameLocation: 'start',
|
|
||||||
offset: 60,
|
|
||||||
name: '电流(A)',
|
|
||||||
// show: false,
|
|
||||||
// min: 5,
|
|
||||||
// max: 15,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 'left',
|
|
||||||
type: 'value',
|
|
||||||
name: '电压(V)',
|
|
||||||
// show: false,
|
|
||||||
min: 0,
|
|
||||||
max: 400,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 'right',
|
|
||||||
type: 'value',
|
|
||||||
name: '温度(℃)',
|
|
||||||
// show: false,
|
|
||||||
min: -10,
|
|
||||||
max: 60,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '电流',
|
|
||||||
data: sensorLogs.value.map((l) => l.ampere),
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
yAxisIndex: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '电压',
|
|
||||||
data: sensorLogs.value.map((l) => l.voltage),
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
yAxisIndex: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '温度',
|
|
||||||
data: sensorLogs.value.map((l) => l.temperature),
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
yAxisIndex: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
clearInterval(timer)
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.chart {
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,98 +0,0 @@
|
|||||||
<template>
|
|
||||||
<page-container
|
|
||||||
:tabs="tabs"
|
|
||||||
:current-tab="currentTab"
|
|
||||||
:sub-title="`${station?.name} (传感器:${station?.key} 通道:${station?.channel})`"
|
|
||||||
@tab-changed="tabChanged"
|
|
||||||
>
|
|
||||||
<template #tags>
|
|
||||||
<a-tag :color="status?.powered ? 'processing' : 'warning'">{{ status?.powered ? '已开机' : '未开机' }}</a-tag>
|
|
||||||
<a-tag :color="status?.working ? 'processing' : 'warning'">{{ status?.working ? '焊接中' : '未焊接' }}</a-tag>
|
|
||||||
</template>
|
|
||||||
<template #ops>
|
|
||||||
<a-select
|
|
||||||
v-model:value="team"
|
|
||||||
style="width: 150px"
|
|
||||||
placeholder="请选择班组"
|
|
||||||
:options="options"
|
|
||||||
allow-clear
|
|
||||||
></a-select>
|
|
||||||
</template>
|
|
||||||
<station-charts
|
|
||||||
v-if="station && currentTab === 'charts'"
|
|
||||||
:station-id="station?.id"
|
|
||||||
:team-id="team"
|
|
||||||
></station-charts>
|
|
||||||
<station-power-log
|
|
||||||
v-if="station && currentTab === 'power'"
|
|
||||||
:station-id="station?.id"
|
|
||||||
:team-id="team"
|
|
||||||
></station-power-log>
|
|
||||||
<station-working-log
|
|
||||||
v-if="station && currentTab === 'working'"
|
|
||||||
:station-id="station?.id"
|
|
||||||
:team-id="team"
|
|
||||||
></station-working-log>
|
|
||||||
</page-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import api from '@/api'
|
|
||||||
import { Key } from 'ant-design-vue/es/_util/type'
|
|
||||||
import StationCharts from './station-charts.vue'
|
|
||||||
import StationPowerLog from './station-power-log.vue'
|
|
||||||
import StationWorkingLog from './station-working-log.vue'
|
|
||||||
const teams = ref<station.Team[]>([])
|
|
||||||
api.stationApi.team.teams({}, (data) => {
|
|
||||||
teams.value = data.records ?? []
|
|
||||||
})
|
|
||||||
const options = computed(() => {
|
|
||||||
return teams.value.map((team) => ({
|
|
||||||
label: team.name,
|
|
||||||
value: team.id,
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
const team = ref<number>()
|
|
||||||
const route = useRoute()
|
|
||||||
const key = computed(() => route.params.key)
|
|
||||||
const station = ref<station.Station>()
|
|
||||||
const status = ref<station.StationStatus>()
|
|
||||||
watch(
|
|
||||||
key,
|
|
||||||
(val) => {
|
|
||||||
api.stationApi.station.detail(String(val), (data) => {
|
|
||||||
station.value = data
|
|
||||||
})
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
watch(
|
|
||||||
station,
|
|
||||||
(val) => {
|
|
||||||
if (val?.id) {
|
|
||||||
api.stationApi.stationStatus.detail(val.id, (data) => {
|
|
||||||
status.value = data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: false, deep: true },
|
|
||||||
)
|
|
||||||
const tabs = ref([
|
|
||||||
{
|
|
||||||
key: 'charts',
|
|
||||||
title: '工位数据图表',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'working',
|
|
||||||
title: '焊接记录',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'power',
|
|
||||||
title: '开机记录',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
const currentTab = ref('charts')
|
|
||||||
const tabChanged = (key: Key) => {
|
|
||||||
currentTab.value = key as string
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,314 +0,0 @@
|
|||||||
<template>
|
|
||||||
<page-container>
|
|
||||||
<template #ops>
|
|
||||||
<a-row>
|
|
||||||
<a-col :span="18">
|
|
||||||
<a-input-search
|
|
||||||
v-model:value="searchKey"
|
|
||||||
:placeholder="`请输入设备号/工位名称`"
|
|
||||||
allow-clear
|
|
||||||
enter-button
|
|
||||||
@search="loadData()"
|
|
||||||
></a-input-search>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="6">
|
|
||||||
<a-button type="primary" style="margin-left: 10px" @click="addOrEdit()">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-plus" />
|
|
||||||
</template>
|
|
||||||
添加
|
|
||||||
</a-button>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
|
||||||
<div style="min-height: calc(100vh - 305px)">
|
|
||||||
<a-table
|
|
||||||
:columns="columns"
|
|
||||||
:data-source="stationPage?.records"
|
|
||||||
bordered
|
|
||||||
:pagination="pagination"
|
|
||||||
:loading="loading"
|
|
||||||
row-key="id"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.dataIndex === 'key'">
|
|
||||||
<a-typography-link
|
|
||||||
href="javascript:;"
|
|
||||||
:style="{ color: token.colorPrimary }"
|
|
||||||
@click="showDetail(record as station.Station)"
|
|
||||||
>
|
|
||||||
{{ record.key }}
|
|
||||||
</a-typography-link>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.dataIndex === 'channel'">通道 #{{ record.channel }}</template>
|
|
||||||
<template v-if="column.dataIndex === 'operation'">
|
|
||||||
<a-button type="link" :style="{ color: token.colorPrimary }" @click="addOrEdit(record)">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-edit" />
|
|
||||||
</template>
|
|
||||||
编辑
|
|
||||||
</a-button>
|
|
||||||
<a-popconfirm :title="`确定需要删除设备 ${record.name}(${record.key}) 吗?`" @confirm="remove(record.id)">
|
|
||||||
<a-button type="link" danger style="margin-left: 10px">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-delete" />
|
|
||||||
</template>
|
|
||||||
删除
|
|
||||||
</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</div>
|
|
||||||
</page-container>
|
|
||||||
<form-drawer
|
|
||||||
ref="formDrawer"
|
|
||||||
v-model="station"
|
|
||||||
:form-items="items"
|
|
||||||
:config="formConfig"
|
|
||||||
:title="modalTitle"
|
|
||||||
@ok="doSave"
|
|
||||||
>
|
|
||||||
<template #after-name>
|
|
||||||
<a-row>
|
|
||||||
<a-col :span="12">
|
|
||||||
<a-form-item
|
|
||||||
label="设备绑定"
|
|
||||||
name="key"
|
|
||||||
:rules="[{ required: true, message: '请选择设备' }]"
|
|
||||||
:label-col="{ span: 8 }"
|
|
||||||
>
|
|
||||||
<a-select
|
|
||||||
v-model:value="station.key"
|
|
||||||
show-search
|
|
||||||
placeholder="请输入设备名称/编码"
|
|
||||||
:default-active-first-option="false"
|
|
||||||
:show-arrow="false"
|
|
||||||
:filter-option="false"
|
|
||||||
not-found-content="没有找到设备"
|
|
||||||
:field-names="{ label: 'name', value: 'key' }"
|
|
||||||
allow-clear
|
|
||||||
:options="sensors"
|
|
||||||
@search="handleSearch"
|
|
||||||
></a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="12">
|
|
||||||
<a-form-item
|
|
||||||
label="设备通道"
|
|
||||||
name="channel"
|
|
||||||
:rules="[{ required: true, message: '请选择通道' }]"
|
|
||||||
:label-col="{ span: 8 }"
|
|
||||||
>
|
|
||||||
<a-select
|
|
||||||
v-model:value="station.channel"
|
|
||||||
allow-clear
|
|
||||||
placeholder="请选择设备通道"
|
|
||||||
:options="channels"
|
|
||||||
></a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
|
||||||
<template #after-maxGap>
|
|
||||||
<a-slider
|
|
||||||
v-model:value="range"
|
|
||||||
:tip-formatter="formatter"
|
|
||||||
dots
|
|
||||||
range
|
|
||||||
:marks="marks"
|
|
||||||
:max="station.working ? station.working * 1.1 : 100"
|
|
||||||
:step="station.working ? Math.floor((station.working < 20 ? 20 : station.working) / 20) : 100 / 20"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</form-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import FormDrawer from '@/components/form-render/form-drawer.vue'
|
|
||||||
|
|
||||||
import api from '@/api'
|
|
||||||
import { IPage } from '@/api/api'
|
|
||||||
import { notification, SelectProps, theme } from 'ant-design-vue/es'
|
|
||||||
import { config, formItems } from './form'
|
|
||||||
import { FormDataType } from '@/components/form-render/form-render-types'
|
|
||||||
import { SliderMarks } from 'ant-design-vue/es/slider'
|
|
||||||
const { useToken } = theme
|
|
||||||
const { token } = useToken()
|
|
||||||
const searchKey = ref('')
|
|
||||||
|
|
||||||
const stationPage = ref<IPage<station.Station>>()
|
|
||||||
const loading = ref(false)
|
|
||||||
const loadData = async (page = 1, size = 10) => {
|
|
||||||
loading.value = true
|
|
||||||
api.stationApi.station.stations(
|
|
||||||
{ page: page || stationPage.value?.current, size: size || stationPage.value?.size, key: searchKey.value },
|
|
||||||
(data) => {
|
|
||||||
loading.value = false
|
|
||||||
stationPage.value = data
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
loadData()
|
|
||||||
|
|
||||||
//表格列
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: '设备编号',
|
|
||||||
dataIndex: 'key',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '设备通道',
|
|
||||||
dataIndex: 'channel',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '工位名称',
|
|
||||||
dataIndex: 'name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '待机电流(安培)',
|
|
||||||
dataIndex: 'standby',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '工作电流(安培)',
|
|
||||||
dataIndex: 'working',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '最大工作间歇(秒)',
|
|
||||||
dataIndex: 'maxGap',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
dataIndex: 'operation',
|
|
||||||
width: 400,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
//分页信息
|
|
||||||
const pagination = computed(() => {
|
|
||||||
return {
|
|
||||||
current: stationPage.value?.current,
|
|
||||||
pageSize: stationPage.value?.size,
|
|
||||||
total: stationPage.value?.total,
|
|
||||||
onChange: (page: number, pageSize: number) => {
|
|
||||||
loadData(page, pageSize)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const router = useRouter()
|
|
||||||
const showDetail = (_station: station.Station) => {
|
|
||||||
router.push({ name: 'station-detail', params: { key: _station.uid } })
|
|
||||||
}
|
|
||||||
|
|
||||||
const station = ref<Partial<station.Station>>({})
|
|
||||||
|
|
||||||
const range = computed({
|
|
||||||
get: () => {
|
|
||||||
return [station.value.standby ?? 10, station.value.working ?? 100] as [number, number]
|
|
||||||
},
|
|
||||||
set: (val) => {
|
|
||||||
station.value.standby = val[0]
|
|
||||||
station.value.working = val[1]
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const marks = computed(() => {
|
|
||||||
const standby = station.value.standby ?? 10
|
|
||||||
const working = station.value.working ?? 100
|
|
||||||
const a: SliderMarks = {}
|
|
||||||
a[standby] = `${standby} A`
|
|
||||||
a[working] = `${working} A`
|
|
||||||
return a as SliderMarks
|
|
||||||
})
|
|
||||||
|
|
||||||
const formatter = (value?: number) => {
|
|
||||||
if (value === station.value.standby) {
|
|
||||||
return `待机电流: ${value} A`
|
|
||||||
}
|
|
||||||
if (value === station.value.working) {
|
|
||||||
return `工作触发电流: ${value} A`
|
|
||||||
}
|
|
||||||
return `${value}`
|
|
||||||
}
|
|
||||||
//表单
|
|
||||||
const formDrawer = ref<typeof FormDrawer>()
|
|
||||||
|
|
||||||
const formConfig = computed(() => {
|
|
||||||
return config
|
|
||||||
})
|
|
||||||
//表单配置
|
|
||||||
const items = computed(() => {
|
|
||||||
return formItems
|
|
||||||
})
|
|
||||||
|
|
||||||
//弹窗标题
|
|
||||||
const modalTitle = computed(() => {
|
|
||||||
return station.value.id ? '编辑工位' : '添加工位'
|
|
||||||
})
|
|
||||||
|
|
||||||
const addOrEdit = (u?: Record<string, unknown>) => {
|
|
||||||
station.value = { ...u }
|
|
||||||
formDrawer.value?.show()
|
|
||||||
}
|
|
||||||
const doSave = (_data: FormDataType) => {
|
|
||||||
const f = station.value.id ? api.stationApi.station.update : api.stationApi.station.add
|
|
||||||
f(_data as unknown as station.Station, (data) => {
|
|
||||||
console.log(data)
|
|
||||||
formDrawer.value?.close()
|
|
||||||
notification.success({
|
|
||||||
message: '操作成功',
|
|
||||||
description: '工位信息保存成功,页面将自动刷新!',
|
|
||||||
onClose: () => {
|
|
||||||
loadData(1)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const remove = (id: number) => {
|
|
||||||
api.stationApi.station.deleteStation(id, () => {
|
|
||||||
notification.success({
|
|
||||||
message: '操作成功',
|
|
||||||
description: '工位信息删除成功,页面将自动刷新!',
|
|
||||||
onClose: () => {
|
|
||||||
loadData(1)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const sensors = ref<Array<sensor.Sensor>>([])
|
|
||||||
const handleSearch = (val: string) => {
|
|
||||||
api.sensorApi.sensor.sensors({ key: val }, (data) => {
|
|
||||||
sensors.value = data.records ?? []
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const channels = ref<SelectProps['options']>([])
|
|
||||||
watch(
|
|
||||||
() => {
|
|
||||||
return station.value.key
|
|
||||||
},
|
|
||||||
(val) => {
|
|
||||||
if (val)
|
|
||||||
api.sensorApi.sensor.channels(val, (data) => {
|
|
||||||
channels.value = data.map((item) => {
|
|
||||||
return {
|
|
||||||
label: item.label,
|
|
||||||
value: Number(item.value),
|
|
||||||
disabled: item.disabled,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
{ immediate: true, deep: true },
|
|
||||||
)
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => {
|
|
||||||
return station.value.key
|
|
||||||
},
|
|
||||||
(val) => {
|
|
||||||
if (val) handleSearch(val)
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
</script>
|
|
@ -1,103 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-table
|
|
||||||
:columns="columns"
|
|
||||||
:data-source="powerLogPage?.records"
|
|
||||||
bordered
|
|
||||||
:pagination="pagination"
|
|
||||||
:loading="loading"
|
|
||||||
row-key="id"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.dataIndex === 'teamId'">
|
|
||||||
{{ teams.filter((t) => t.id === record.teamId)[0]?.name }}
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import api from '@/api'
|
|
||||||
import { IPage } from '@/api/api'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
stationId: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: () => 0,
|
|
||||||
},
|
|
||||||
teamId: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: () => 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const { stationId, teamId } = toRefs(props)
|
|
||||||
const powerLogPage = ref<IPage<station.PowerLog>>()
|
|
||||||
const loading = ref(false)
|
|
||||||
const loadData = async (page = 1, size = 10) => {
|
|
||||||
loading.value = true
|
|
||||||
api.stationApi.powerLog.powerLogs(
|
|
||||||
{
|
|
||||||
stationId: stationId.value,
|
|
||||||
teamId: teamId?.value,
|
|
||||||
page: page || powerLogPage.value?.current,
|
|
||||||
size: size || powerLogPage.value?.size,
|
|
||||||
},
|
|
||||||
(data) => {
|
|
||||||
powerLogPage.value = data
|
|
||||||
loading.value = false
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
teamId,
|
|
||||||
() => {
|
|
||||||
loadData()
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
|
|
||||||
const pagination = computed(() => {
|
|
||||||
return {
|
|
||||||
current: powerLogPage.value?.current,
|
|
||||||
pageSize: powerLogPage.value?.size,
|
|
||||||
total: powerLogPage.value?.total,
|
|
||||||
onChange: (page: number, pageSize: number) => {
|
|
||||||
loadData(page, pageSize)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
//表格列
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: '班组',
|
|
||||||
dataIndex: 'teamId',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '日期',
|
|
||||||
dataIndex: 'date',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '开机时间',
|
|
||||||
dataIndex: 'powerOn',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '开机类型',
|
|
||||||
dataIndex: ['powerOnTypeInfo', 'description'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '关机时间',
|
|
||||||
dataIndex: 'powerOff',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '关机类型',
|
|
||||||
dataIndex: ['powerOffTypeInfo', 'description'],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const teams = ref<station.Team[]>([])
|
|
||||||
api.stationApi.team.teams({}, (data) => {
|
|
||||||
teams.value = data.records ?? []
|
|
||||||
})
|
|
||||||
</script>
|
|
@ -1,110 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-table
|
|
||||||
:columns="columns"
|
|
||||||
:data-source="workingLogPage?.records"
|
|
||||||
bordered
|
|
||||||
:pagination="pagination"
|
|
||||||
:loading="loading"
|
|
||||||
row-key="id"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.dataIndex === 'teamId'">
|
|
||||||
{{ teams.filter((t) => t.id === record.teamId)[0]?.name }}
|
|
||||||
</template>
|
|
||||||
<template v-if="column.dataIndex === 'duration'">
|
|
||||||
{{ dayjs(record.end).diff(record.start, 'seconds') + ' 秒' }}
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import api from '@/api'
|
|
||||||
import { IPage } from '@/api/api'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
stationId: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: () => 0,
|
|
||||||
},
|
|
||||||
teamId: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: () => 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const { stationId, teamId } = toRefs(props)
|
|
||||||
const workingLogPage = ref<IPage<station.WorkingLog>>()
|
|
||||||
const loading = ref(false)
|
|
||||||
const loadData = async (page = 1, size = 10) => {
|
|
||||||
loading.value = true
|
|
||||||
api.stationApi.workingLog.workingLogs(
|
|
||||||
{
|
|
||||||
stationId: stationId.value,
|
|
||||||
teamId: teamId?.value,
|
|
||||||
page: page || workingLogPage.value?.current,
|
|
||||||
size: size || workingLogPage.value?.size,
|
|
||||||
},
|
|
||||||
(data) => {
|
|
||||||
workingLogPage.value = data
|
|
||||||
loading.value = false
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
watch(
|
|
||||||
teamId,
|
|
||||||
() => {
|
|
||||||
loadData()
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
|
|
||||||
const pagination = computed(() => {
|
|
||||||
return {
|
|
||||||
current: workingLogPage.value?.current,
|
|
||||||
pageSize: workingLogPage.value?.size,
|
|
||||||
total: workingLogPage.value?.total,
|
|
||||||
onChange: (page: number, pageSize: number) => {
|
|
||||||
loadData(page, pageSize)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
//表格列
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: '班组',
|
|
||||||
dataIndex: 'teamId',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '日期',
|
|
||||||
dataIndex: 'date',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '开始时间',
|
|
||||||
dataIndex: 'start',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '开始类型',
|
|
||||||
dataIndex: ['startTypeInfo', 'description'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '结束时间',
|
|
||||||
dataIndex: 'end',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '结束类型',
|
|
||||||
dataIndex: ['endTypeInfo', 'description'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '持续时间',
|
|
||||||
dataIndex: 'duration',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const teams = ref<station.Team[]>([])
|
|
||||||
api.stationApi.team.teams({}, (data) => {
|
|
||||||
teams.value = data.records ?? []
|
|
||||||
})
|
|
||||||
</script>
|
|
@ -1,70 +0,0 @@
|
|||||||
import { FormItem, FormConfig } from '@/components/form-render/form-render-types'
|
|
||||||
|
|
||||||
export const config: FormConfig = {
|
|
||||||
layout: 'horizontal',
|
|
||||||
colon: true,
|
|
||||||
hideRequiredMark: false,
|
|
||||||
labelAlign: 'right',
|
|
||||||
scrollToFirstError: false,
|
|
||||||
validateOnRuleChange: true,
|
|
||||||
labelCol: {
|
|
||||||
span: 4,
|
|
||||||
offset: 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const formItems: FormItem[] = [
|
|
||||||
{
|
|
||||||
group: 'form',
|
|
||||||
type: 'input',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '班组名称',
|
|
||||||
name: 'name',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
type: 'text',
|
|
||||||
allowClear: false,
|
|
||||||
bordered: true,
|
|
||||||
showCount: false,
|
|
||||||
placeholder: '请填写班组名称',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'time-picker',
|
|
||||||
group: 'form',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '开始时间',
|
|
||||||
name: 'start',
|
|
||||||
required: true,
|
|
||||||
help: '',
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
valueFormat: 'HH:mm:ss',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'time-picker',
|
|
||||||
group: 'form',
|
|
||||||
config: {
|
|
||||||
autoLink: true,
|
|
||||||
hasFeedback: false,
|
|
||||||
label: '结束时间',
|
|
||||||
name: 'end',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
size: 'default',
|
|
||||||
valueFormat: 'HH:mm:ss',
|
|
||||||
},
|
|
||||||
rules: [],
|
|
||||||
},
|
|
||||||
]
|
|
@ -1,172 +0,0 @@
|
|||||||
<template>
|
|
||||||
<page-container>
|
|
||||||
<template #ops>
|
|
||||||
<a-row>
|
|
||||||
<a-col :span="18">
|
|
||||||
<a-input-search
|
|
||||||
v-model:value="searchKey"
|
|
||||||
:placeholder="`请输入班组名称`"
|
|
||||||
allow-clear
|
|
||||||
enter-button
|
|
||||||
@search="loadData()"
|
|
||||||
></a-input-search>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="6">
|
|
||||||
<a-button type="primary" style="margin-left: 10px" @click="addOrEdit()">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-plus" />
|
|
||||||
</template>
|
|
||||||
添加
|
|
||||||
</a-button>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</template>
|
|
||||||
<div style="min-height: calc(100vh - 305px)">
|
|
||||||
<a-table
|
|
||||||
:columns="columns"
|
|
||||||
:data-source="teamPage?.records"
|
|
||||||
bordered
|
|
||||||
:pagination="pagination"
|
|
||||||
:loading="loading"
|
|
||||||
row-key="id"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.dataIndex === 'operation'">
|
|
||||||
<a-button type="link" :style="{ color: token.colorPrimary }" @click="addOrEdit(record)">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-edit" />
|
|
||||||
</template>
|
|
||||||
编辑
|
|
||||||
</a-button>
|
|
||||||
<a-popconfirm :title="`确定需要删除设备 ${record.name} 吗?`" @confirm="remove(record.id)">
|
|
||||||
<a-button type="link" danger style="margin-left: 10px">
|
|
||||||
<template #icon>
|
|
||||||
<icon-font type="icon-delete" />
|
|
||||||
</template>
|
|
||||||
删除
|
|
||||||
</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
</div>
|
|
||||||
</page-container>
|
|
||||||
<form-drawer
|
|
||||||
ref="formDrawer"
|
|
||||||
v-model="team"
|
|
||||||
:form-items="items"
|
|
||||||
:config="formConfig"
|
|
||||||
:title="modalTitle"
|
|
||||||
@ok="doSave"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import FormDrawer from '@/components/form-render/form-drawer.vue'
|
|
||||||
|
|
||||||
import api from '@/api'
|
|
||||||
import { IPage } from '@/api/api'
|
|
||||||
import { config, formItems } from './form'
|
|
||||||
import { FormDataType } from '@/components/form-render/form-render-types'
|
|
||||||
import { notification, theme } from 'ant-design-vue/es'
|
|
||||||
const { useToken } = theme
|
|
||||||
const { token } = useToken()
|
|
||||||
const searchKey = ref('')
|
|
||||||
|
|
||||||
const teamPage = ref<IPage<station.Team>>()
|
|
||||||
const loading = ref(false)
|
|
||||||
const loadData = async (page = 1, size = 10) => {
|
|
||||||
loading.value = true
|
|
||||||
api.stationApi.team.teams(
|
|
||||||
{ page: page || teamPage.value?.current, size: size || teamPage.value?.size, key: searchKey.value },
|
|
||||||
(data) => {
|
|
||||||
loading.value = false
|
|
||||||
teamPage.value = data
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadData()
|
|
||||||
|
|
||||||
//表格列
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: '班组名称',
|
|
||||||
dataIndex: 'name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '开始时间',
|
|
||||||
dataIndex: 'start',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '结束时间',
|
|
||||||
dataIndex: 'end',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
dataIndex: 'operation',
|
|
||||||
width: 400,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
//分页信息
|
|
||||||
const pagination = computed(() => {
|
|
||||||
return {
|
|
||||||
current: teamPage.value?.current,
|
|
||||||
pageSize: teamPage.value?.size,
|
|
||||||
total: teamPage.value?.total,
|
|
||||||
onChange: (page: number, pageSize: number) => {
|
|
||||||
loadData(page, pageSize)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const team = ref<Partial<station.Team>>({})
|
|
||||||
//表单
|
|
||||||
const formDrawer = ref<typeof FormDrawer>()
|
|
||||||
|
|
||||||
const formConfig = computed(() => {
|
|
||||||
return config
|
|
||||||
})
|
|
||||||
//表单配置
|
|
||||||
const items = computed(() => {
|
|
||||||
return formItems
|
|
||||||
})
|
|
||||||
|
|
||||||
//弹窗标题
|
|
||||||
const modalTitle = computed(() => {
|
|
||||||
return team.value.id ? '编辑班组' : '添加班组'
|
|
||||||
})
|
|
||||||
|
|
||||||
const addOrEdit = (u?: Record<string, unknown>) => {
|
|
||||||
team.value = { ...u }
|
|
||||||
formDrawer.value?.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
const doSave = (_data: FormDataType) => {
|
|
||||||
const f = team.value.id ? api.stationApi.team.update : api.stationApi.team.add
|
|
||||||
f(_data as unknown as station.Team, () => {
|
|
||||||
formDrawer.value?.close()
|
|
||||||
notification.success({
|
|
||||||
message: '操作成功',
|
|
||||||
description: '班组信息保存成功,页面将自动刷新!',
|
|
||||||
onClose: () => {
|
|
||||||
loadData(1)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const remove = (id: number) => {
|
|
||||||
api.stationApi.team.deleteTeam(id, () => {
|
|
||||||
notification.success({
|
|
||||||
message: '操作成功',
|
|
||||||
description: '班组信息删除成功,页面将自动刷新!',
|
|
||||||
onClose: () => {
|
|
||||||
loadData(1)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,223 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-card ref="dashboard" :body-style="{ ...style, minHeight: isFullscreen ? '100vh' : '100px' }" :bordered="false">
|
|
||||||
<a-row :gutter="[16, 16]">
|
|
||||||
<a-col :span="4"></a-col>
|
|
||||||
<a-col :span="16" style="text-align: center">
|
|
||||||
<a-typography-title>
|
|
||||||
<span :style="style">{{ currentTeam?.name }}班组数据采集</span>
|
|
||||||
</a-typography-title>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="4">
|
|
||||||
<a-radio-group v-model:value="team" button-style="solid" size="large">
|
|
||||||
<a-radio-button v-for="t in teams" :key="t.id" :value="t.id">{{ t.name }}</a-radio-button>
|
|
||||||
</a-radio-group>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="24">
|
|
||||||
<a-card :body-style="cardStyle" :bordered="false">
|
|
||||||
<a-row justify="center">
|
|
||||||
<a-col :span="4" style="text-align: center">
|
|
||||||
<a-statistic
|
|
||||||
:value="stationStatusStatistic?.powered ?? 0"
|
|
||||||
style="margin-right: 50px"
|
|
||||||
:value-style="{ fontFamily: 'digii', fontSize: '40px', fontWeight: 700, ...cardStyle }"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<span style="font-size: 20px" :style="cardStyle">开机工位</span>
|
|
||||||
</template>
|
|
||||||
<template #suffix>
|
|
||||||
<span>/ {{ stations.length }}</span>
|
|
||||||
</template>
|
|
||||||
</a-statistic>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="4" style="text-align: center">
|
|
||||||
<a-statistic
|
|
||||||
:value="stationStatusStatistic?.working ?? 0"
|
|
||||||
style="margin-right: 50px"
|
|
||||||
:value-style="{ fontFamily: 'digii', fontSize: '40px', fontWeight: 700, ...cardStyle }"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<span style="font-size: 20px" :style="cardStyle">有效工作</span>
|
|
||||||
</template>
|
|
||||||
<template #suffix>
|
|
||||||
<span>/ {{ stations.length }}</span>
|
|
||||||
</template>
|
|
||||||
</a-statistic>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="4" style="text-align: center">
|
|
||||||
<a-statistic
|
|
||||||
:value="XEUtils.commafy(dayStatistic?.powerHours ?? 0, { digits: 3 })"
|
|
||||||
style="margin-right: 50px"
|
|
||||||
:value-style="{ fontFamily: 'digii', fontSize: '40px', fontWeight: 700, ...cardStyle }"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<span style="font-size: 20px" :style="cardStyle">当日开机时长</span>
|
|
||||||
</template>
|
|
||||||
<template #suffix>
|
|
||||||
<span>H</span>
|
|
||||||
</template>
|
|
||||||
</a-statistic>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="4" style="text-align: center">
|
|
||||||
<a-statistic
|
|
||||||
:value="XEUtils.commafy(dayStatistic?.workingHours ?? 0, { digits: 3 })"
|
|
||||||
style="margin-right: 50px"
|
|
||||||
:value-style="{ fontFamily: 'digii', fontSize: '40px', fontWeight: 700, ...cardStyle }"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<span style="font-size: 20px" :style="cardStyle">当日焊接时长</span>
|
|
||||||
</template>
|
|
||||||
<template #suffix>
|
|
||||||
<span>H</span>
|
|
||||||
</template>
|
|
||||||
</a-statistic>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="4" style="text-align: center">
|
|
||||||
<a-statistic
|
|
||||||
:value="XEUtils.commafy(monthStatistic?.powerHours ?? 0, { digits: 3 })"
|
|
||||||
style="margin-right: 50px"
|
|
||||||
:value-style="{ fontFamily: 'digii', fontSize: '40px', fontWeight: 700, ...cardStyle }"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<span style="font-size: 20px" :style="cardStyle">当月开机时长</span>
|
|
||||||
</template>
|
|
||||||
<template #suffix>
|
|
||||||
<span>H</span>
|
|
||||||
</template>
|
|
||||||
</a-statistic>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="4" style="text-align: center">
|
|
||||||
<a-statistic
|
|
||||||
:value="XEUtils.commafy(monthStatistic?.workingHours ?? 0, { digits: 3 })"
|
|
||||||
style="margin-right: 50px"
|
|
||||||
:value-style="{ fontFamily: 'digii', fontSize: '40px', fontWeight: 700, ...cardStyle }"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<span style="font-size: 20px" :style="cardStyle">当月焊接时长</span>
|
|
||||||
</template>
|
|
||||||
<template #suffix>
|
|
||||||
<span>H</span>
|
|
||||||
</template>
|
|
||||||
</a-statistic>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="24">
|
|
||||||
<a-card :body-style="cardStyle" :bordered="false">
|
|
||||||
<a-card-grid
|
|
||||||
v-for="(station, index) in stations"
|
|
||||||
:key="index"
|
|
||||||
:style="{
|
|
||||||
width: '13.8%',
|
|
||||||
marginTop: isFullscreen ? '55px' : '20px',
|
|
||||||
marginBottom: isFullscreen ? '55px' : '20px',
|
|
||||||
marginRight: index % 7 === 6 ? '0.08%' : '0.54%',
|
|
||||||
marginLeft: index % 7 === 0 ? '0.08%' : '0',
|
|
||||||
paddingRight: 0,
|
|
||||||
paddingBottom: 0,
|
|
||||||
paddingTop: '4px',
|
|
||||||
boxShadow:
|
|
||||||
'1px 0 0 0 #1362e5,0 1px 0 0 #1362e5,1px 1px 0 0 #1362e5,1px 0 0 0 #1362e5 inset,0 1px 0 0 #1362e5 inset',
|
|
||||||
...style,
|
|
||||||
}"
|
|
||||||
:bordered="false"
|
|
||||||
>
|
|
||||||
<station-card v-if="team && station" :station="station" :team-id="team"></station-card>
|
|
||||||
</a-card-grid>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import api from '@/api'
|
|
||||||
import StationCard from './station-card.vue'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
import XEUtils from 'xe-utils'
|
|
||||||
const stations = ref<station.Station[]>([])
|
|
||||||
// api.stationApi.station.stations({ page: 1, size: 100 }, (data) => {
|
|
||||||
// stations.value = data.records ?? []
|
|
||||||
// })
|
|
||||||
stations.value = Array.from({ length: 14 }).map((_, index) => ({
|
|
||||||
id: index + 1,
|
|
||||||
name: `工位${index + 1}`,
|
|
||||||
channel: 1,
|
|
||||||
standby: 69.2,
|
|
||||||
working: 23.8,
|
|
||||||
key: '1',
|
|
||||||
maxGap: 15,
|
|
||||||
uid: '',
|
|
||||||
}))
|
|
||||||
const teams = ref<station.Team[]>([])
|
|
||||||
const team = ref<number>()
|
|
||||||
api.stationApi.team.teams({}, (data) => {
|
|
||||||
teams.value = data.records ?? []
|
|
||||||
team.value = teams.value[0].id
|
|
||||||
})
|
|
||||||
const currentTeam = computed(() => teams.value.find((t) => t.id === team.value))
|
|
||||||
const stationStatusStatistic = ref<station.StationStatusStatistic>()
|
|
||||||
const loadStationStatusStatistic = () => {
|
|
||||||
api.stationApi.stationStatus.statistic((data) => {
|
|
||||||
stationStatusStatistic.value = data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const teamStatistics = ref<station.Statistic[]>([])
|
|
||||||
const loadTeamStatistics = (_teamId: number) => {
|
|
||||||
api.stationApi.team.statistics(_teamId, (data) => {
|
|
||||||
teamStatistics.value = data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const timer = ref()
|
|
||||||
const loadData = (_id?: number) => {
|
|
||||||
timer.value = setInterval(() => {
|
|
||||||
loadStationStatusStatistic()
|
|
||||||
if (_id) {
|
|
||||||
loadTeamStatistics(Number(_id))
|
|
||||||
}
|
|
||||||
}, 10000)
|
|
||||||
}
|
|
||||||
watch(
|
|
||||||
team,
|
|
||||||
(val) => {
|
|
||||||
clearInterval(timer.value)
|
|
||||||
loadData(val)
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
clearInterval(timer.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
const dayStatistic = computed(() => {
|
|
||||||
return teamStatistics.value.find((s) => s.scale === dayjs().format('YYYY-MM-DD'))
|
|
||||||
})
|
|
||||||
const monthStatistic = computed(() => {
|
|
||||||
return teamStatistics.value.find((s) => s.scale === dayjs().format('YYYY-MM'))
|
|
||||||
})
|
|
||||||
const dashboard = ref<HTMLElement | null>(null)
|
|
||||||
const { toggle, isFullscreen } = useFullscreen(dashboard)
|
|
||||||
onKeyStroke('ArrowUp', () => {
|
|
||||||
toggle()
|
|
||||||
})
|
|
||||||
const style = computed(() => {
|
|
||||||
return {
|
|
||||||
backgroundColor: '#155bd5',
|
|
||||||
color: '#fff',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const cardStyle = computed(() => {
|
|
||||||
return {
|
|
||||||
backgroundColor: '#1362e5',
|
|
||||||
color: '#fff',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="css" scoped>
|
|
||||||
@font-face {
|
|
||||||
font-family: digii;
|
|
||||||
src: url('/DS-DIGII-3.ttf');
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,161 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-badge-ribbon :text="statusInfo.description" :color="statusInfo.color">
|
|
||||||
<a-card
|
|
||||||
:body-style="{ ...style, boxShadow: 'none' }"
|
|
||||||
:head-style="{
|
|
||||||
...style,
|
|
||||||
padding: '0',
|
|
||||||
}"
|
|
||||||
:style="{ boxShadow: 'none' }"
|
|
||||||
:bordered="false"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<div style="font-size: 20px; font-weight: 800; cursor: pointer" :style="{ ...style }" @click="toDetail">
|
|
||||||
{{ station.name }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<a-descriptions
|
|
||||||
:column="1"
|
|
||||||
:content-style="{ textAlign: 'right', display: 'block', ...style }"
|
|
||||||
:label-style="{ fontSize: '16px', fontWeight: 600, ...style }"
|
|
||||||
>
|
|
||||||
<a-descriptions-item label="日开机">
|
|
||||||
<div class="data-digii">{{ XEUtils.commafy(dayStatistic?.powerHours ?? 0, { digits: 3 }) }}</div>
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="日焊接">
|
|
||||||
<div class="data-digii">{{ XEUtils.commafy(dayStatistic?.workingHours ?? 0, { digits: 3 }) }}</div>
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="月开机">
|
|
||||||
<div class="data-digii">{{ XEUtils.commafy(monthStatistic?.powerHours ?? 0, { digits: 3 }) }}</div>
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="月焊接">
|
|
||||||
<div class="data-digii">{{ XEUtils.commafy(monthStatistic?.workingHours ?? 0, { digits: 3 }) }}</div>
|
|
||||||
</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
|
||||||
<a-descriptions
|
|
||||||
:content-style="{ textAlign: 'right', display: 'block', ...style }"
|
|
||||||
:label-style="{ fontSize: '10px', fontWeight: 600, ...style }"
|
|
||||||
>
|
|
||||||
<a-descriptions-item label="开机">
|
|
||||||
<div class="data-digii-small">{{ XEUtils.commafy(station.standby ?? 0, { digits: 1 }) }} A</div>
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="工作">
|
|
||||||
<div class="data-digii-small">{{ XEUtils.commafy(station.working ?? 0, { digits: 1 }) }} A</div>
|
|
||||||
</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="间隔">
|
|
||||||
<div class="data-digii-small">{{ XEUtils.commafy(station.maxGap ?? 0, { digits: 1 }) }} S</div>
|
|
||||||
</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
|
||||||
</a-card>
|
|
||||||
</a-badge-ribbon>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import api from '@/api'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
import { PropType } from 'vue'
|
|
||||||
import XEUtils from 'xe-utils'
|
|
||||||
const props = defineProps({
|
|
||||||
station: {
|
|
||||||
type: Object as PropType<station.Station>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
teamId: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const { station, teamId } = toRefs(props)
|
|
||||||
|
|
||||||
const statistics = ref<station.Statistic[]>([])
|
|
||||||
const loadTeamStatistics = (_teamId: number) => {
|
|
||||||
api.stationApi.station.statistics(Number(station.value.id), _teamId, (data) => {
|
|
||||||
statistics.value = data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const dayStatistic = computed(() => {
|
|
||||||
return statistics.value.find((s) => s.scale === dayjs().format('YYYY-MM-DD'))
|
|
||||||
})
|
|
||||||
const monthStatistic = computed(() => {
|
|
||||||
return statistics.value.find((s) => s.scale === dayjs().format('YYYY-MM'))
|
|
||||||
})
|
|
||||||
const status = ref<station.StationStatus>()
|
|
||||||
const statusInfo = computed(() => {
|
|
||||||
let color = 'green'
|
|
||||||
let description = '焊接中'
|
|
||||||
if (!status.value?.powered) {
|
|
||||||
color = 'volcano'
|
|
||||||
description = '已关机'
|
|
||||||
} else if (!status.value?.working) {
|
|
||||||
color = 'cyan'
|
|
||||||
description = '待机中'
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
color: color,
|
|
||||||
description: description,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const timer = ref()
|
|
||||||
const loadData = (_id?: number) => {
|
|
||||||
timer.value = setInterval(() => {
|
|
||||||
if (_id) {
|
|
||||||
loadTeamStatistics(_id)
|
|
||||||
api.stationApi.stationStatus.detail(Number(station.value.id), (data) => {
|
|
||||||
status.value = data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, 10000)
|
|
||||||
}
|
|
||||||
watch(
|
|
||||||
teamId,
|
|
||||||
(val) => {
|
|
||||||
if (val) {
|
|
||||||
clearInterval(timer.value)
|
|
||||||
loadData(val)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
clearInterval(timer.value)
|
|
||||||
})
|
|
||||||
const router = useRouter()
|
|
||||||
const toDetail = () => {
|
|
||||||
router.push({ name: 'station-detail', params: { key: station.value.uid } })
|
|
||||||
}
|
|
||||||
const style = computed(() => {
|
|
||||||
return {
|
|
||||||
backgroundColor: '#155bd5',
|
|
||||||
color: '#fff',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="css" scoped>
|
|
||||||
@font-face {
|
|
||||||
font-family: digii;
|
|
||||||
src: url('/DS-DIGII-3.ttf');
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-digii {
|
|
||||||
display: block;
|
|
||||||
padding-right: 24px;
|
|
||||||
font-family: digii, Arial, sans-serif;
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-digii-small {
|
|
||||||
display: block;
|
|
||||||
padding-right: 6px;
|
|
||||||
font-family: digii, Arial, sans-serif;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 600;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.ant-descriptions-header) {
|
|
||||||
box-shadow: '0 1px 2px 0 rgba(0, 0, 0, 0.03),0 1px 6px -1px rgba(0, 0, 0, 0.02),0 2px 4px 0 rgba(0, 0, 0, 0.02)';
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -51,7 +51,7 @@ const props = defineProps({
|
|||||||
const { pageType } = toRefs(props)
|
const { pageType } = toRefs(props)
|
||||||
|
|
||||||
const searchKey = ref('')
|
const searchKey = ref('')
|
||||||
const pagedata = ref<IPage<material.ApplyForm>>()
|
const pagedata = ref<IPage<material.ApplyDTO>>()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
|
|
||||||
@ -59,9 +59,16 @@ const loading = ref(false)
|
|||||||
// 加载数据的方法
|
// 加载数据的方法
|
||||||
const loadData = async (page = 1, size = 10) => {
|
const loadData = async (page = 1, size = 10) => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
api.materialApi.apply.applies(
|
api.materialApi.apply.searchPage(
|
||||||
//1: 采购入库 2: 归还入库 3: 出库外借
|
//1: 采购入库 2: 归还入库 3: 出库外借
|
||||||
{ type: 1, page: page || pagedata.value?.current, size: size || pagedata.value?.size, key: searchKey.value },
|
{
|
||||||
|
applyType: 1,
|
||||||
|
page: page || pagedata.value?.current,
|
||||||
|
size: size || pagedata.value?.size,
|
||||||
|
type: searchKey.value,
|
||||||
|
code: searchKey.value,
|
||||||
|
name: searchKey.value
|
||||||
|
},
|
||||||
(data) => {
|
(data) => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
pagedata.value = data
|
pagedata.value = data
|
||||||
|
@ -70,7 +70,7 @@ const props = defineProps(
|
|||||||
}
|
}
|
||||||
} // 申请类型 applyType页面传值的使用1和2,1: 采购入库 和 归还入库 2: 出库外借
|
} // 申请类型 applyType页面传值的使用1和2,1: 采购入库 和 归还入库 2: 出库外借
|
||||||
)
|
)
|
||||||
const getTableData = () => {
|
const getTableData = ()=> {
|
||||||
const $table = tableRef.value
|
const $table = tableRef.value
|
||||||
return $table?.getTableData().fullData;
|
return $table?.getTableData().fullData;
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ const formData = ref<FormData>({
|
|||||||
|
|
||||||
|
|
||||||
// vxe-table相关的设置
|
// vxe-table相关的设置
|
||||||
interface RowVO {
|
export interface RowVO {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
code: string
|
code: string
|
||||||
@ -112,7 +112,7 @@ interface RowVO {
|
|||||||
quantity: number
|
quantity: number
|
||||||
disabled: boolean
|
disabled: boolean
|
||||||
checked: boolean
|
checked: boolean
|
||||||
assignRule: number
|
assignRule: string
|
||||||
}
|
}
|
||||||
const tableRef = ref<VxeTableInstance<RowVO>>()
|
const tableRef = ref<VxeTableInstance<RowVO>>()
|
||||||
// vxe-table 数据结果
|
// vxe-table 数据结果
|
||||||
@ -145,7 +145,7 @@ const insertEvent = (value: any) => {
|
|||||||
spec: m.spec ? m.spec : '未知',
|
spec: m.spec ? m.spec : '未知',
|
||||||
type: m.type ? m.type : '未知',
|
type: m.type ? m.type : '未知',
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
assignRule: m.assignRule ? m.assignRule : 1,
|
assignRule: m.assignRule ? m.assignRule : 'HIGH_VALUE',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
checked: false
|
checked: false
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import applyForm from '../component/applyForm.vue'
|
import applyForm,{RowVO} from '../component/applyForm.vue'
|
||||||
import scanForm from '../component/scanForm.vue'
|
import scanForm from '../component/scanForm.vue'
|
||||||
import applyConfirm from '../component/applyConfirm.vue'
|
import applyConfirm from '../component/applyConfirm.vue'
|
||||||
import successResul from '../component/successResul.vue'
|
import successResul from '../component/successResul.vue'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
|
||||||
// 和外层界面的数据交互
|
// 和外层界面的数据交互
|
||||||
defineProps(
|
defineProps(
|
||||||
{
|
{
|
||||||
@ -66,7 +65,7 @@
|
|||||||
totalValue.value = 0
|
totalValue.value = 0
|
||||||
// 再step1中点击下一步的时候,就去获取step1中的表单数据
|
// 再step1中点击下一步的时候,就去获取step1中的表单数据
|
||||||
selectData.value = applyFormRef.value.getTableData()
|
selectData.value = applyFormRef.value.getTableData()
|
||||||
selectData.value.forEach((item) => {
|
selectData.value.forEach((item:RowVO) => {
|
||||||
if (item.assignRule === 'HIGH_VALUE') {
|
if (item.assignRule === 'HIGH_VALUE') {
|
||||||
totalValue.value += item.quantity
|
totalValue.value += item.quantity
|
||||||
}
|
}
|
||||||
@ -75,7 +74,7 @@
|
|||||||
if (scanFormRef.value && current.value === 1) {
|
if (scanFormRef.value && current.value === 1) {
|
||||||
// 再step2中点击下一步的时候,就去获取step2中的表单数据
|
// 再step2中点击下一步的时候,就去获取step2中的表单数据
|
||||||
const items = scanFormRef.value.getTableData()
|
const items = scanFormRef.value.getTableData()
|
||||||
const groupedSums = items.reduce((acc, item) => {
|
const groupedSums = items.reduce((acc:any, item:RowVO) => {
|
||||||
if (!acc[item.code]) {
|
if (!acc[item.code]) {
|
||||||
acc[item.code] = 0
|
acc[item.code] = 0
|
||||||
}
|
}
|
||||||
@ -83,7 +82,7 @@
|
|||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
// 组装步骤三的原始数据
|
// 组装步骤三的原始数据
|
||||||
conformData.value = selectData.value.map((item) => {
|
conformData.value = selectData.value.map((item :RowVO) => {
|
||||||
return {
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
|
@ -138,7 +138,11 @@ const removeStep2Row = async (row: TableRowVO) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function beiginScan() {
|
function beiginScan() {
|
||||||
input.value?.focus()
|
// input.value?.focus()
|
||||||
|
const el = input.value as HTMLInputElement | null;
|
||||||
|
if (el) {
|
||||||
|
el.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击开始扫码按钮,自动新增一行 或者 扫码结束后也自动新增一行
|
// 点击开始扫码按钮,自动新增一行 或者 扫码结束后也自动新增一行
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user