|
|
@@ -1,165 +1,153 @@
|
|
|
<template>
|
|
|
- <ContentWrap v-loading="formLoading">
|
|
|
- <ContentWrap>
|
|
|
- <el-form
|
|
|
- ref="formRef"
|
|
|
- :model="formData"
|
|
|
- :rules="formRules"
|
|
|
- style="margin-right: 4em; margin-left: 0.5em; margin-top: 1em"
|
|
|
- label-width="130px"
|
|
|
- >
|
|
|
- <div class="base-expandable-content">
|
|
|
- <el-row>
|
|
|
- <el-col :span="12">
|
|
|
+ <div v-loading="formLoading" class="operation-plan-page">
|
|
|
+ <section class="info-card">
|
|
|
+ <div class="info-card__header">
|
|
|
+ <div class="info-card__title">
|
|
|
+ <span class="info-card__marker"></span>
|
|
|
+ <span>基础信息</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="info-card__body">
|
|
|
+ <el-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="formRules"
|
|
|
+ size="default"
|
|
|
+ label-position="top"
|
|
|
+ class="operation-plan-form">
|
|
|
+ <div class="operation-plan-form__grid">
|
|
|
+ <div class="form-cell">
|
|
|
<el-form-item :label="t('main.planName')" prop="planTitle">
|
|
|
<el-input v-model="formData.planTitle" :placeholder="t('main.nameHolder')" />
|
|
|
</el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :span="12">
|
|
|
+ </div>
|
|
|
+ <div class="form-cell">
|
|
|
<el-form-item :label="t('workOrderMaterial.unit')" prop="planUnit">
|
|
|
<el-select
|
|
|
v-model="formData.planUnit"
|
|
|
:placeholder="t('route.unitHolder')"
|
|
|
:disabled="formType === 'update'"
|
|
|
clearable
|
|
|
- >
|
|
|
+ class="w-full">
|
|
|
<el-option
|
|
|
v-for="dict in getStrDictOptions(DICT_TYPE.PMS_INSPECT_UNIT)"
|
|
|
:key="dict.label"
|
|
|
:label="dict.label"
|
|
|
- :value="dict.value"
|
|
|
- />
|
|
|
+ :value="dict.value" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :span="12">
|
|
|
+ </div>
|
|
|
+ <div class="form-cell">
|
|
|
<el-form-item :label="t('route.cycle')" prop="planCycle">
|
|
|
<el-input-number
|
|
|
- style="width: 100%"
|
|
|
v-model="formData.planCycle"
|
|
|
:precision="0"
|
|
|
:min="1"
|
|
|
:max="99999"
|
|
|
- />
|
|
|
+ class="!w-full" />
|
|
|
</el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :span="12">
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-cell form-cell--start-time">
|
|
|
<el-form-item :label="t('route.beginCreateTime')" prop="beginCreateTime">
|
|
|
<el-date-picker
|
|
|
- style="width: 150%"
|
|
|
v-model="formData.beginCreateTime"
|
|
|
type="datetime"
|
|
|
value-format="x"
|
|
|
- />
|
|
|
+ class="!w-full" />
|
|
|
</el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :span="12">
|
|
|
+ </div>
|
|
|
+ <div class="form-cell form-cell--report">
|
|
|
<el-form-item label="日报填报" prop="isReport">
|
|
|
<el-radio-group v-model="formData.isReport">
|
|
|
<el-radio
|
|
|
v-for="dict in getIntDictOptions(DICT_TYPE.RQ_IOT_ISCOLLECTION)"
|
|
|
:key="dict.value"
|
|
|
- :value="dict.value"
|
|
|
- >
|
|
|
+ :value="dict.value">
|
|
|
{{ dict.label }}
|
|
|
</el-radio>
|
|
|
</el-radio-group>
|
|
|
</el-form-item>
|
|
|
- </el-col>
|
|
|
-
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item :label="t('form.remark')" prop="remark">
|
|
|
- <el-input type="textarea" v-model="formData.remark" />
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
- </div>
|
|
|
- </el-form>
|
|
|
- </ContentWrap>
|
|
|
-
|
|
|
- <ContentWrap>
|
|
|
- <!-- 列表 -->
|
|
|
- <!-- <ContentWrap>-->
|
|
|
- <ContentWrap>
|
|
|
- <el-form
|
|
|
- class="-mb-15px"
|
|
|
- :model="queryParams"
|
|
|
- ref="queryFormRef"
|
|
|
- :inline="true"
|
|
|
- label-width="68px"
|
|
|
- >
|
|
|
- <el-form-item>
|
|
|
- <el-button @click="openForm" type="primary"
|
|
|
- ><Icon icon="ep:plus" class="mr-5px" />
|
|
|
- {{ t('route.SelectOperationDevice') }}</el-button
|
|
|
- >
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </ContentWrap>
|
|
|
- <draggable
|
|
|
- v-model="list"
|
|
|
- item-key="id"
|
|
|
- tag="div"
|
|
|
- class="sortable-container"
|
|
|
- handle=".sortable-item"
|
|
|
- :animation="150"
|
|
|
- @start="dragStart"
|
|
|
- @end="dragEnd"
|
|
|
- >
|
|
|
- <template #item="{ element, index }">
|
|
|
- <div class="sortable-item">
|
|
|
- <!-- 序号显示 -->
|
|
|
- <div class="order-number">{{ index + 1 }}</div>
|
|
|
-
|
|
|
- <!-- 拖动手柄 -->
|
|
|
- <span class="drag-handle">≡</span>
|
|
|
-
|
|
|
- <!-- 组件内容 -->
|
|
|
- <div class="component-content">
|
|
|
- <span style="font-weight: bold">{{ t('iotDevice.code') }}:</span
|
|
|
- ><span style="font-size: 14px">{{ element.deviceCode }}</span
|
|
|
- >
|
|
|
- <span style="font-weight: bold">{{ t('iotDevice.name') }}:</span
|
|
|
- ><span style="font-size: 14px">{{ element.deviceName }}</span>
|
|
|
</div>
|
|
|
- <div>
|
|
|
- <!-- <el-button type="warning" @click="deleteDraggable(index)">{{ t('form.delete') }}</el-button>-->
|
|
|
- <el-button
|
|
|
- style="vertical-align: middle"
|
|
|
- link
|
|
|
- type="danger"
|
|
|
- @click="handleDelete(element.id,element.deviceId)"
|
|
|
- >
|
|
|
- <Icon style="vertical-align: middle; color: #ea3434" icon="ep:zoom-out" />
|
|
|
+ <div class="form-cell form-cell--remark">
|
|
|
+ <el-form-item :label="t('form.remark')" prop="remark">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.remark"
|
|
|
+ type="textarea"
|
|
|
+ :autosize="{ minRows: 4, maxRows: 4 }" />
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="info-card device-card">
|
|
|
+ <div class="info-card__header">
|
|
|
+ <div class="info-card__title">
|
|
|
+ <span class="info-card__marker"></span>
|
|
|
+ <span>设备列表</span>
|
|
|
+ </div>
|
|
|
+ <span class="card-total">共 {{ list.length }} 台设备</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="info-card__body device-card__body">
|
|
|
+ <el-button type="primary" @click="openForm">
|
|
|
+ <Icon icon="ep:plus" class="mr-5px" />
|
|
|
+ {{ t('route.SelectOperationDevice') }}
|
|
|
+ </el-button>
|
|
|
+
|
|
|
+ <el-empty v-if="!list.length" description="暂无设备" class="device-empty" />
|
|
|
+
|
|
|
+ <draggable
|
|
|
+ v-else
|
|
|
+ v-model="list"
|
|
|
+ item-key="id"
|
|
|
+ tag="div"
|
|
|
+ class="sortable-container"
|
|
|
+ handle=".drag-handle"
|
|
|
+ :animation="150"
|
|
|
+ @start="dragStart"
|
|
|
+ @end="dragEnd">
|
|
|
+ <template #item="{ element, index }">
|
|
|
+ <div class="sortable-item">
|
|
|
+ <div class="order-number">{{ index + 1 }}</div>
|
|
|
+ <el-icon class="drag-handle" size="18"><Rank /></el-icon>
|
|
|
+ <div class="component-content">
|
|
|
+ <div class="device-title">{{ element.deviceName || '-' }}</div>
|
|
|
+ <div class="device-meta">
|
|
|
+ <span>{{ t('iotDevice.code') }}:{{ element.deviceCode || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-button link type="danger" @click="handleDelete(element.id, element.deviceId)">
|
|
|
+ <Icon icon="ep:delete" class="mr-3px" />
|
|
|
{{ t('form.delete') }}
|
|
|
</el-button>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </draggable>
|
|
|
- </ContentWrap>
|
|
|
-
|
|
|
- <ContentWrap>
|
|
|
- <el-form>
|
|
|
- <el-form-item style="float: right">
|
|
|
- <el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('iotMaintain.save') }}</el-button>
|
|
|
- <el-button @click="close">{{ t('iotMaintain.cancel') }}</el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </ContentWrap>
|
|
|
+ </template>
|
|
|
+ </draggable>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <div class="operation-plan-footer">
|
|
|
+ <el-button @click="close">{{ t('iotMaintain.cancel') }}</el-button>
|
|
|
+ <el-button type="primary" :disabled="formLoading" @click="submitForm">
|
|
|
+ {{ t('iotMaintain.save') }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
<InspectItemList
|
|
|
ref="inspectItemFormRef"
|
|
|
:classify="formData.deviceClassify"
|
|
|
:deviceId="formData.deviceId"
|
|
|
- @choose="inspectItemChoose"
|
|
|
- />
|
|
|
+ @choose="inspectItemChoose" />
|
|
|
<PlanDeviceList ref="deviceFormRef" @choose="deviceChoose" />
|
|
|
<RouteInspectItemDrawer
|
|
|
ref="showDrawer"
|
|
|
:model-value="drawerVisible"
|
|
|
- @update:model-value="(val) => (drawerVisible = val)"
|
|
|
- />
|
|
|
- </ContentWrap>
|
|
|
+ @update:model-value="(val) => (drawerVisible = val)" />
|
|
|
+ </div>
|
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
|
import * as UserApi from '@/api/system/user'
|
|
|
@@ -167,18 +155,17 @@ import { useUserStore } from '@/store/modules/user'
|
|
|
import { ref } from 'vue'
|
|
|
import { useTagsViewStore } from '@/store/modules/tagsView'
|
|
|
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
|
|
+import { Rank } from '@element-plus/icons-vue'
|
|
|
import InspectItemList from '@/views/pms/inspect/route/InspectItemList.vue'
|
|
|
import PlanDeviceList from '@/views/pms/iotopeationfill/plan/PlanDeviceList.vue'
|
|
|
import { IotInspectRouteVO } from '@/api/pms/inspect/route'
|
|
|
-import { DICT_TYPE, getStrDictOptions,getIntDictOptions } from '@/utils/dict'
|
|
|
-import { IotInspectPlanApi, IotInspectPlanVO } from '@/api/pms/inspect/plan'
|
|
|
+import { DICT_TYPE, getStrDictOptions, getIntDictOptions } from '@/utils/dict'
|
|
|
import RouteInspectItemDrawer from '@/views/pms/inspect/plan/RouteInspectItemDrawer.vue'
|
|
|
import draggable from 'vuedraggable'
|
|
|
-import {IotDeviceApi, IotDeviceVO} from "@/api/pms/device";
|
|
|
-import {defaultProps,handleTree} from "@/utils/tree";
|
|
|
-import * as ProductClassifyApi from "@/api/pms/productclassify";
|
|
|
-import {IotInspectItemVO} from "@/api/pms/inspect/item";
|
|
|
-import {IotOperationPlanApi, IotOperationPlanVO} from "@/api/pms/iotopeationfill/plan";
|
|
|
+import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
|
|
|
+import { handleTree } from '@/utils/tree'
|
|
|
+import * as ProductClassifyApi from '@/api/pms/productclassify'
|
|
|
+import { IotOperationPlanApi, IotOperationPlanVO } from '@/api/pms/iotopeationfill/plan'
|
|
|
|
|
|
/** 维修工单 表单 */
|
|
|
defineOptions({ name: 'OperationPlanAdd' })
|
|
|
@@ -211,7 +198,7 @@ const formData = ref({
|
|
|
deviceIds: undefined,
|
|
|
remark: undefined,
|
|
|
deptId: undefined,
|
|
|
- planDevList:[]
|
|
|
+ planDevList: []
|
|
|
})
|
|
|
const formRules = reactive({
|
|
|
planTitle: [{ required: true, message: '运行计划标题不能为空', trigger: 'blur' }],
|
|
|
@@ -254,7 +241,7 @@ const queryParams = reactive({
|
|
|
templateJson: undefined,
|
|
|
creator: undefined,
|
|
|
sortingFields: [],
|
|
|
- assetClass: undefined,
|
|
|
+ assetClass: undefined
|
|
|
})
|
|
|
const queryFormRef = ref() // 搜索的表单
|
|
|
/** 重置按钮操作 */
|
|
|
@@ -275,140 +262,138 @@ const selectedRows = ref<IotDeviceVO[]>([]) // 多选数据(存储所有选中
|
|
|
const selectAll = async () => {
|
|
|
try {
|
|
|
// 显示加载状态
|
|
|
- loading.value = true;
|
|
|
- isAllSelected.value = true;
|
|
|
- deselectedRows.value = [];
|
|
|
- selectedRows.value = []; // 清空现有选中项
|
|
|
- allDataCache.value = []; // 清空缓存
|
|
|
+ loading.value = true
|
|
|
+ isAllSelected.value = true
|
|
|
+ deselectedRows.value = []
|
|
|
+ selectedRows.value = [] // 清空现有选中项
|
|
|
+ allDataCache.value = [] // 清空缓存
|
|
|
|
|
|
- const paramsCopy = { ...queryParams };
|
|
|
- const originalPageNo = paramsCopy.pageNo;
|
|
|
- const originalPageSize = paramsCopy.pageSize;
|
|
|
+ const paramsCopy = { ...queryParams }
|
|
|
+ const originalPageNo = paramsCopy.pageNo
|
|
|
+ const originalPageSize = paramsCopy.pageSize
|
|
|
|
|
|
- paramsCopy.pageNo = 1;
|
|
|
- paramsCopy.pageSize = 100; // 按后台限制的最大页数获取
|
|
|
+ paramsCopy.pageNo = 1
|
|
|
+ paramsCopy.pageSize = 100 // 按后台限制的最大页数获取
|
|
|
|
|
|
// 获取第一页数据
|
|
|
- const firstPageData = await IotDeviceApi.getPlanDevicePage(paramsCopy);
|
|
|
- totalSelectedCount.value = firstPageData.total;
|
|
|
- allDataCache.value.push(...firstPageData.list);
|
|
|
+ const firstPageData = await IotDeviceApi.getPlanDevicePage(paramsCopy)
|
|
|
+ totalSelectedCount.value = firstPageData.total
|
|
|
+ allDataCache.value.push(...firstPageData.list)
|
|
|
|
|
|
// 分批获取剩余数据
|
|
|
if (firstPageData.total > 100) {
|
|
|
- const totalPages = Math.ceil(firstPageData.total / 100);
|
|
|
- const fetchPromises = [];
|
|
|
+ const totalPages = Math.ceil(firstPageData.total / 100)
|
|
|
+ const fetchPromises = []
|
|
|
|
|
|
for (let page = 2; page <= totalPages; page++) {
|
|
|
- fetchPromises.push(IotDeviceApi.getPlanDevicePage({ ...paramsCopy, pageNo: page }));
|
|
|
+ fetchPromises.push(IotDeviceApi.getPlanDevicePage({ ...paramsCopy, pageNo: page }))
|
|
|
}
|
|
|
|
|
|
- const remainingPages = await Promise.all(fetchPromises);
|
|
|
- remainingPages.forEach(pageData => {
|
|
|
- allDataCache.value.push(...pageData.list);
|
|
|
- });
|
|
|
+ const remainingPages = await Promise.all(fetchPromises)
|
|
|
+ remainingPages.forEach((pageData) => {
|
|
|
+ allDataCache.value.push(...pageData.list)
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
// 全选时,将所有数据放入selectedRows
|
|
|
- selectedRows.value = [...allDataCache.value];
|
|
|
+ selectedRows.value = [...allDataCache.value]
|
|
|
|
|
|
// 恢复原始分页参数
|
|
|
- queryParams.pageNo = originalPageNo;
|
|
|
- queryParams.pageSize = originalPageSize;
|
|
|
+ queryParams.pageNo = originalPageNo
|
|
|
+ queryParams.pageSize = originalPageSize
|
|
|
|
|
|
- message.success(t('operationFill.allSelected', { count: totalSelectedCount.value }));
|
|
|
+ message.success(t('operationFill.allSelected', { count: totalSelectedCount.value }))
|
|
|
} catch (error) {
|
|
|
- console.error('全选失败', error);
|
|
|
- message.error(t('operationFill.selectAllFailed'));
|
|
|
- isAllSelected.value = false;
|
|
|
- selectedRows.value = [];
|
|
|
+ console.error('全选失败', error)
|
|
|
+ message.error(t('operationFill.selectAllFailed'))
|
|
|
+ isAllSelected.value = false
|
|
|
+ selectedRows.value = []
|
|
|
} finally {
|
|
|
- loading.value = false;
|
|
|
+ loading.value = false
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
// 修改取消全选方法,同步清空selectedRows
|
|
|
const deselectAll = () => {
|
|
|
- isAllSelected.value = false;
|
|
|
- deselectedRows.value = [];
|
|
|
- selectedRows.value = []; // 清空所有选中项
|
|
|
- allDataCache.value = []; // 清空缓存
|
|
|
- totalSelectedCount.value = 0;
|
|
|
- message.info(t('operationFill.allDeselected'));
|
|
|
-};
|
|
|
+ isAllSelected.value = false
|
|
|
+ deselectedRows.value = []
|
|
|
+ selectedRows.value = [] // 清空所有选中项
|
|
|
+ allDataCache.value = [] // 清空缓存
|
|
|
+ totalSelectedCount.value = 0
|
|
|
+ message.info(t('operationFill.allDeselected'))
|
|
|
+}
|
|
|
|
|
|
// 修改单选逻辑,确保selectedRows正确更新
|
|
|
const selectRow = (row) => {
|
|
|
if (isAllSelected.value) {
|
|
|
// 全选状态下的单选操作
|
|
|
const deselectedIndex = deselectedRows.value.findIndex(
|
|
|
- item => item.id === row.id && item.deviceCode === row.deviceCode
|
|
|
- );
|
|
|
+ (item) => item.id === row.id && item.deviceCode === row.deviceCode
|
|
|
+ )
|
|
|
|
|
|
const selectedIndex = selectedRows.value.findIndex(
|
|
|
- item => item.id === row.id && item.deviceCode === row.deviceCode
|
|
|
- );
|
|
|
+ (item) => item.id === row.id && item.deviceCode === row.deviceCode
|
|
|
+ )
|
|
|
|
|
|
if (deselectedIndex > -1) {
|
|
|
// 从取消列表中移除,添加到选中列表
|
|
|
- deselectedRows.value.splice(deselectedIndex, 1);
|
|
|
+ deselectedRows.value.splice(deselectedIndex, 1)
|
|
|
if (selectedIndex === -1) {
|
|
|
- selectedRows.value.push({ ...row });
|
|
|
+ selectedRows.value.push({ ...row })
|
|
|
}
|
|
|
} else {
|
|
|
// 从选中列表中移除,添加到取消列表
|
|
|
if (selectedIndex > -1) {
|
|
|
- selectedRows.value.splice(selectedIndex, 1);
|
|
|
+ selectedRows.value.splice(selectedIndex, 1)
|
|
|
}
|
|
|
- deselectedRows.value.push({ ...row });
|
|
|
+ deselectedRows.value.push({ ...row })
|
|
|
}
|
|
|
} else {
|
|
|
// 非全选状态下的单选操作
|
|
|
const index = selectedRows.value.findIndex(
|
|
|
- item => item.id === row.id && item.deviceCode === row.deviceCode
|
|
|
- );
|
|
|
+ (item) => item.id === row.id && item.deviceCode === row.deviceCode
|
|
|
+ )
|
|
|
|
|
|
if (index > -1) {
|
|
|
// 取消选择
|
|
|
- selectedRows.value.splice(index, 1);
|
|
|
+ selectedRows.value.splice(index, 1)
|
|
|
} else {
|
|
|
// 选中
|
|
|
- selectedRows.value.push({ ...row });
|
|
|
+ selectedRows.value.push({ ...row })
|
|
|
}
|
|
|
}
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
+}
|
|
|
|
|
|
// 生成行唯一标识
|
|
|
const rowKey = (row: any) => {
|
|
|
- return `${row.id}`; // 确保行更新时重新渲染
|
|
|
-};
|
|
|
+ return `${row.id}` // 确保行更新时重新渲染
|
|
|
+}
|
|
|
|
|
|
// 修改移除标签方法,确保selectedRows同步更新
|
|
|
const removeTag = (route) => {
|
|
|
// 从选中列表中移除
|
|
|
const selectedIndex = selectedRows.value.findIndex(
|
|
|
- item => item.id === route.id && item.deviceCode === route.deviceCode
|
|
|
- );
|
|
|
+ (item) => item.id === route.id && item.deviceCode === route.deviceCode
|
|
|
+ )
|
|
|
|
|
|
if (selectedIndex > -1) {
|
|
|
- selectedRows.value.splice(selectedIndex, 1);
|
|
|
+ selectedRows.value.splice(selectedIndex, 1)
|
|
|
}
|
|
|
|
|
|
// 全选状态下还要添加到取消列表
|
|
|
if (isAllSelected.value) {
|
|
|
const deselectedIndex = deselectedRows.value.findIndex(
|
|
|
- item => item.id === route.id && item.deviceCode === route.deviceCode
|
|
|
- );
|
|
|
+ (item) => item.id === route.id && item.deviceCode === route.deviceCode
|
|
|
+ )
|
|
|
|
|
|
if (deselectedIndex === -1) {
|
|
|
- deselectedRows.value.push({ ...route });
|
|
|
+ deselectedRows.value.push({ ...route })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 刷新表格
|
|
|
- list.value = [...list.value];
|
|
|
-};
|
|
|
+ list.value = [...list.value]
|
|
|
+}
|
|
|
const handleQuery = () => {
|
|
|
queryParams.pageNo = 1
|
|
|
getList()
|
|
|
@@ -427,12 +412,10 @@ const getList = async () => {
|
|
|
// 拖动状态管理
|
|
|
const items = ref([])
|
|
|
const deviceChoose = (rows) => {
|
|
|
- debugger
|
|
|
rows.forEach((it) => {
|
|
|
- const ifExist = list.value.find((item) => item.id === it.id&&item.deviceId===it.deviceId)
|
|
|
+ const ifExist = list.value.find((item) => item.id === it.id && item.deviceId === it.deviceId)
|
|
|
if (!ifExist) {
|
|
|
list.value.push(it)
|
|
|
- console.log(JSON.stringify(it))
|
|
|
}
|
|
|
})
|
|
|
// list.value = rows
|
|
|
@@ -481,16 +464,17 @@ const submitForm = async () => {
|
|
|
// 提交请求
|
|
|
formLoading.value = true
|
|
|
try {
|
|
|
- formData.value.planDevList = list;
|
|
|
+ formData.value.planDevList = list
|
|
|
const user = wsCache.get(CACHE_KEY.USER)
|
|
|
const data = formData.value as unknown as IotOperationPlanVO
|
|
|
if (formType.value === 'create') {
|
|
|
//校验是否是已有计划
|
|
|
const newitems = itemsWithIndex
|
|
|
formData.value.deviceIds = JSON.stringify(newitems.value)
|
|
|
- if (!formData.value.deptId) {formData.value.deptId = user.user.deptId}
|
|
|
- await IotOperationPlanApi.createIotOperationPlan(data).then((res) => {
|
|
|
- })
|
|
|
+ if (!formData.value.deptId) {
|
|
|
+ formData.value.deptId = user.user.deptId
|
|
|
+ }
|
|
|
+ await IotOperationPlanApi.createIotOperationPlan(data).then((res) => {})
|
|
|
message.success(t('common.createSuccess'))
|
|
|
close()
|
|
|
} else {
|
|
|
@@ -510,7 +494,6 @@ const submitForm = async () => {
|
|
|
|
|
|
/** 重置表单 */
|
|
|
onMounted(async () => {
|
|
|
-
|
|
|
const route = useRoute()
|
|
|
const deptId = useUserStore().getUser.deptId
|
|
|
formData.value.deptId = Number(route.query.deptId)
|
|
|
@@ -532,8 +515,7 @@ onMounted(async () => {
|
|
|
})
|
|
|
const handleDelete = async (id: number, deviceId: number) => {
|
|
|
try {
|
|
|
- debugger
|
|
|
- const index = list.value.findIndex((item) => item.id === id&&item.deviceId===deviceId)
|
|
|
+ const index = list.value.findIndex((item) => item.id === id && item.deviceId === deviceId)
|
|
|
if (index !== -1) {
|
|
|
// 通过 splice 删除元素
|
|
|
list.value.splice(index, 1)
|
|
|
@@ -542,87 +524,182 @@ const handleDelete = async (id: number, deviceId: number) => {
|
|
|
}
|
|
|
</script>
|
|
|
<style scoped>
|
|
|
-.base-expandable-content {
|
|
|
- overflow: hidden; /* 隐藏溢出的内容 */
|
|
|
- transition: max-height 0.3s ease; /* 平滑过渡效果 */
|
|
|
+.operation-plan-page {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 16px;
|
|
|
+ min-height: calc(
|
|
|
+ 100vh - 20px - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height)
|
|
|
+ );
|
|
|
}
|
|
|
-/* 横向布局容器 */
|
|
|
|
|
|
+.info-card {
|
|
|
+ overflow: hidden;
|
|
|
+ background: var(--el-bg-color);
|
|
|
+ border: 1px solid var(--el-border-color-lighter);
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 10px 28px rgb(31 45 61 / 6%);
|
|
|
+}
|
|
|
|
|
|
-/* 拖拽手柄样式 */
|
|
|
-.drag-handle {
|
|
|
- opacity: 0.5;
|
|
|
- cursor: move;
|
|
|
- transition: opacity 0.3s;
|
|
|
+.device-card {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ flex-direction: column;
|
|
|
+ min-height: 360px;
|
|
|
}
|
|
|
-.drag-handle:hover {
|
|
|
- opacity: 1;
|
|
|
+
|
|
|
+.info-card__header {
|
|
|
+ display: flex;
|
|
|
+ min-height: 58px;
|
|
|
+ padding: 0 20px;
|
|
|
+ background: linear-gradient(90deg, rgb(64 158 255 / 8%) 0%, rgb(255 255 255 / 0%) 72%);
|
|
|
+ border-bottom: 1px solid var(--el-border-color-lighter);
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
}
|
|
|
|
|
|
-/* 拖拽时的悬停效果 */
|
|
|
-.horizontal-item:hover {
|
|
|
- transform: translateY(-2px);
|
|
|
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
+.info-card__title {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ line-height: 22px;
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
+ align-items: center;
|
|
|
}
|
|
|
|
|
|
-/* 滚动条样式 */
|
|
|
-.horizontal-list::-webkit-scrollbar {
|
|
|
- height: 8px;
|
|
|
+.info-card__marker {
|
|
|
+ width: 4px;
|
|
|
+ height: 18px;
|
|
|
+ background: var(--el-color-primary);
|
|
|
+ border-radius: 2px;
|
|
|
}
|
|
|
-.horizontal-list::-webkit-scrollbar-thumb {
|
|
|
- background: #888;
|
|
|
- border-radius: 4px;
|
|
|
+
|
|
|
+.info-card__body {
|
|
|
+ padding: 20px;
|
|
|
}
|
|
|
|
|
|
-.sortable-container {
|
|
|
- cursor: move;
|
|
|
+.card-total {
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
+}
|
|
|
+
|
|
|
+.operation-plan-form__grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
|
+ gap: 18px 32px;
|
|
|
+ align-items: start;
|
|
|
+}
|
|
|
+
|
|
|
+.form-cell {
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.form-cell--start-time {
|
|
|
+ grid-column: 1;
|
|
|
+ grid-row: 2;
|
|
|
+}
|
|
|
+
|
|
|
+.form-cell--report {
|
|
|
+ grid-column: 1;
|
|
|
+ grid-row: 3;
|
|
|
+}
|
|
|
+
|
|
|
+.form-cell--remark {
|
|
|
+ grid-column: 2 / 4;
|
|
|
+ grid-row: 2 / 4;
|
|
|
+}
|
|
|
+
|
|
|
+.operation-plan-form :deep(.el-form-item) {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.operation-plan-form :deep(.el-form-item__label) {
|
|
|
+ margin-bottom: 6px;
|
|
|
+ line-height: 18px;
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
+}
|
|
|
+
|
|
|
+.form-cell--remark :deep(.el-form-item),
|
|
|
+.form-cell--remark :deep(.el-form-item__content),
|
|
|
+.form-cell--remark :deep(.el-textarea),
|
|
|
+.form-cell--remark :deep(.el-textarea__inner) {
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card__body {
|
|
|
display: flex;
|
|
|
+ flex: 1;
|
|
|
flex-direction: column;
|
|
|
- gap: 9px;
|
|
|
- //max-height: 80vh;
|
|
|
+ gap: 14px;
|
|
|
+ min-height: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card__body > .el-button {
|
|
|
+ align-self: flex-start;
|
|
|
+}
|
|
|
+
|
|
|
+.device-empty {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 260px;
|
|
|
+}
|
|
|
+
|
|
|
+.sortable-container {
|
|
|
+ display: flex;
|
|
|
+ max-height: calc(100vh - 430px);
|
|
|
+ min-height: 0;
|
|
|
+ padding-right: 4px;
|
|
|
overflow-y: auto;
|
|
|
- padding: 7px;
|
|
|
+ flex: 1;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
}
|
|
|
|
|
|
.sortable-item {
|
|
|
display: flex;
|
|
|
+ gap: 12px;
|
|
|
align-items: center;
|
|
|
- padding: 8px;
|
|
|
- background: #fff;
|
|
|
- border: 1px solid #ebeef5;
|
|
|
+ min-height: 60px;
|
|
|
+ padding: 12px 14px;
|
|
|
+ background: var(--el-bg-color);
|
|
|
+ border: 1px solid var(--el-border-color-lighter);
|
|
|
border-radius: 8px;
|
|
|
transition:
|
|
|
- transform 0.3s,
|
|
|
- box-shadow 0.3s;
|
|
|
+ border-color 0.2s,
|
|
|
+ box-shadow 0.2s,
|
|
|
+ transform 0.2s;
|
|
|
user-select: none;
|
|
|
- height: 50%;
|
|
|
}
|
|
|
|
|
|
.sortable-item:hover {
|
|
|
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
|
|
+ border-color: var(--el-color-primary-light-5);
|
|
|
+ transform: translateY(-1px);
|
|
|
+ box-shadow: 0 4px 14px rgb(31 45 61 / 8%);
|
|
|
}
|
|
|
|
|
|
.order-number {
|
|
|
- width: 24px;
|
|
|
- height: 24px;
|
|
|
display: flex;
|
|
|
+ flex: 0 0 28px;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
- background: #409eff;
|
|
|
- color: white;
|
|
|
+ width: 28px;
|
|
|
+ height: 28px;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: var(--el-color-primary);
|
|
|
+ background: var(--el-color-primary-light-9);
|
|
|
border-radius: 50%;
|
|
|
- margin-right: 7px;
|
|
|
- font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.drag-handle {
|
|
|
- padding: 0 12px;
|
|
|
- opacity: 0.4;
|
|
|
- transition: opacity 0.3s;
|
|
|
+ flex: 0 0 auto;
|
|
|
+ color: var(--el-text-color-placeholder);
|
|
|
+ cursor: grab;
|
|
|
+ transition: color 0.2s;
|
|
|
}
|
|
|
|
|
|
.drag-handle:hover {
|
|
|
- opacity: 1;
|
|
|
+ color: var(--el-color-primary);
|
|
|
}
|
|
|
|
|
|
.component-content {
|
|
|
@@ -630,12 +707,70 @@ const handleDelete = async (id: number, deviceId: number) => {
|
|
|
min-width: 0;
|
|
|
}
|
|
|
|
|
|
-/* 优化滚动条 */
|
|
|
+.device-title {
|
|
|
+ overflow: hidden;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ line-height: 22px;
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.device-meta {
|
|
|
+ display: flex;
|
|
|
+ gap: 18px;
|
|
|
+ margin-top: 2px;
|
|
|
+ overflow: hidden;
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 20px;
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.operation-plan-footer {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ padding: 16px 24px;
|
|
|
+ background: var(--el-bg-color);
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: var(--el-box-shadow-light);
|
|
|
+}
|
|
|
+
|
|
|
.sortable-container::-webkit-scrollbar {
|
|
|
width: 8px;
|
|
|
}
|
|
|
+
|
|
|
.sortable-container::-webkit-scrollbar-thumb {
|
|
|
- background: #c0c4cc;
|
|
|
+ background: var(--el-border-color);
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
+
|
|
|
+@media (width <= 1200px) {
|
|
|
+ .operation-plan-form__grid {
|
|
|
+ grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-cell--start-time,
|
|
|
+ .form-cell--report,
|
|
|
+ .form-cell--remark {
|
|
|
+ grid-column: auto;
|
|
|
+ grid-row: auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-cell--remark {
|
|
|
+ grid-column: 1 / -1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (width <= 768px) {
|
|
|
+ .operation-plan-form__grid {
|
|
|
+ grid-template-columns: minmax(0, 1fr);
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-cell--remark {
|
|
|
+ grid-column: auto;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|