|
|
@@ -1,43 +1,41 @@
|
|
|
<template>
|
|
|
<ContentWrap>
|
|
|
- <el-tabs
|
|
|
- v-model="activeTab"
|
|
|
- type="border-card"
|
|
|
- tab-position="left"
|
|
|
- v-loading="loading"
|
|
|
- style="height: 84vh"
|
|
|
- >
|
|
|
- <el-tab-pane style="height: 100%" v-for="(item, index) in list" :key="index">
|
|
|
+ <el-tabs type="border-card" tab-position="left" v-loading="loading" style="height: 84vh">
|
|
|
+ <el-tab-pane
|
|
|
+ style="height: 100%"
|
|
|
+ v-for="(deviceItem, deviceIndex) in list"
|
|
|
+ :key="deviceIndex"
|
|
|
+ >
|
|
|
<template #label>
|
|
|
<span
|
|
|
- :class="['custom-label', { 'has-border': item.deviceName === '生产日报' }]"
|
|
|
- v-if="item.isFill === 1"
|
|
|
+ :class="['custom-label', { 'has-border': deviceItem.deviceName === '生产日报' }]"
|
|
|
+ v-if="deviceItem.isFill === 1"
|
|
|
@click="
|
|
|
openFill(
|
|
|
- item.deviceCategoryId,
|
|
|
- item.deviceId,
|
|
|
- item.deptId,
|
|
|
- item.deviceName,
|
|
|
- item.deviceCode
|
|
|
+ deviceItem.deviceCategoryId,
|
|
|
+ deviceItem.deviceId,
|
|
|
+ deviceItem.deptId,
|
|
|
+ deviceItem.deviceName,
|
|
|
+ deviceItem.deviceCode
|
|
|
)
|
|
|
"
|
|
|
>
|
|
|
- {{ item.deviceCode }} ({{ item.deviceName }})
|
|
|
+ {{ deviceItem.deviceCode }} ({{ deviceItem.deviceName }})
|
|
|
</span>
|
|
|
<span
|
|
|
- :class="['custom-label1', { 'has-border': item.deviceName === '生产日报' }]"
|
|
|
+ :class="['custom-label1', { 'has-border': deviceItem.deviceName === '生产日报' }]"
|
|
|
v-else
|
|
|
@click="
|
|
|
openFill(
|
|
|
- item.deviceCategoryId,
|
|
|
- item.deviceId,
|
|
|
- item.deptId,
|
|
|
- item.deviceName,
|
|
|
- item.deviceCode
|
|
|
+ deviceItem.deviceCategoryId,
|
|
|
+ deviceItem.deviceId,
|
|
|
+ deviceItem.deptId,
|
|
|
+ deviceItem.deviceName,
|
|
|
+ deviceItem.deviceCode
|
|
|
)
|
|
|
"
|
|
|
>
|
|
|
- {{ item.deviceCode }} ({{ item.deviceName }})
|
|
|
+ {{ deviceItem.deviceCode }} ({{ deviceItem.deviceName }})
|
|
|
</span>
|
|
|
</template>
|
|
|
<div class="form-wrapper">
|
|
|
@@ -51,14 +49,18 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item :label="t('operationFillForm.team')" class="custom-label1">
|
|
|
<span style="text-decoration: underline">
|
|
|
- {{ item.orgName }}
|
|
|
+ {{ deviceItem.orgName }}
|
|
|
</span>
|
|
|
</el-form-item>
|
|
|
<el-row :gutter="20">
|
|
|
- <el-col v-for="(item, index) in attrList1" :key="index" :span="24">
|
|
|
- <el-form-item :label="item.name" class="custom-label1">
|
|
|
+ <el-col
|
|
|
+ v-for="(summaryItem, summaryIndex) in attrList1"
|
|
|
+ :key="summaryIndex"
|
|
|
+ :span="24"
|
|
|
+ >
|
|
|
+ <el-form-item :label="summaryItem.name" class="custom-label1">
|
|
|
<span style="text-decoration: underline">
|
|
|
- {{ item.totalRunTime }}
|
|
|
+ {{ summaryItem.totalRunTime }}
|
|
|
</span>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
@@ -71,9 +73,14 @@
|
|
|
</el-form>
|
|
|
</div>
|
|
|
|
|
|
- <div v-for="(item, index) in attrList" :key="index" style="margin-left: 24px">
|
|
|
+ <div
|
|
|
+ v-for="(attrItem, attrIndex) in attrList"
|
|
|
+ :key="attrIndex"
|
|
|
+ style="margin-left: 24px"
|
|
|
+ >
|
|
|
+ {{ attrItem }}
|
|
|
<!-- 添加提示文字 -->
|
|
|
- <div v-if="item.isCollection === 1" class="plc-tip">
|
|
|
+ <div v-if="attrItem.isCollection === 1" class="plc-tip">
|
|
|
<el-alert
|
|
|
:title="t('operationFillForm.alert')"
|
|
|
type="warning"
|
|
|
@@ -83,28 +90,28 @@
|
|
|
style="width: 320px"
|
|
|
/>
|
|
|
</div>
|
|
|
- <el-form-item :label="item.name" prop="deviceId" label-position="top">
|
|
|
+ <el-form-item :label="attrItem.name" prop="deviceId" label-position="top">
|
|
|
<div v-if="fillStatus === '1'">
|
|
|
<el-select
|
|
|
disabled
|
|
|
- v-model="item.fillContent"
|
|
|
- v-if="item.type === 'enum' && item.description !== null"
|
|
|
+ v-model="attrItem.fillContent"
|
|
|
+ v-if="attrItem.type === 'enum' && attrItem.description !== null"
|
|
|
style="width: 200px"
|
|
|
>
|
|
|
<el-option
|
|
|
- v-for="dict in item.name === '非生产原因'
|
|
|
- ? getIntDictOptions(item.description)
|
|
|
- : getStrDictOptions(item.description)"
|
|
|
+ v-for="dict in attrItem.name === '非生产原因'
|
|
|
+ ? getIntDictOptions(attrItem.description)
|
|
|
+ : getStrDictOptions(attrItem.description)"
|
|
|
:key="dict.label"
|
|
|
:label="dict.label"
|
|
|
:value="
|
|
|
- item.name === '非生产原因' ? Number(dict.value) : dict.value.toString()
|
|
|
+ attrItem.name === '非生产原因' ? Number(dict.value) : dict.value.toString()
|
|
|
"
|
|
|
/>
|
|
|
</el-select>
|
|
|
<el-input
|
|
|
v-else
|
|
|
- v-model="item.fillContent"
|
|
|
+ v-model="attrItem.fillContent"
|
|
|
clearable
|
|
|
style="width: 200px; margin-right: 10px"
|
|
|
disabled
|
|
|
@@ -112,40 +119,42 @@
|
|
|
</div>
|
|
|
|
|
|
<el-input
|
|
|
- v-else-if="item.type === 'textarea'"
|
|
|
- v-model="item.fillContent"
|
|
|
+ v-else-if="attrItem.type === 'textarea'"
|
|
|
+ v-model="attrItem.fillContent"
|
|
|
type="textarea"
|
|
|
clearable
|
|
|
style="width: 200px"
|
|
|
/>
|
|
|
<el-select
|
|
|
- v-model="item.fillContent"
|
|
|
+ v-model="attrItem.fillContent"
|
|
|
clearable
|
|
|
- v-else-if="item.type === 'enum' && item.description !== null"
|
|
|
+ v-else-if="attrItem.type === 'enum' && attrItem.description !== null"
|
|
|
style="width: 200px"
|
|
|
filterable
|
|
|
>
|
|
|
<el-option
|
|
|
- v-for="dict in item.name === '非生产原因'
|
|
|
- ? getIntDictOptions(item.description)
|
|
|
- : getStrDictOptions(item.description)"
|
|
|
+ v-for="dict in attrItem.name === '非生产原因'
|
|
|
+ ? getIntDictOptions(attrItem.description)
|
|
|
+ : getStrDictOptions(attrItem.description)"
|
|
|
:key="dict.label"
|
|
|
:label="dict.label"
|
|
|
- :value="item.name === '非生产原因' ? Number(dict.value) : dict.value.toString()"
|
|
|
+ :value="
|
|
|
+ attrItem.name === '非生产原因' ? Number(dict.value) : dict.value.toString()
|
|
|
+ "
|
|
|
/>
|
|
|
</el-select>
|
|
|
<el-input
|
|
|
v-else
|
|
|
- v-model="item.fillContent"
|
|
|
+ v-model="attrItem.fillContent"
|
|
|
clearable
|
|
|
style="width: 200px"
|
|
|
:placeholder="
|
|
|
- item.type === 'double'
|
|
|
+ attrItem.type === 'double'
|
|
|
? t('operationFillForm.enterNumber')
|
|
|
: t('operationFillForm.enterContent')
|
|
|
"
|
|
|
- @input="handleInput(item)"
|
|
|
- :maxlength="item.type === 'double' ? calculateMaxLength(item) : undefined"
|
|
|
+ @input="handleInput(attrItem)"
|
|
|
+ :maxlength="attrItem.type === 'double' ? calculateMaxLength(attrItem) : undefined"
|
|
|
/>
|
|
|
</el-form-item>
|
|
|
</div>
|
|
|
@@ -165,17 +174,10 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { dateFormatter2 } from '@/utils/formatTime'
|
|
|
-import download from '@/utils/download'
|
|
|
import { IotOpeationFillApi, IotOpeationFillVO } from '@/api/pms/iotopeationfill'
|
|
|
-import IotOpeationFillForm from './IotOpeationFillForm.vue'
|
|
|
-import Vue from '@vitejs/plugin-vue'
|
|
|
-import { useUserStore } from '@/store/modules/user'
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
import moment from 'moment'
|
|
|
-import { format } from 'date-fns'
|
|
|
-import { cx } from '@fullcalendar/core/internal-common'
|
|
|
-import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
|
|
|
+import { getIntDictOptions, getStrDictOptions } from '@/utils/dict'
|
|
|
import { useRoute } from 'vue-router'
|
|
|
|
|
|
/** 运行记录填报 列表 */
|
|
|
@@ -188,18 +190,18 @@ const { t } = useI18n() // 国际化
|
|
|
/** 提交表单 */
|
|
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
|
|
const loading = ref(true) // 列表的加载中
|
|
|
-const { params, name } = useRoute() // 查询参数
|
|
|
-const deptId = params.id
|
|
|
+const { params } = useRoute() // 查询参数
|
|
|
+const deptId = params.id as string
|
|
|
const list = ref<IotOpeationFillVO[]>([]) // 列表的数据
|
|
|
const attrList = ref<IotOpeationFillVO[]>([]) // 非累计属性集合
|
|
|
const attrList1 = ref<IotOpeationFillVO[]>([]) // 累计属性集合
|
|
|
const attrList2 = ref<IotOpeationFillVO[]>([]) // 属性集合
|
|
|
let companyName = ref('')
|
|
|
|
|
|
-let fillStatus = params.id.split(',')[4]
|
|
|
+let fillStatus = deptId.split(',')[4]
|
|
|
let createTime = formatTimestamp(JSON.parse(deptId.split(',')[2].substring(0, 10)))
|
|
|
let showStatus = true
|
|
|
-const queryParams = reactive({
|
|
|
+const queryParams = reactive<any>({
|
|
|
pageNo: 1,
|
|
|
pageSize: 10,
|
|
|
deviceCode: undefined,
|
|
|
@@ -237,9 +239,10 @@ const calculateMaxLength = (item: any) => {
|
|
|
}
|
|
|
|
|
|
// 简单的节流函数,避免提示信息过于频繁
|
|
|
-const throttle = (fn: Function, delay: number) => {
|
|
|
+const throttle = <T extends (...args: any[]) => any>(fn: T, delay: number) => {
|
|
|
let lastTime = 0
|
|
|
- return function (...args: any[]) {
|
|
|
+
|
|
|
+ return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
|
|
|
const now = Date.now()
|
|
|
if (now - lastTime >= delay) {
|
|
|
fn.apply(this, args)
|
|
|
@@ -277,11 +280,11 @@ const getList = async () => {
|
|
|
}
|
|
|
}
|
|
|
function formatTimestamp(timestamp) {
|
|
|
- const date = new Date(timestamp * 1000)
|
|
|
+ // const date = new Date(timestamp * 1000)
|
|
|
return moment.unix(timestamp).format('YYYY-MM-DD')
|
|
|
}
|
|
|
|
|
|
-const open = async (type: string, id?: number) => {
|
|
|
+const open = async (_type: string, id?: number) => {
|
|
|
alert(id)
|
|
|
}
|
|
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
|
@@ -381,7 +384,7 @@ const getAttrList = async () => {
|
|
|
})
|
|
|
|
|
|
// 为非累计数据添加最大值限制
|
|
|
- attrList.value.forEach(function (item, index) {
|
|
|
+ attrList.value.forEach(function (item) {
|
|
|
if (item.fillContent !== '' && item.fillContent !== null) {
|
|
|
const num = Number(item.fillContent)
|
|
|
if (!isNaN(num)) {
|
|
|
@@ -421,7 +424,7 @@ const getAttrList = async () => {
|
|
|
console.log(item.fillContent)
|
|
|
})
|
|
|
|
|
|
- attrList1.value.forEach(function (item, index) {
|
|
|
+ attrList1.value.forEach(function (item) {
|
|
|
item.deviceCode = queryParams.deviceCode
|
|
|
item.deptId = queryParams.deptId
|
|
|
item.deviceId = queryParams.deviceId
|
|
|
@@ -485,11 +488,8 @@ const getFillInfo = async () => {
|
|
|
const confirmResult = await message.confirm(
|
|
|
exceededMessage,
|
|
|
'以下填报项超出限制,是否继续保存?',
|
|
|
- {
|
|
|
- confirmButtonText: '继续保存',
|
|
|
- cancelButtonText: '取消',
|
|
|
- type: 'warning'
|
|
|
- }
|
|
|
+ '继续保存',
|
|
|
+ '取消'
|
|
|
)
|
|
|
if (!confirmResult) {
|
|
|
return // 用户取消保存
|
|
|
@@ -499,7 +499,7 @@ const getFillInfo = async () => {
|
|
|
|
|
|
attrList2.value = attrList.value.concat(attrList1.value)
|
|
|
|
|
|
- attrList2.value.forEach(function (item, index) {
|
|
|
+ attrList2.value.forEach(function (item) {
|
|
|
item.pointName = item.name
|
|
|
item.createTime = formatTimestamp(JSON.parse(deptId.split(',')[2].substring(0, 10)))
|
|
|
item.userId = deptId.split(',')[1]
|
|
|
@@ -519,7 +519,7 @@ const getFillInfo = async () => {
|
|
|
|
|
|
/**清空填写信息*/
|
|
|
const deleteFillInfo = () => {
|
|
|
- attrList.value.forEach(function (item, index) {
|
|
|
+ attrList.value.forEach(function (item) {
|
|
|
item.fillContent = ''
|
|
|
})
|
|
|
}
|
|
|
@@ -537,10 +537,12 @@ onMounted(async () => {
|
|
|
.scrollable-form {
|
|
|
/* 设置最大高度,超过这个高度会出现滚动条 */
|
|
|
max-height: 500px; /* 根据你的需求调整 */
|
|
|
- /* 超出部分显示垂直滚动条 */
|
|
|
- overflow-y: auto;
|
|
|
+
|
|
|
/* 可选:添加内边距和边框美化 */
|
|
|
padding: 16px;
|
|
|
+
|
|
|
+ /* 超出部分显示垂直滚动条 */
|
|
|
+ overflow-y: auto;
|
|
|
border: 1px solid #e5e7eb;
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
@@ -568,9 +570,11 @@ onMounted(async () => {
|
|
|
/* 红色背景 */
|
|
|
background-color: red;
|
|
|
}
|
|
|
+
|
|
|
.back-blue {
|
|
|
background-color: grey;
|
|
|
}
|
|
|
+
|
|
|
.step-container {
|
|
|
display: grid;
|
|
|
grid-template-columns: 220px 1fr;
|
|
|
@@ -580,15 +584,15 @@ onMounted(async () => {
|
|
|
}
|
|
|
|
|
|
.steps-nav {
|
|
|
- overflow-y: auto;
|
|
|
padding-right: 15px;
|
|
|
+ overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
.form-wrapper {
|
|
|
- background: #fff;
|
|
|
padding: 30px;
|
|
|
+ background: #fff;
|
|
|
border-radius: 8px;
|
|
|
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
|
|
+ box-shadow: 0 2px 12px rgb(0 0 0 / 10%);
|
|
|
}
|
|
|
|
|
|
.navigation-controls {
|
|
|
@@ -597,33 +601,37 @@ onMounted(async () => {
|
|
|
}
|
|
|
|
|
|
.custom-label {
|
|
|
- font-weight: 1000;
|
|
|
- font-size: 17px;
|
|
|
padding: 0 10px;
|
|
|
+ font-size: 17px;
|
|
|
+ font-weight: 1000;
|
|
|
color: forestgreen;
|
|
|
}
|
|
|
+
|
|
|
.custom-label1 {
|
|
|
- font-weight: 1000;
|
|
|
- font-size: 17px;
|
|
|
padding: 0 10px;
|
|
|
+ font-size: 17px;
|
|
|
+ font-weight: 1000;
|
|
|
}
|
|
|
+
|
|
|
.has-border {
|
|
|
- border: 2px solid #333; /* 加粗到2px,使用深灰色#333让边框更清晰 */
|
|
|
padding: 3px 8px; /* 适当增加内边距,避免文字太贴近边框 */
|
|
|
- border-radius: 2px; /* 轻微圆角,可选 */
|
|
|
font-size: 20px;
|
|
|
+ border: 2px solid #333; /* 加粗到2px,使用深灰色#333让边框更清晰 */
|
|
|
+ border-radius: 2px; /* 轻微圆角,可选 */
|
|
|
}
|
|
|
+
|
|
|
::v-deep .el-step__icon {
|
|
|
- background-color: #409eff;
|
|
|
color: #fff;
|
|
|
- border: 0px;
|
|
|
+ background-color: #409eff;
|
|
|
+ border: 0;
|
|
|
}
|
|
|
+
|
|
|
.step-title-wrapper {
|
|
|
+ position: relative;
|
|
|
display: inline-flex;
|
|
|
+ padding-right: 25px;
|
|
|
align-items: center;
|
|
|
gap: 8px;
|
|
|
- position: relative;
|
|
|
- padding-right: 25px;
|
|
|
}
|
|
|
|
|
|
/* 覆盖步骤条默认样式 */
|
|
|
@@ -636,8 +644,8 @@ onMounted(async () => {
|
|
|
/* 标题容器定位 */
|
|
|
.el-step__title {
|
|
|
display: inline-block;
|
|
|
- margin-left: 10px;
|
|
|
padding-right: 0;
|
|
|
+ margin-left: 10px;
|
|
|
}
|
|
|
|
|
|
/* 步骤连接线 */
|
|
|
@@ -668,10 +676,11 @@ onMounted(async () => {
|
|
|
flex: 1; /* 等宽分布 */
|
|
|
min-width: 200px; /* 最小宽度防止挤压 */
|
|
|
}
|
|
|
+
|
|
|
/* 新增日报填报项的边框样式 */
|
|
|
.report-border {
|
|
|
- border: 2px solid #42b983; /* 使用Vue标志性的绿色边框 */
|
|
|
padding: 2px 4px;
|
|
|
+ border: 2px solid #42b983; /* 使用Vue标志性的绿色边框 */
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
</style>
|