---初始化后台管理web页面项目

This commit is contained in:
2025-08-20 14:39:30 +08:00
parent ad49711a7e
commit 87545a8baf
2057 changed files with 282864 additions and 213 deletions

View File

@ -0,0 +1,234 @@
<template>
<PageWrapper dense fixedHeight contentFullHeight>
<BasicTableErp @register="registerTable">
<template #toolbar>
<a-button type="primary" @click="handleExport"> {{ t('导出') }} </a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex == 'level'">
<a-tag :color="getLevel(record.level)">
{{ levelData.filter((x) => x.id === record.level)[0]?.name }}
</a-tag>
</template>
<template v-if="column.dataIndex == 'state'">
<span :style="`color:${record.state === 1 ? '#67c23a' : '#F56C6C'}`">
{{ record.state === 1 ? '已处理' : '待处理' }}
</span>
</template>
<template v-if="column.dataIndex == 'action'">
<TableAction
:actions="[
{
label: '查看',
onClick: handleView.bind(null, record),
},
{
label: '处理',
onClick: handleDispose.bind(null, record),
},
{
label: '删除',
color: 'error',
onClick: handleDelete.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTableErp>
<AlarmModal @register="registerModal" @success="reload" />
<AlarmInfomation @register="registerCheckModal" />
</PageWrapper>
</template>
<script lang="ts" setup>
import { createVNode, onMounted, ref } from 'vue';
import { useTable, TableAction, BasicColumn, FormSchema } from '/@/components/Table';
import BasicTableErp from '/@/components/Table/src/BasicTableErp.vue';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageWrapper } from '/@/components/Page';
import { getDeviceAlarmPageList, deleteDeviceAlarm, exportInfo } from '/@/api/erp/device/alarm';
import { getDicDetailList } from '/@/api/system/dic';
import { useI18n } from '/@/hooks/web/useI18n';
import { Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { downloadByData } from '/@/utils/file/download';
import AlarmModal from './components/AlarmModal.vue';
import AlarmInfomation from './components/AlarmInfomation.vue';
const { t } = useI18n();
const columns: BasicColumn[] = [
{
title: '设备编号',
dataIndex: 'number',
width: 100,
},
{
title: '设备名称',
dataIndex: 'name',
width: 100,
},
{
title: '设备类型',
dataIndex: 'typeName',
width: 100,
},
{
title: '设备位置',
dataIndex: 'address',
width: 100,
},
{
title: '规格型号',
dataIndex: 'model',
width: 100,
},
{
title: '故障等级',
dataIndex: 'level',
width: 100,
},
{
title: '故障描述',
dataIndex: 'remark',
width: 150,
},
{
title: '负责人',
dataIndex: 'dealUserNames',
width: 100,
},
{
title: '告警时间',
dataIndex: 'createDate',
width: 150,
},
{
title: '处理状态',
dataIndex: 'state',
width: 100,
},
];
const searchFormSchema: FormSchema[] = [
{
field: 'typeId',
label: '设备类型',
component: 'XjrSelect',
colProps: { span: 8 },
componentProps: {
datasourceType: 'dic',
params: { itemId: '1671412696707850241' },
labelField: 'name',
valueField: 'id',
placeholder: '请选择设备类型',
getPopupContainer: () => document.body,
},
},
{
field: 'state',
label: '状态',
component: 'Select',
colProps: { span: 8 },
componentProps: {
placeholder: '请选择状态',
options: [
{ label: '已处理', value: 1 },
{ label: '待处理', value: 0 },
],
},
},
{
field: 'createDate',
label: '告警时间',
component: 'RangePicker',
colProps: { span: 8 },
componentProps: {
format: 'YYYY-MM-DD',
},
},
];
const levelData = ref<Recordable[]>([]);
const { notification } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerCheckModal, { openModal: openCheckModal }] = useModal();
const [registerTable, { reload }] = useTable({
title: '设备告警',
api: getDeviceAlarmPageList,
rowKey: 'id',
columns,
formConfig: {
rowProps: {
gutter: 16,
},
schemas: searchFormSchema,
fieldMapToTime: [['createDate', ['startTime', 'endTime'], 'YYYY-MM-DD', true]],
},
useSearchForm: true,
showTableSetting: true,
striped: false,
actionColumn: {
width: 140,
title: t('操作'),
dataIndex: 'action',
slots: { customRender: 'action' },
},
});
onMounted(async () => {
levelData.value = (await getDicDetailList({ itemId: '1679372182895345665' })) || [];
});
const getLevel = (level) => {
const data = levelData.value.filter((x) => x.id === level);
if (!data.length) return '';
switch (data[0].value) {
case '0':
return 'error';
case '1':
return 'warning';
case '2':
return 'processing';
}
};
const handleDispose = (record) => {
openModal(true, {
id: record.id,
});
};
const handleView = (record) => {
openCheckModal(true, {
id: record.id,
});
};
const handleDelete = (record) => {
Modal.confirm({
title: t('提示信息'),
icon: createVNode(ExclamationCircleOutlined),
content: t('是否确认删除?'),
okText: t('确认'),
cancelText: t('取消'),
async onOk() {
await deleteDeviceAlarm(record.id);
notification.success({
message: t('提示'),
description: t('删除成功'),
});
reload();
},
onCancel() {},
});
};
const handleExport = async () => {
const res = await exportInfo();
downloadByData(
res.data,
'设备告警.xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
);
};
</script>

View File

@ -0,0 +1,222 @@
<template>
<PageWrapper dense fixedHeight contentFullHeight>
<BasicTableErp @register="registerTable">
<template #toolbar>
<a-button type="primary" @click="handleCreate"> {{ t('新增') }} </a-button>
<a-button type="primary" @click="handleExport"> {{ t('导出') }} </a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex == 'state'">
<span :style="`color:${record.state === 1 ? '#67c23a' : '#F56C6C'}`">
{{ record.state === 1 ? '正常' : '异常' }}
</span>
</template>
<template v-if="column.dataIndex == 'action'">
<TableAction
:actions="[
{
icon: 'ant-design:eye-outlined',
onClick: handleView.bind(null, record),
},
{
icon: 'clarity:note-edit-line',
onClick: handleEdit.bind(null, record),
},
{
icon: 'ant-design:delete-outlined',
color: 'error',
onClick: handleDelete.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTableErp>
<InfomationModal @register="registerModal" @success="reload" />
<InfomationCheckModal @register="registerCheckModal" />
</PageWrapper>
</template>
<script lang="ts" setup>
import { createVNode } from 'vue';
import { useTable, TableAction, BasicColumn, FormSchema } from '/@/components/Table';
import BasicTableErp from '/@/components/Table/src/BasicTableErp.vue';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageWrapper } from '/@/components/Page';
import { getDeviceInfoPageList, deleteDeviceInfo, exportInfo } from '/@/api/erp/device/info';
import { useI18n } from '/@/hooks/web/useI18n';
import { Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { downloadByData } from '/@/utils/file/download';
import InfomationModal from './components/InfomationModal.vue';
import InfomationCheckModal from './components/InfomationCheckModal.vue';
const { t } = useI18n();
const columns: BasicColumn[] = [
{
title: '设备编号',
dataIndex: 'number',
},
{
title: '设备名称',
dataIndex: 'name',
},
{
title: '设备类型',
dataIndex: 'typeName',
},
{
title: '供应商',
dataIndex: 'supplierName',
},
{
title: '设备位置',
dataIndex: 'address',
},
{
title: '规格型号',
dataIndex: 'model',
},
{
title: '负责人',
dataIndex: 'principalNames',
},
{
title: '设备状态',
dataIndex: 'state',
},
];
const searchFormSchema: FormSchema[] = [
{
field: 'typeId',
label: '设备类型',
component: 'XjrSelect',
colProps: { span: 8 },
componentProps: {
datasourceType: 'dic',
params: { itemId: '1671412696707850241' },
labelField: 'name',
valueField: 'id',
placeholder: '请选择设备类型',
getPopupContainer: () => document.body,
},
},
{
field: 'name',
label: '设备名称',
component: 'Input',
colProps: { span: 8 },
componentProps: {
placeholder: '请输入设备名称',
},
},
{
field: 'address',
label: '设备位置',
component: 'Input',
colProps: { span: 8 },
componentProps: {
placeholder: '请输入设备位置',
},
},
];
const { notification } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerCheckModal, { openModal: openCheckModal }] = useModal();
const customRow = (record) => {
return {
onClick: () => {
let selectedRowKeys = [...getSelectRowKeys()];
if (selectedRowKeys.indexOf(record.id) >= 0) {
let index = selectedRowKeys.indexOf(record.id);
selectedRowKeys.splice(index, 1);
} else {
selectedRowKeys.push(record.id);
}
setSelectedRowKeys(selectedRowKeys);
},
};
};
const [registerTable, { reload, setSelectedRowKeys, getSelectRowKeys }] = useTable({
title: '设备信息',
api: getDeviceInfoPageList,
rowKey: 'id',
columns,
formConfig: {
rowProps: {
gutter: 16,
},
schemas: searchFormSchema,
},
useSearchForm: true,
showTableSetting: true,
striped: false,
actionColumn: {
width: 120,
title: t('操作'),
dataIndex: 'action',
slots: { customRender: 'action' },
},
rowSelection: {
type: 'checkbox',
},
customRow,
});
const handleCreate = () => {
openModal(true, {
isUpdate: false,
});
};
const handleEdit = (record) => {
openModal(true, {
id: record.id,
isUpdate: true,
});
};
const handleView = (record) => {
openCheckModal(true, {
id: record.id,
});
};
const handleDelete = (record) => {
Modal.confirm({
title: t('提示信息'),
icon: createVNode(ExclamationCircleOutlined),
content: t('是否确认删除?'),
okText: t('确认'),
cancelText: t('取消'),
async onOk() {
await deleteDeviceInfo(record.id);
notification.success({
message: t('提示'),
description: t('删除成功'),
});
reload();
},
onCancel() {},
});
};
const handleExport = async () => {
if (!getSelectRowKeys().length) {
notification.warning({
message: 'Tip',
description: '请选择需要导出的数据',
});
return false;
}
const res = await exportInfo(getSelectRowKeys());
downloadByData(
res.data,
'设备信息.xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
);
};
</script>

View File

@ -0,0 +1,212 @@
<template>
<PageWrapper dense fixedHeight contentFullHeight>
<BasicTableErp @register="registerTable">
<template #toolbar>
<a-button type="primary" @click="handleCreate"> {{ t('新增') }} </a-button>
<a-button type="primary" @click="handleExport"> {{ t('导出') }} </a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex == 'state'">
<span :style="`color:${record.state === 1 ? '#67c23a' : '#F56C6C'}`">
{{ record.state === 1 ? '已完成' : '待维修' }}
</span>
</template>
<template v-if="column.dataIndex == 'action'">
<TableAction
:actions="[
{
icon: 'ant-design:eye-outlined',
onClick: handleView.bind(null, record),
},
{
icon: 'clarity:note-edit-line',
onClick: handleEdit.bind(null, record),
},
{
icon: 'ant-design:delete-outlined',
color: 'error',
onClick: handleDelete.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTableErp>
<InspectModal @register="registerModal" @success="reload" />
<InspectInfomation @register="registerCheckModal" />
</PageWrapper>
</template>
<script lang="ts" setup>
import { createVNode } from 'vue';
import { useTable, TableAction, BasicColumn, FormSchema } from '/@/components/Table';
import BasicTableErp from '/@/components/Table/src/BasicTableErp.vue';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageWrapper } from '/@/components/Page';
import {
getDeviceInspectPageList,
deleteDeviceInspect,
exportInfo,
} from '/@/api/erp/device/inspect';
import { useI18n } from '/@/hooks/web/useI18n';
import { Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { downloadByData } from '/@/utils/file/download';
import InspectModal from './components/InspectModal.vue';
import InspectInfomation from './components/InspectInfomation.vue';
const { t } = useI18n();
const columns: BasicColumn[] = [
{
title: '设备编号',
dataIndex: 'number',
},
{
title: '设备名称',
dataIndex: 'name',
},
{
title: '设备类型',
dataIndex: 'typeName',
width: 100,
},
{
title: '规格型号',
dataIndex: 'model',
width: 100,
},
{
title: '设备位置',
dataIndex: 'address',
},
{
title: '巡检结果',
dataIndex: 'result',
},
{
title: '巡检人',
dataIndex: 'checkedUserNames',
},
{
title: '巡检时间',
dataIndex: 'date',
width: 100,
},
{
title: '巡检状态',
dataIndex: 'state',
width: 100,
},
];
const searchFormSchema: FormSchema[] = [
{
field: 'typeId',
label: '设备类型',
component: 'XjrSelect',
colProps: { span: 8 },
componentProps: {
datasourceType: 'dic',
params: { itemId: '1671412696707850241' },
labelField: 'name',
valueField: 'id',
placeholder: '请选择设备类型',
getPopupContainer: () => document.body,
},
},
{
field: 'name',
label: '设备名称',
component: 'Input',
colProps: { span: 8 },
componentProps: {
placeholder: '请输入设备类型',
},
},
{
field: 'state',
label: '状态',
component: 'Select',
colProps: { span: 8 },
componentProps: {
placeholder: '请选择状态',
options: [
{ label: '已完成', value: 1 },
{ label: '未维修', value: 0 },
],
},
},
];
const { notification } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerCheckModal, { openModal: openCheckModal }] = useModal();
const [registerTable, { reload }] = useTable({
title: '设备巡检',
api: getDeviceInspectPageList,
rowKey: 'id',
columns,
formConfig: {
rowProps: {
gutter: 16,
},
schemas: searchFormSchema,
},
useSearchForm: true,
showTableSetting: true,
striped: false,
actionColumn: {
width: 120,
title: t('操作'),
dataIndex: 'action',
slots: { customRender: 'action' },
},
});
const handleCreate = () => {
openModal(true, {
isUpdate: false,
});
};
const handleEdit = (record) => {
openModal(true, {
id: record.id,
isUpdate: true,
});
};
const handleView = (record) => {
openCheckModal(true, {
id: record.id,
});
};
const handleDelete = (record) => {
Modal.confirm({
title: t('提示信息'),
icon: createVNode(ExclamationCircleOutlined),
content: t('是否确认删除?'),
okText: t('确认'),
cancelText: t('取消'),
async onOk() {
await deleteDeviceInspect(record.id);
notification.success({
message: t('提示'),
description: t('删除成功'),
});
reload();
},
onCancel() {},
});
};
const handleExport = async () => {
const res = await exportInfo();
downloadByData(
res.data,
'设备巡检.xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
);
};
</script>

View File

@ -0,0 +1,83 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="查看告警">
<a-row>
<a-col :span="24">处理人{{ alarmtInfo?.dealUserNames }}</a-col>
<a-col :span="24">故障等级{{ alarmtInfo?.levelName }}</a-col>
<a-col :span="24">故障描述{{ alarmtInfo?.remark }}</a-col>
<a-col :span="24">处理方法{{ alarmtInfo?.dealWay }}</a-col>
<a-col :span="24">处理日期{{ alarmtInfo?.date }}</a-col>
</a-row>
<a-divider />
<div class="img-box">
附件
<a-image-preview-group v-if="imgList.length">
<a-image v-for="(item, index) in imgList" :key="index" :src="item.fileUrl" />
</a-image-preview-group>
<span v-else>暂无附件</span>
</div>
<div class="img-title">
<img :src="`/src/assets/erp/${imgSrc}.png`" />
</div>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { getDeviceAlarmCheck } from '/@/api/erp/device/alarm';
import { getFileList } from '/@/api/system/file';
const rowId = ref('');
const alarmtInfo = ref();
const imgList = ref<any>([]);
const imgSrc = ref('');
defineEmits(['register']);
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
setModalProps({
confirmLoading: false,
destroyOnClose: true,
showCancelBtn: false,
showOkBtn: false,
footer: null,
width: 500,
});
rowId.value = data.id;
alarmtInfo.value = await getDeviceAlarmCheck(data.id);
imgSrc.value = alarmtInfo.value?.state === 0 ? 'check_tip_no1' : 'check_tip_pass1';
if (alarmtInfo.value.filePath) {
imgList.value = await getFileList({ folderId: alarmtInfo.value.filePath });
}
});
</script>
<style lang="less" scoped>
.ant-col {
margin-bottom: 15px;
}
.img-title {
position: absolute;
top: 10px;
right: 30px;
width: 100px;
}
.img-box {
display: flex;
align-items: center;
margin-bottom: 10px;
}
:deep(.ant-image) {
width: 100px;
height: 75px;
padding: 5px;
border: 1px solid silver;
border-radius: 4px;
margin-right: 10px;
}
:deep(.ant-image-img) {
height: 100%;
}
</style>

View File

@ -0,0 +1,135 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="处理告警" @ok="handleSubmit">
<BasicForm @register="registerForm">
<template #user="{ model }">
<SelectUser
v-model:value="model.dealUserIds"
suffix="ant-design:setting-outlined"
placeholder="请选择处理人"
/>
</template>
<template #upload="{ model }">
<Upload v-model:value="model.filePath" listType="picture" />
</template>
</BasicForm>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { FormSchema } from '/@/components/Table';
import { updateDeviceAlarm, getDeviceAlarmInfo } from '/@/api/erp/device/alarm';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import SelectUser from '/@/components/Form/src/components/SelectUser.vue';
import Upload from '/@/components/Form/src/components/Upload.vue';
const { t } = useI18n();
const FormSchema: FormSchema[] = [
{
field: 'dealUserIds',
label: '处理人',
component: 'Input',
slot: 'user',
required: true,
colProps: { span: 24 },
},
{
field: 'level',
label: '故障等级',
component: 'DicSelect',
colProps: { span: 24 },
componentProps: {
placeholder: '请选择故障等级',
itemId: '1679372182895345665',
isShowAdd: false,
disabled: true,
},
},
{
field: 'remark',
label: '故障描述',
component: 'Input',
colProps: { span: 24 },
componentProps: {
placeholder: '请输入故障描述',
disabled: true,
},
},
{
field: 'dealWay',
label: '处理方法',
component: 'InputTextArea',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请输入处理方法',
},
},
{
field: 'filePath',
label: '附件',
component: 'Upload',
slot: 'upload',
colProps: { span: 24 },
},
{
field: 'state',
label: '选择状态',
component: 'RadioGroup',
required: true,
colProps: { span: 24 },
componentProps: {
options: [
{ label: '已处理', value: 1 },
{ label: '待处理', value: 0 },
],
},
},
];
const { notification } = useMessage();
const rowId = ref('');
const emit = defineEmits(['success', 'register']);
const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
labelWidth: 100,
schemas: FormSchema,
showActionButtonGroup: false,
actionColOptions: {
span: 23,
},
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
resetFields();
setModalProps({ confirmLoading: false, destroyOnClose: true });
rowId.value = data.id;
const record = await getDeviceAlarmInfo(data.id);
setFieldsValue({
...record,
});
});
const handleSubmit = async () => {
try {
const values = await validate();
setModalProps({ confirmLoading: true });
values.id = rowId.value;
await updateDeviceAlarm(values);
notification.success({
message: '处理告警',
description: t('成功'),
});
closeModal();
emit('success');
} catch (error) {
setModalProps({ confirmLoading: false });
}
};
</script>

View File

@ -0,0 +1,193 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="查看设备详情">
<a-row>
<a-col class="title">基础信息</a-col>
</a-row>
<a-row>
<a-col :span="12">设备编号{{ deviceInfo?.number }}</a-col>
<a-col
align="right"
:style="`color:${deviceInfo?.state === 1 ? '#67c23a' : '#F56C6C'}`"
class="state"
:span="11"
>
状态{{ deviceInfo?.state === 1 ? '正常' : '异常' }}
</a-col>
</a-row>
<a-row>
<a-col :span="12">设备类型{{ deviceInfo?.typeName }}</a-col>
<a-col :span="12">设备名称{{ deviceInfo?.name }}</a-col>
</a-row>
<a-row>
<a-col :span="12">设备位置{{ deviceInfo?.address }}</a-col>
<a-col :span="12">设备供应商{{ deviceInfo?.supplierName }}</a-col>
</a-row>
<a-row>
<a-col :span="12">规格型号{{ deviceInfo?.model }}</a-col>
<a-col :span="12">购买日期{{ deviceInfo?.buyDate }}</a-col>
</a-row>
<a-row>
<a-col :span="12">维保日期{{ deviceInfo?.maintainDate }}</a-col>
<a-col :span="12">报废日期{{ deviceInfo?.scrapDate }}</a-col>
</a-row>
<a-row>
<a-col>负责人{{ deviceInfo?.principalNames }}</a-col>
</a-row>
<a-row>
<a-col class="title">运行状况</a-col>
</a-row>
<a-row>
<a-col :span="10" align="center">
<div ref="gaute" style="height: 240px"></div>
<span>实时运行速度m/s</span>
</a-col>
<a-col :span="14">
<div ref="linechart" style="height: 300px"></div>
</a-col>
</a-row>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { checkDeviceInfo } from '/@/api/erp/device/info';
import * as echarts from 'echarts';
const rowId = ref('');
const deviceInfo = ref();
const gaute = ref<HTMLDivElement>();
const linechart = ref<HTMLDivElement>();
const gauteOption = {
series: [
{
type: 'gauge',
radius: '88%',
center: ['50%', '60%'],
axisLine: {
lineStyle: {
width: 20,
color: [
[0.3, '#67e0e3'],
[0.7, '#37a2da'],
[1, '#fd666d'],
],
},
},
pointer: {
itemStyle: {
color: 'auto',
},
},
axisTick: {
distance: -20,
length: 8,
lineStyle: {
color: '#fff',
width: 2,
},
},
splitLine: {
distance: -20,
length: 30,
lineStyle: {
color: '#fff',
width: 4,
},
},
axisLabel: {
color: 'auto',
distance: 15,
fontSize: 12,
},
detail: {
valueAnimation: true,
color: 'auto',
},
title: {
offsetCenter: [0, '-50%'],
},
data: [
{
value: 70,
name: 'm',
},
],
},
],
};
const linechartOption = {
color: ['#00CACF'],
title: {
text: '生产效率',
textStyle: {
fontSize: 14,
},
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['4:00', '8:00', '12:00', '16:00', '20:00', '24:00'],
},
yAxis: {
type: 'value',
name: '单位:个',
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330],
type: 'line',
smooth: true,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(0, 202, 207, 0.6)',
},
{
offset: 1,
color: 'rgba(255, 255, 255, 0)',
},
]),
},
},
],
};
defineEmits(['register']);
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
setModalProps({
confirmLoading: false,
destroyOnClose: true,
showCancelBtn: false,
showOkBtn: false,
width: 800,
fixedHeight: true,
});
rowId.value = data.id;
deviceInfo.value = await checkDeviceInfo(data.id);
const myChartGaute = echarts.init(unref(gaute) as HTMLDivElement);
myChartGaute.setOption(gauteOption);
myChartGaute.resize(); //显示区域大小发生改变更新图表
const myChartLinechart = echarts.init(unref(linechart) as HTMLDivElement);
myChartLinechart.setOption(linechartOption);
myChartLinechart.resize(); //显示区域大小发生改变更新图表
});
</script>
<style lang="less" scoped>
.ant-row {
margin-bottom: 15px;
.title {
font-size: 16px;
font-weight: bold;
margin-top: 5px;
}
.state {
font-size: 16px;
}
}
</style>

View File

@ -0,0 +1,189 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
<BasicForm @register="registerForm">
<template #user="{ model }">
<SelectUser
v-model:value="model.principalIds"
suffix="ant-design:setting-outlined"
placeholder="请选择负责人"
/>
</template>
</BasicForm>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { FormSchema } from '/@/components/Table';
import { addDeviceInfo, updateDeviceInfo, getDeviceInfo } from '/@/api/erp/device/info';
import { getSupplierList } from '/@/api/erp/supplier/list';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import SelectUser from '/@/components/Form/src/components/SelectUser.vue';
const { t } = useI18n();
const FormSchema: FormSchema[] = [
{
field: 'typeId',
label: '设备类型',
component: 'DicSelect',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请选择设备类型',
itemId: '1671412696707850241',
isShowAdd: false,
},
},
{
field: 'number',
label: '设备编号',
component: 'Input',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请输入设备编号',
},
},
{
field: 'name',
label: '设备名称',
component: 'Input',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请输入设备名称',
},
},
{
field: 'model',
label: '规格型号',
component: 'Input',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请输入规格型号',
},
},
{
field: 'supplierId',
label: '供应商',
component: 'ApiSelect',
colProps: { span: 24 },
componentProps: {
placeholder: '请选择供应商',
api: getSupplierList,
labelField: 'name',
valueField: 'id',
getPopupContainer: () => document.body,
},
},
{
field: 'buyDate',
label: '购买日期',
component: 'DatePicker',
colProps: { span: 24 },
componentProps: {
format: 'YYYY-MM-DD',
placeholder: '请选择购买日期',
},
},
{
field: 'maintainDate',
label: '维保日期',
component: 'DatePicker',
required: true,
colProps: { span: 24 },
componentProps: {
format: 'YYYY-MM-DD',
placeholder: '请选择维保日期',
},
},
{
field: 'scrapDate',
label: '报废日期',
component: 'DatePicker',
required: true,
colProps: { span: 24 },
componentProps: {
format: 'YYYY-MM-DD',
placeholder: '请选择报废日期',
},
},
{
field: 'principalIds',
label: '负责人',
component: 'Input',
slot: 'user',
required: true,
colProps: { span: 24 },
},
{
field: 'address',
label: '设备位置',
component: 'Input',
colProps: { span: 24 },
componentProps: {
placeholder: '请输入设备位置',
},
},
];
const { notification } = useMessage();
const isUpdate = ref(true);
const rowId = ref('');
const emit = defineEmits(['success', 'register']);
const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
labelWidth: 100,
schemas: FormSchema,
showActionButtonGroup: false,
actionColOptions: {
span: 23,
},
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
resetFields();
setModalProps({ confirmLoading: false, destroyOnClose: true });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
rowId.value = data.id;
const record = await getDeviceInfo(data.id);
setFieldsValue({
...record,
});
}
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备'));
const handleSubmit = async () => {
try {
const values = await validate();
setModalProps({ confirmLoading: true });
if (!unref(isUpdate)) {
await addDeviceInfo(values);
notification.success({
message: '新增设备',
description: t('成功'),
});
} else {
values.id = rowId.value;
await updateDeviceInfo(values);
notification.success({
message: '编辑设备',
description: t('成功'),
});
}
closeModal();
emit('success');
} catch (error) {
setModalProps({ confirmLoading: false });
}
};
</script>

View File

@ -0,0 +1,86 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="巡检通知单">
<a-row>
<a-col :span="24">巡检人{{ inspectInfo?.checkedUserNames }}</a-col>
<a-col :span="24">检查性质{{ inspectInfo?.natureName }}</a-col>
<a-col :span="24">检查设备{{ inspectInfo?.name }}</a-col>
<a-col :span="24">设备编号{{ inspectInfo?.number }}</a-col>
<a-col :span="24">设备位置{{ inspectInfo?.address }}</a-col>
<a-col :span="24">规格型号{{ inspectInfo?.model }}</a-col>
<a-col :span="24">检查日期{{ inspectInfo?.date }}</a-col>
<a-col :span="24">检查结果{{ inspectInfo?.result }}</a-col>
</a-row>
<a-divider />
<div class="img-box">
图片资料
<a-image-preview-group v-if="imgList.length">
<a-image v-for="(item, index) in imgList" :key="index" :src="item.fileUrl" />
</a-image-preview-group>
<span v-else>暂无图片</span>
</div>
<div class="img-title">
<img :src="`/src/assets/erp/${imgSrc}.png`" />
</div>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { getDeviceInspectInfo } from '/@/api/erp/device/inspect';
import { getFileList } from '/@/api/system/file';
const rowId = ref('');
const inspectInfo = ref();
const imgList = ref<any>([]);
const imgSrc = ref('');
defineEmits(['register']);
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
setModalProps({
confirmLoading: false,
destroyOnClose: true,
showCancelBtn: false,
showOkBtn: false,
footer: null,
width: 500,
});
rowId.value = data.id;
inspectInfo.value = await getDeviceInspectInfo(data.id);
imgSrc.value = inspectInfo.value?.state === 0 ? 'check_tip_no' : 'check_tip_pass';
if (inspectInfo.value.filePath) {
imgList.value = await getFileList({ folderId: inspectInfo.value.filePath });
}
});
</script>
<style lang="less" scoped>
.ant-col {
margin-bottom: 15px;
}
.img-title {
position: absolute;
top: 10px;
right: 30px;
width: 100px;
}
.img-box {
display: flex;
align-items: center;
margin-bottom: 10px;
}
:deep(.ant-image) {
width: 100px;
height: 75px;
padding: 5px;
border: 1px solid silver;
border-radius: 4px;
margin-right: 10px;
}
:deep(.ant-image-img) {
height: 100%;
}
</style>

View File

@ -0,0 +1,219 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
<BasicForm @register="registerForm">
<template #user="{ model }">
<SelectUser
v-model:value="model.checkedUserIds"
suffix="ant-design:setting-outlined"
placeholder="请选择巡检人"
/>
</template>
<template #upload="{ model }">
<Upload v-model:value="model.filePath" listType="picture" />
</template>
</BasicForm>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { FormSchema } from '/@/components/Table';
import {
addDeviceInspect,
updateDeviceInspect,
getDeviceInspectInfo,
} from '/@/api/erp/device/inspect';
import { getDeviceInfoByTypeId } from '/@/api/erp/device/info';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import SelectUser from '/@/components/Form/src/components/SelectUser.vue';
import Upload from '/@/components/Form/src/components/Upload.vue';
const { t } = useI18n();
const FormSchema: FormSchema[] = [
{
field: 'typeId',
label: '设备类型',
component: 'DicSelect',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请选择设备类型',
itemId: '1671412696707850241',
isShowAdd: false,
onChange: (value) => {
if (value) {
updateSchema({
field: 'deviceId',
componentProps: {
placeholder: '请选择设备名称',
api: getDeviceInfoByTypeId,
params: value,
labelField: 'name',
valueField: 'id',
getPopupContainer: () => document.body,
},
});
}
},
},
},
{
field: 'number',
label: '设备编号',
component: 'Input',
colProps: { span: 24 },
componentProps: {
placeholder: '请输入设备编号',
disabled: true,
},
},
{
field: 'deviceId',
label: '设备名称',
component: 'ApiSelect',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请选择设备名称',
onChange: (_, option) => {
setFieldsValue({ number: option?.number, model: option?.model });
},
},
},
{
field: 'model',
label: '规格型号',
component: 'Input',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请输入规格型号',
disabled: true,
},
},
{
field: 'checkedUserIds',
label: '巡检人',
component: 'Input',
slot: 'user',
required: true,
colProps: { span: 24 },
},
{
field: 'date',
label: '巡检时间',
component: 'DatePicker',
required: true,
colProps: { span: 24 },
componentProps: {
format: 'YYYY-MM-DD',
placeholder: '请选择巡检时间',
},
},
{
field: 'natureId',
label: '检查性质',
component: 'DicSelect',
required: true,
colProps: { span: 24 },
componentProps: {
placeholder: '请选择检查性质',
itemId: '1679045876047552513',
isShowAdd: false,
},
},
{
field: 'result',
label: '检查结果',
component: 'InputTextArea',
colProps: { span: 24 },
componentProps: {
placeholder: '请输入检查结果',
},
},
{
field: 'filePath',
label: '上传附件',
component: 'Upload',
slot: 'upload',
colProps: { span: 24 },
},
{
field: 'state',
label: '选择状态',
component: 'RadioGroup',
// slot: 'state',
colProps: { span: 24 },
componentProps: {
options: [
{ label: '通过', value: 1 },
{ label: '未通过', value: 0 },
],
},
},
];
const { notification } = useMessage();
const isUpdate = ref(true);
const rowId = ref('');
const emit = defineEmits(['success', 'register']);
const [registerForm, { setFieldsValue, resetFields, validate, updateSchema }] = useForm({
labelWidth: 100,
schemas: FormSchema,
showActionButtonGroup: false,
actionColOptions: {
span: 23,
},
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
resetFields();
setModalProps({ confirmLoading: false, destroyOnClose: true });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
rowId.value = data.id;
const record = await getDeviceInspectInfo(data.id);
setFieldsValue({
...record,
});
} else {
setFieldsValue({
state: 1,
});
}
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增巡检' : '编辑巡检'));
const handleSubmit = async () => {
try {
const values = await validate();
setModalProps({ confirmLoading: true });
if (!unref(isUpdate)) {
await addDeviceInspect(values);
notification.success({
message: '新增巡检',
description: t('成功'),
});
} else {
values.id = rowId.value;
await updateDeviceInspect(values);
notification.success({
message: '编辑巡检',
description: t('成功'),
});
}
closeModal();
emit('success');
} catch (error) {
setModalProps({ confirmLoading: false });
}
};
</script>