Переглянути джерело

巡检计划的设备路线排序

lipenghui 1 місяць тому
батько
коміт
9ddb175bf4

+ 194 - 38
src/views/pms/inspect/plan/IotInspectPlan.vue

@@ -81,43 +81,96 @@
             </el-form-item>
           </el-form>
         </ContentWrap>
-        <ContentWrap>
-          <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-            <el-table-column :label="t('iotDevice.code')" align="center" prop="deviceCode" />
-            <el-table-column :label="t('iotDevice.name')"  align="center" prop="deviceName" />
-            <el-table-column :label="t('route.RouteName')" align="center" prop="routeName" />
-            <el-table-column :label="t('operationFill.operation')" align="center" min-width="120px">
-              <template #default="scope">
-                <div
-                  style="display: flex; justify-content: center; align-items: center; width: 100%"
-                >
-                  <div style="margin-right: 10px">
-                    <el-button
-                      style="vertical-align: middle"
-                      link
-                      type="warning"
-                      @click="viewRoute(scope.row.itemJson)"
-                    >
-                      <Icon style="vertical-align: middle; color: #c36e5b" icon="ep:view" />
-                      {{ t('route.InspectionRoute') }}
-                    </el-button>
-                  </div>
-                  <div>
-                    <el-button
-                      style="vertical-align: middle"
-                      link
-                      type="danger"
-                      @click="handleDelete(scope.row.id,scope.row.deviceId)"
-                    >
-                      <Icon style="vertical-align: middle; color: #ea3434" icon="ep:zoom-out" />
-                      {{ t('form.delete') }}
-                    </el-button>
-                  </div>
-                </div>
-              </template>
-            </el-table-column>
-          </el-table>
-        </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
+            >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+              <span style="font-weight: bold">{{ t('iotDevice.name') }}:</span
+              ><span style="font-size: 14px">{{ element.deviceName }}</span>
+              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+              <span style="font-weight: bold">{{ t('route.RouteName') }}:</span
+              ><span style="font-size: 14px">{{ element.routeName }}</span>
+            </div>
+            <div>
+<!--              <el-button type="warning" @click="deleteDraggable(index)">{{ t('form.delete') }}</el-button>-->
+              <el-button
+                style="vertical-align: middle"
+                link
+                type="warning"
+                @click="viewRoute(element.itemJson)"
+              >
+                <Icon style="vertical-align: middle; color: #c36e5b" icon="ep:view" />
+                {{ t('route.InspectionRoute') }}
+              </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" />
+                {{ t('form.delete') }}
+              </el-button>
+            </div>
+          </div>
+        </template>
+      </draggable>
+<!--        <ContentWrap>-->
+<!--          <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">-->
+<!--            <el-table-column :label="t('iotDevice.code')" align="center" prop="deviceCode" />-->
+<!--            <el-table-column :label="t('iotDevice.name')"  align="center" prop="deviceName" />-->
+<!--            <el-table-column :label="t('route.RouteName')" align="center" prop="routeName" />-->
+<!--            <el-table-column :label="t('operationFill.operation')" align="center" min-width="120px">-->
+<!--              <template #default="scope">-->
+<!--                <div-->
+<!--                  style="display: flex; justify-content: center; align-items: center; width: 100%"-->
+<!--                >-->
+<!--                  <div style="margin-right: 10px">-->
+<!--                    <el-button-->
+<!--                      style="vertical-align: middle"-->
+<!--                      link-->
+<!--                      type="warning"-->
+<!--                      @click="viewRoute(scope.row.itemJson)"-->
+<!--                    >-->
+<!--                      <Icon style="vertical-align: middle; color: #c36e5b" icon="ep:view" />-->
+<!--                      {{ t('route.InspectionRoute') }}-->
+<!--                    </el-button>-->
+<!--                  </div>-->
+<!--                  <div>-->
+<!--                    <el-button-->
+<!--                      style="vertical-align: middle"-->
+<!--                      link-->
+<!--                      type="danger"-->
+<!--                      @click="handleDelete(scope.row.id,scope.row.deviceId)"-->
+<!--                    >-->
+<!--                      <Icon style="vertical-align: middle; color: #ea3434" icon="ep:zoom-out" />-->
+<!--                      {{ t('form.delete') }}-->
+<!--                    </el-button>-->
+<!--                  </div>-->
+<!--                </div>-->
+<!--              </template>-->
+<!--            </el-table-column>-->
+<!--          </el-table>-->
+<!--        </ContentWrap>-->
 <!--      </ContentWrap>-->
     </ContentWrap>
     <ContentWrap>
@@ -154,6 +207,7 @@ import { IotInspectRouteVO } from '@/api/pms/inspect/route'
 import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
 import { IotInspectPlanApi, IotInspectPlanVO } from '@/api/pms/inspect/plan'
 import RouteInspectItemDrawer from '@/views/pms/inspect/plan/RouteInspectItemDrawer.vue'
+import draggable from 'vuedraggable'
 
 /** 维修工单 表单 */
 defineOptions({ name: 'InspectPlanAdd' })
@@ -232,6 +286,12 @@ const close = () => {
   //   }
   // })
 }
+const itemsWithIndex = computed(() => {
+  return list.value.map((item, index) => ({
+    ...item,
+    index: index + 1 // 序号从1开始
+  }))
+})
 const { wsCache } = useCache()
 /** 提交表单 */
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
@@ -242,16 +302,21 @@ const submitForm = async () => {
   formLoading.value = true
   try {
     const user = wsCache.get(CACHE_KEY.USER)
-    formData.value.deviceIds = JSON.stringify(list.value)
     const data = formData.value as unknown as IotInspectPlanVO
     if (formType.value === 'create') {
       //校验是否是已有计划
+      const newitems = itemsWithIndex
+      debugger
+      formData.value.deviceIds = JSON.stringify(newitems.value)
       formData.value.deptId = user.user.deptId
       await IotInspectPlanApi.createIotInspectPlan(data).then((res) => {
       })
       message.success(t('common.createSuccess'))
       close()
     } else {
+      const newitems = itemsWithIndex
+      debugger
+      formData.value.deviceIds = JSON.stringify(newitems.value)
       await IotInspectPlanApi.updateIotInspectPlan(data)
       message.success(t('common.updateSuccess'))
       close()
@@ -294,4 +359,95 @@ const handleDelete = async (id: number, deviceId: number) => {
   transition: max-height 0.3s ease; /* 平滑过渡效果 */
 }
 /* 横向布局容器 */
+
+
+/* 拖拽手柄样式 */
+.drag-handle {
+  opacity: 0.5;
+  cursor: move;
+  transition: opacity 0.3s;
+}
+.drag-handle:hover {
+  opacity: 1;
+}
+
+/* 拖拽时的悬停效果 */
+.horizontal-item:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+/* 滚动条样式 */
+.horizontal-list::-webkit-scrollbar {
+  height: 8px;
+}
+.horizontal-list::-webkit-scrollbar-thumb {
+  background: #888;
+  border-radius: 4px;
+}
+
+.sortable-container {
+  cursor: move;
+  display: flex;
+  flex-direction: column;
+  gap: 9px;
+  //max-height: 80vh;
+  overflow-y: auto;
+  padding: 7px;
+}
+
+.sortable-item {
+  display: flex;
+  align-items: center;
+  padding: 8px;
+  background: #fff;
+  border: 1px solid #ebeef5;
+  border-radius: 8px;
+  transition:
+    transform 0.3s,
+    box-shadow 0.3s;
+  user-select: none;
+  height: 50%;
+}
+
+.sortable-item:hover {
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+}
+
+.order-number {
+  width: 24px;
+  height: 24px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #409eff;
+  color: white;
+  border-radius: 50%;
+  margin-right: 7px;
+  font-weight: bold;
+}
+
+.drag-handle {
+  padding: 0 12px;
+  opacity: 0.4;
+  transition: opacity 0.3s;
+}
+
+.drag-handle:hover {
+  opacity: 1;
+}
+
+.component-content {
+  flex: 1;
+  min-width: 0;
+}
+
+/* 优化滚动条 */
+.sortable-container::-webkit-scrollbar {
+  width: 8px;
+}
+.sortable-container::-webkit-scrollbar-thumb {
+  background: #c0c4cc;
+  border-radius: 4px;
+}
 </style>

+ 0 - 1
src/views/pms/inspect/route/IotInspectRoute.vue

@@ -114,7 +114,6 @@
 </template>
 <script setup lang="ts">
 import * as UserApi from '@/api/system/user'
-import { useUserStore } from '@/store/modules/user'
 import { ref } from 'vue'
 import { IotMaintainMaterialVO } from '@/api/pms/maintain/material'
 import { useTagsViewStore } from '@/store/modules/tagsView'