Bläddra i källkod

feat(zhld): 更新智慧路灯模块

- 修改路灯管理页面布局和功能
- 添加定时任务功能
- 优化灯杆数据展示和操作
- 调整环境变量 VITE_APP_BASE_API- 添加 VideoPlayer 组件
nahida 1 år sedan
förälder
incheckning
8d366102a2

+ 1 - 1
.env.development

@@ -1,4 +1,4 @@
 # 变量必须以 VITE_ 为前缀才能暴露给外部读取
 NODE_ENV = 'development'
-VITE_APP_BASE_API = 'http://192.168.110.13:8080'
+VITE_APP_BASE_API = '/api'
 VITE_MINIO_BASE_URL = 'http://192.168.110.30:9000/zksy-file'

+ 2 - 0
components.d.ts

@@ -39,6 +39,7 @@ declare module 'vue' {
     ElText: typeof import('element-plus/es')['ElText']
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
+    ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']
@@ -49,6 +50,7 @@ declare module 'vue' {
     RecursiveMenuItem: typeof import('./src/components/RecursiveMenuItem.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
+    VideoPlayer: typeof import('./src/components/VideoPlayer.vue')['default']
   }
   export interface ComponentCustomProperties {
     vLoading: typeof import('element-plus/es')['ElLoadingDirective']

BIN
src/assets/灯杆图片.jpg


BIN
src/assets/设置图片.jpg


+ 11 - 0
src/components/VideoPlayer.vue

@@ -0,0 +1,11 @@
+<script setup lang="ts">
+
+</script>
+
+<template>
+
+</template>
+
+<style scoped>
+
+</style>

+ 1 - 1
src/router/route.ts

@@ -370,7 +370,7 @@ export const routeList:RouterType[] = [
   },
   {
     path: 'zhld/dggl',
-    name: '智慧路灯-灯管理',
+    name: '智慧路灯-灯管理',
     icon: 'Location',
     addr: 'zhld/dggl'
   },

+ 4 - 4
src/views/zhdpgl/yqzl/yqjs.vue

@@ -181,7 +181,7 @@ init()
     <el-button type="primary" size="small" @click="addDialogVisible = true">新增</el-button>
     <el-table :data="tableData" style="width: 100%">
       <el-table-column :show-overflow-tooltip="true" type="index" label="序号"></el-table-column>
-      <el-table-column :show-overflow-tooltip="true" prop="parkName" label="园区名称"></el-table-column>
+      <el-table-column :show-overflow-tooltip="true" prop="parkName" label="园区介绍"></el-table-column>
       <el-table-column :show-overflow-tooltip="true" prop="totalArea" label="园区总面积"></el-table-column>
       <el-table-column :show-overflow-tooltip="true" prop="enteredCompany" label="入职企业"></el-table-column>
       <el-table-column :show-overflow-tooltip="true" prop="numberBuildings" label="楼栋数量"></el-table-column>
@@ -212,7 +212,7 @@ init()
     <el-dialog v-model="dialogVisible" title="详情" width="80%" destroy-on-close>
       <el-descriptions border>
         <el-descriptions-item min-width="200" label="ID">{{ currentRow?.id }}</el-descriptions-item>
-        <el-descriptions-item min-width="200" label="园区名称">{{ currentRow?.parkName }}</el-descriptions-item>
+        <el-descriptions-item min-width="200" label="园区介绍">{{ currentRow?.parkName }}</el-descriptions-item>
         <el-descriptions-item min-width="200" label="园区总面积">{{ currentRow?.totalArea }}</el-descriptions-item>
         <el-descriptions-item min-width="200" label="入职企业">{{ currentRow?.enteredCompany }}</el-descriptions-item>
         <el-descriptions-item min-width="200" label="楼栋数量">{{ currentRow?.numberBuildings }}</el-descriptions-item>
@@ -243,7 +243,7 @@ init()
     </el-dialog>
     <el-dialog v-model="editDialogVisible" title="编辑园区信息" width="50%">
       <el-form :model="editForm" label-width="120px">
-        <el-form-item label="园区名称">
+        <el-form-item label="园区介绍">
           <el-input v-model="editForm.parkName"></el-input>
         </el-form-item>
         <el-form-item label="园区总面积">
@@ -312,7 +312,7 @@ init()
     </el-dialog>
     <el-dialog v-model="addDialogVisible" title="新增园区信息" width="50%">
       <el-form :model="addForm" label-width="120px">
-        <el-form-item label="园区名称">
+        <el-form-item label="园区介绍">
           <el-input v-model="addForm.parkName"></el-input>
         </el-form-item>
         <el-form-item label="园区总面积">

+ 220 - 0
src/views/zhdpgl/zhdg/dpfb.bak

@@ -0,0 +1,220 @@
+<script setup lang="ts">
+import { clientGet, clientPost, clientPut, clientDel } from '@/utils/request.ts'
+import { ref } from 'vue'
+import type { BaseResponse } from '@/utils/type.ts'
+import { ElMessage, ElDialog, ElInput, ElForm, ElFormItem, ElButton, ElUpload,type UploadFile,type UploadFiles, ElMessageBox } from 'element-plus'
+
+interface ParkStemScreen {
+  "id": string,
+  "type": string,
+  "createTime": string,
+  "updateTime": string,
+  "filePath": string[],
+}
+
+interface ParkStemScreenResponse extends BaseResponse {
+  data: ParkStemScreen[]
+}
+
+const minioUrl = import.meta.env.VITE_MINIO_BASE_URL
+
+const cardList = ref<ParkStemScreen[]>()
+
+const getList = async () => {
+  const res = await clientGet<null, ParkStemScreenResponse>('/park/parkStemScreen/getListWithImg');
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+  }
+  cardList.value = res.data;
+}
+
+const init = () => {
+  getList()
+}
+init()
+
+// 新增功能相关状态和方法
+const addDialogVisible = ref(false)
+const newScreen = ref({
+  type: '',
+  filePath: [] as string[]
+})
+const addFileList = ref<UploadFile[]>([])
+
+const handleAddFileChange = (file: UploadFile, fileList: UploadFiles) => {
+  addFileList.value = fileList
+}
+
+const handleAdd = async () => {
+  if (addFileList.value.length === 0) {
+    ElMessage.error('请上传文件')
+    return
+  }
+
+  const formData = new FormData()
+  formData.append('type', newScreen.value.type)
+  addFileList.value.forEach(file => {
+    formData.append('files', file.raw!)
+  })
+
+  const res = await clientPost<FormData, BaseResponse>('/park/parkStemScreen/save', formData, {
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  });
+
+  if (res.code === 200) {
+    ElMessage.success('新增成功')
+    getList()
+    addDialogVisible.value = false
+    addFileList.value = []
+  } else {
+    ElMessage.error(res.msg)
+  }
+}
+
+// 修改功能相关状态和方法
+const editDialogVisible = ref(false)
+const editScreen = ref<ParkStemScreen>({
+  id: '',
+  type: '',
+  createTime: '',
+  updateTime: '',
+  filePath: [] as string[]
+})
+const editFileList = ref<UploadFile[]>([])
+
+const handleEditFileChange = (file: UploadFile, fileList: UploadFiles) => {
+  editFileList.value = fileList
+}
+
+const handleEdit = (item: ParkStemScreen) => {
+  editScreen.value = { ...item }
+  editFileList.value = []
+  editDialogVisible.value = true
+}
+
+const handleUpdate = async () => {
+  const formData = new FormData()
+  formData.append('id', editScreen.value.id)
+  formData.append('type', editScreen.value.type)
+
+  if (editFileList.value.length > 0) {
+    editFileList.value.forEach(file => {
+      formData.append('files', file.raw!)
+    })
+  }
+
+  const res = await clientPut<FormData, BaseResponse>('/park/parkStemScreen/updateById', formData, {
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  });
+
+  if (res.code === 200) {
+    ElMessage.success('修改成功')
+    getList()
+    editDialogVisible.value = false
+    editFileList.value = []
+  } else {
+    ElMessage.error(res.msg)
+  }
+}
+
+// 删除功能相关方法
+const handleDelete = async (id: string) => {
+  ElMessageBox.confirm('确定要删除此大屏图片吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(async () => {
+    const res = await clientDel<null,BaseResponse>(`/park/parkStemScreen/deleteById?id=${id}`);
+    if (res.code === 200) {
+      ElMessage.success('删除成功')
+      getList()
+    } else {
+      ElMessage.error(res.msg)
+    }
+  }).catch(() => {
+    ElMessage.info('已取消删除')
+  })
+}
+</script>
+
+<template>
+  <div>
+    <el-row class="p-20px" :gutter="20">
+      <el-col :span="24" class="my-20px">
+        <el-button type="primary" @click="addDialogVisible = true">新增大屏图片</el-button>
+      </el-col>
+      <el-col :lg="6" :sm="12" v-for="(item, index) in cardList" :key="index">
+        <el-card style="max-width: 480px">
+          <template #header>
+            <div class="flex justify-between">
+              <div>{{ item.type }}</div>
+              <div>
+                <el-button type="warning" @click="handleEdit(item)">修改</el-button>
+                <el-button type="danger" @click="handleDelete(item.id)" v-if="false">删除</el-button>
+              </div>
+            </div>
+          </template>
+          <img
+            :src="minioUrl + item.filePath[0]"
+            style="width: 100%"
+            alt="大屏图片"
+          />
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <!-- 新增对话框 -->
+    <el-dialog v-model="addDialogVisible" title="新增大屏图片" destroy-on-close>
+      <el-form :model="newScreen" label-width="120px">
+        <el-form-item label="类型">
+          <el-input v-model="newScreen.type" />
+        </el-form-item>
+        <el-form-item label="文件上传">
+          <el-upload
+            action=""
+            :on-change="handleAddFileChange"
+            :auto-upload="false"
+            :file-list="addFileList"
+          >
+            <el-button type="primary">选取文件</el-button>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="addDialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleAdd">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <!-- 修改对话框 -->
+    <el-dialog v-model="editDialogVisible" title="修改大屏图片" destroy-on-close>
+      <el-form :model="editScreen" label-width="120px">
+        <el-form-item label="类型">
+          <el-input v-model="editScreen.type" />
+        </el-form-item>
+        <el-form-item label="文件上传">
+          <el-upload
+            action=""
+            :on-change="handleEditFileChange"
+            :auto-upload="false"
+            :file-list="editFileList"
+          >
+            <el-button type="primary">选取文件</el-button>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="editDialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleUpdate">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>

+ 247 - 178
src/views/zhdpgl/zhdg/dpfb.vue

@@ -1,220 +1,289 @@
 <script setup lang="ts">
-import { clientGet, clientPost, clientPut, clientDel } from '@/utils/request.ts'
-import { ref } from 'vue'
 import type { BaseResponse } from '@/utils/type.ts'
-import { ElMessage, ElDialog, ElInput, ElForm, ElFormItem, ElButton, ElUpload,type UploadFile,type UploadFiles, ElMessageBox } from 'element-plus'
-
-interface ParkStemScreen {
-  "id": string,
-  "type": string,
-  "createTime": string,
-  "updateTime": string,
-  "filePath": string[],
+import { clientGet, clientPost, clientPut } from '@/utils/request.ts'
+import { onMounted, ref, toRaw } from 'vue'
+import {
+  ElButton,
+  ElDialog,
+  ElForm,
+  ElFormItem,
+  ElInput,
+  ElMessage,
+  ElTable,
+  ElTableColumn,
+  ElUpload
+} from 'element-plus'
+
+// 类型定义
+interface ScreenControlResponse extends BaseResponse {
+  data: ScreenControl[]
+}
+
+interface UploadResponse extends BaseResponse {
+  data: string
 }
 
-interface ParkStemScreenResponse extends BaseResponse {
-  data: ParkStemScreen[]
+interface ScreenControl {
+  id: string
+  url: string
+  deviceId: string
+  state: number
+  createTime: string
+  updateTime: string
+  file?: File // 添加文件属性
+  isOpen?: string // 添加 isOpen 属性
 }
 
-const minioUrl = import.meta.env.VITE_MINIO_BASE_URL
+interface IsOpenResponse extends BaseResponse{
+  data:boolean
+}
 
-const cardList = ref<ParkStemScreen[]>()
+// 响应式数据
+const screenControls = ref<ScreenControl[]>([])
+const dialogVisible = ref(false)
+const BASE_API = import.meta.env.VITE_APP_BASE_API
+const currentItem = ref<ScreenControl>({
+  id: '',
+  url: '',
+  deviceId: '',
+  state: 0,
+  createTime: '',
+  updateTime: ''
+})
+const previewUrl = ref<string>('') // 添加预览URL的响应式数据
 
+// 获取数据
 const getList = async () => {
-  const res = await clientGet<null, ParkStemScreenResponse>('/park/parkStemScreen/getListWithImg');
+  const res = await clientGet<null, ScreenControlResponse>('/screen/test/getAllScreenControl')
   if (res.code !== 200) {
     ElMessage.error(res.msg)
+    return
   }
-  cardList.value = res.data;
+
+  // 获取每个设备的开启状态并更新数据
+  screenControls.value = await Promise.all(
+    res.data.map(async (item) => {
+      const isOpenRes = await checkIsOpen(item.deviceId)
+      return { ...item, isOpen: isOpenRes }
+    })
+  )
 }
 
-const init = () => {
-  getList()
+// 时间格式化方法
+const formatDateTime = (dateTime: string): string => {
+  if (!dateTime) return ''
+  const date = new Date(dateTime)
+  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}
+          ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
 }
-init()
 
-// 新增功能相关状态和方法
-const addDialogVisible = ref(false)
-const newScreen = ref({
-  type: '',
-  filePath: [] as string[]
-})
-const addFileList = ref<UploadFile[]>([])
+const pad = (n: number) => n.toString().padStart(2, '0')
 
-const handleAddFileChange = (file: UploadFile, fileList: UploadFiles) => {
-  addFileList.value = fileList
+// 打开修改对话框
+const openEditDialog = (row: ScreenControl) => {
+  currentItem.value = { ...row }
+  previewUrl.value = row.url // 初始化预览URL
+  dialogVisible.value = true
 }
 
-const handleAdd = async () => {
-  if (addFileList.value.length === 0) {
-    ElMessage.error('请上传文件')
+// 保存修改
+const saveEdit = async () => {
+  const res = await clientPut<ScreenControl, BaseResponse>('/screen/test/updateScreenControl', toRaw(currentItem.value))
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
     return
   }
+  ElMessage.success('修改成功')
+  dialogVisible.value = false
+  getList() // 刷新数据
+}
 
-  const formData = new FormData()
-  formData.append('type', newScreen.value.type)
-  addFileList.value.forEach(file => {
-    formData.append('files', file.raw!)
-  })
+const beforeUpload = (file: File) => {
+  const isImage = currentItem.value.state === 1
+  const validTypes = isImage
+    ? ['image/jpeg', 'image/png']
+    : ['video/mp4', 'video/avi']
 
-  const res = await clientPost<FormData, BaseResponse>('/park/parkStemScreen/save', formData, {
-    headers: {
-      'Content-Type': 'multipart/form-data'
-    }
-  });
-
-  if (res.code === 200) {
-    ElMessage.success('新增成功')
-    getList()
-    addDialogVisible.value = false
-    addFileList.value = []
-  } else {
-    ElMessage.error(res.msg)
+  if (!validTypes.includes(file.type)) {
+    ElMessage.error(`请上传${isImage ? '图片' : '视频'}格式文件`)
+    return false
   }
+  return true
 }
 
-// 修改功能相关状态和方法
-const editDialogVisible = ref(false)
-const editScreen = ref<ParkStemScreen>({
-  id: '',
-  type: '',
-  createTime: '',
-  updateTime: '',
-  filePath: [] as string[]
-})
-const editFileList = ref<UploadFile[]>([])
-
-const handleEditFileChange = (file: UploadFile, fileList: UploadFiles) => {
-  editFileList.value = fileList
+const handleSuccess = (res: UploadResponse) => {
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return
+  }
+  currentItem.value.url = res.data
+  previewUrl.value = res.data // 更新预览URL
+  ElMessage.success('上传成功')
 }
 
-const handleEdit = (item: ParkStemScreen) => {
-  editScreen.value = { ...item }
-  editFileList.value = []
-  editDialogVisible.value = true
+const checkIsOpen = async (deviceId:string) => {
+  const res = await clientPost<{deviceId:string},IsOpenResponse>("/screen/test/checkScreenState?deviceCode="+deviceId);
+  if(res.code !== 200){
+    ElMessage.error(deviceId+"开启状态查询失败")
+    return "未知";
+  }else {
+    return res.data?"开启":"关闭"
+  }
 }
 
-const handleUpdate = async () => {
-  const formData = new FormData()
-  formData.append('id', editScreen.value.id)
-  formData.append('type', editScreen.value.type)
-
-  if (editFileList.value.length > 0) {
-    editFileList.value.forEach(file => {
-      formData.append('files', file.raw!)
-    })
+const turnOrOffLight = async (screenControl: ScreenControl, cmd: number) => {
+  try {
+    const params = {
+      deviceCode: screenControl.deviceId,
+      cmd: cmd
+    };
+    const res = await clientPost<null,IsOpenResponse>("/screen/test/turnOffOrLight", null, { params });
+    if (res.code !== 200) {
+      ElMessage.error(`设备 ${screenControl.deviceId} 操作失败: ${res.msg}`);
+      return;
+    }
+    ElMessage.success(`设备 ${screenControl.deviceId} 操作成功`);
+    getList();
+  } catch (error) {
+    console.error('Error turning on/off light:', error);
+    ElMessage.error('操作失败,请稍后再试');
   }
+}
 
-  const res = await clientPut<FormData, BaseResponse>('/park/parkStemScreen/updateById', formData, {
-    headers: {
-      'Content-Type': 'multipart/form-data'
-    }
-  });
-
-  if (res.code === 200) {
-    ElMessage.success('修改成功')
-    getList()
-    editDialogVisible.value = false
-    editFileList.value = []
-  } else {
+const applyResource = async (item:ScreenControl)=>{
+  const params = {
+    deviceCode: item.deviceId,
+    url: "http://172.16.102.52:83/?deviceId=y4a-b23-00845"
+  }
+  const res = await clientPost<null,BaseResponse>("/screen/test/getTopWebPage",null,{params})
+  if(res.code !== 200){
     ElMessage.error(res.msg)
+  }else {
+    ElMessage.success("资源应用成功");
   }
 }
 
-// 删除功能相关方法
-const handleDelete = async (id: string) => {
-  ElMessageBox.confirm('确定要删除此大屏图片吗?', '提示', {
-    confirmButtonText: '确定',
-    cancelButtonText: '取消',
-    type: 'warning'
-  }).then(async () => {
-    const res = await clientDel<null,BaseResponse>(`/park/parkStemScreen/deleteById?id=${id}`);
-    if (res.code === 200) {
-      ElMessage.success('删除成功')
-      getList()
-    } else {
-      ElMessage.error(res.msg)
-    }
-  }).catch(() => {
-    ElMessage.info('已取消删除')
-  })
-}
+onMounted(() => {
+  getList()
+})
 </script>
 
 <template>
-  <div>
-    <el-row class="p-20px" :gutter="20">
-      <el-col :span="24" class="my-20px">
-        <el-button type="primary" @click="addDialogVisible = true">新增大屏图片</el-button>
-      </el-col>
-      <el-col :lg="6" :sm="12" v-for="(item, index) in cardList" :key="index">
-        <el-card style="max-width: 480px">
-          <template #header>
-            <div class="flex justify-between">
-              <div>{{ item.type }}</div>
-              <div>
-                <el-button type="warning" @click="handleEdit(item)">修改</el-button>
-                <el-button type="danger" @click="handleDelete(item.id)" v-if="false">删除</el-button>
-              </div>
-            </div>
-          </template>
-          <img
-            :src="minioUrl + item.filePath[0]"
-            style="width: 100%"
-            alt="大屏图片"
-          />
-        </el-card>
-      </el-col>
-    </el-row>
-
-    <!-- 新增对话框 -->
-    <el-dialog v-model="addDialogVisible" title="新增大屏图片" destroy-on-close>
-      <el-form :model="newScreen" label-width="120px">
-        <el-form-item label="类型">
-          <el-input v-model="newScreen.type" />
-        </el-form-item>
-        <el-form-item label="文件上传">
-          <el-upload
-            action=""
-            :on-change="handleAddFileChange"
-            :auto-upload="false"
-            :file-list="addFileList"
-          >
-            <el-button type="primary">选取文件</el-button>
-          </el-upload>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="addDialogVisible = false">取消</el-button>
-          <el-button type="primary" @click="handleAdd">确定</el-button>
-        </span>
+  <el-table :data="screenControls" style="width: 100%">
+    <!-- 原有列 -->
+    <el-table-column prop="id" label="ID" width="180" />
+    <el-table-column prop="deviceId" label="设备ID" width="180" />
+    <el-table-column label="状态" width="180">
+      <template #default="scope">
+        <span v-if="scope.row.state === 1">图片</span>
+        <span v-else-if="scope.row.state === 2">视频</span>
+        <span v-else>{{ scope.row.state }}</span>
+      </template>
+    </el-table-column>
+    <el-table-column label="状态" width="180">
+      <template #default="scope">
+        <el-tag>
+          {{ scope.row.isOpen || '未知' }}
+        </el-tag>
+      </template>
+    </el-table-column>
+    <el-table-column prop="createTime" label="创建时间" width="180">
+      <template #default="scope">
+        {{ formatDateTime(scope.row.createTime) }}
       </template>
-    </el-dialog>
-
-    <!-- 修改对话框 -->
-    <el-dialog v-model="editDialogVisible" title="修改大屏图片" destroy-on-close>
-      <el-form :model="editScreen" label-width="120px">
-        <el-form-item label="类型">
-          <el-input v-model="editScreen.type" />
-        </el-form-item>
-        <el-form-item label="文件上传">
-          <el-upload
-            action=""
-            :on-change="handleEditFileChange"
-            :auto-upload="false"
-            :file-list="editFileList"
-          >
-            <el-button type="primary">选取文件</el-button>
-          </el-upload>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="editDialogVisible = false">取消</el-button>
-          <el-button type="primary" @click="handleUpdate">确定</el-button>
-        </span>
+    </el-table-column>
+    <el-table-column prop="updateTime" label="更新时间" width="180">
+      <template #default="scope">
+        {{ formatDateTime(scope.row.updateTime) }}
       </template>
-    </el-dialog>
-  </div>
+    </el-table-column>
+
+    <!-- 操作列 -->
+    <el-table-column label="操作">
+      <template #default="scope">
+        <el-button type="success" size="small" @click="applyResource(scope.row)">
+          应用
+        </el-button>
+        <el-button type="primary" size="small" @click="openEditDialog(scope.row)">
+          修改
+        </el-button>
+        <el-button type="warning" size="small" @click="openEditDialog(scope.row)">
+          预览
+        </el-button>
+        <el-button type="info" size="small" @click="turnOrOffLight(scope.row,1)">
+          开屏
+        </el-button>
+        <el-button type="danger" size="small" @click="turnOrOffLight(scope.row,0)">
+          关屏
+        </el-button>
+      </template>
+    </el-table-column>
+  </el-table>
+
+  <!-- 修改对话框 -->
+  <el-dialog v-model="dialogVisible" title="修改信息" width="30%">
+    <el-form :model="currentItem" label-width="80px">
+      <el-form-item label="ID">
+        <el-input v-model="currentItem.id" disabled />
+      </el-form-item>
+
+      <el-form-item label="设备ID">
+        <el-input v-model="currentItem.deviceId" disabled />
+      </el-form-item>
+
+      <el-form-item label="状态">
+        <el-select v-model="currentItem.state" placeholder="请选择">
+          <el-option
+            label="图片"
+            :value="1"
+          />
+          <el-option
+            label="视频"
+            :value="2"
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-upload
+          class="upload-demo"
+          :action="BASE_API+'/screen/file/upload'"
+          :before-upload="beforeUpload"
+          :accept="currentItem.state === 1 ? 'image/*' : 'video/*'"
+          :show-file-list="false"
+          :on-success="handleSuccess"
+        >
+          <el-button type="primary">点击上传</el-button>
+          <template #tip>
+            <div class="el-upload__tip" v-if="currentItem.state === 1">
+              只能上传jpg/png等图片文件
+            </div>
+            <div class="el-upload__tip" v-else-if="currentItem.state === 2">
+              只能上传mp4等视频文件
+            </div>
+          </template>
+        </el-upload>
+      </el-form-item>
+
+      <!-- 资源预览 -->
+      <el-form-item label="预览">
+        <div v-if="previewUrl">
+          <img v-if="currentItem.state === 1" :src="previewUrl" alt="预览图片" style="max-width: 100%; height: auto;" />
+          <video v-else-if="currentItem.state === 2" :src="previewUrl" controls style="max-width: 100%; height: auto;">
+            您的浏览器不支持 video 标签。
+          </video>
+        </div>
+        <div v-else>
+          请上传文件以预览
+        </div>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="saveEdit">保存</el-button>
+      </span>
+    </template>
+  </el-dialog>
 </template>

+ 144 - 218
src/views/zhld/dggl.vue

@@ -1,254 +1,180 @@
-<script setup lang="ts">
-import { clientGet } from '@/utils/request.ts'
+<script lang="ts" setup>
+import { clientGet } from '@/utils/request.ts';
 import type { BaseResponse } from '@/utils/type.ts'
+import { ElMessage } from 'element-plus'
 import { ref } from 'vue'
-import { ElLoading, ElMessage } from 'element-plus'
-import { useDebounceFn } from '@vueuse/core'
 
-interface StatusParams {
-  cmd: number,
-  lightNums: string,
-  packageId: string
+interface CmdResponse extends BaseResponse{
+  data:string;
 }
 
-interface StatusResponse extends BaseResponse {
-  data: string
-}
-
-interface LightData {
-  light_num: string;       // 灯编号
-  brightness: number | boolean;      // 亮度
-  voltage: number;         // 电压
-  current: number;         // 电流
-  power: number;           // 功率
-  power_quantity: number;  // 电量
-  onlineStatus: number;    // 在线状态
-}
+const onTime = ref('');
+const offTime = ref('');
 
-const cardDatas = ref<LightData[]>([]);
-const linkDialogVisible = ref(false);
-// const downloadUrl = ref('public/LedOK Express.rar');
-
-const orignalParams = [
-  {
-    cmd: 6012,
-    lightNums: '40005289',
-    packageId: '1050'
-  },
-  {
-    cmd: 6012,
-    lightNums: '40005272',
-    packageId: '1050'
-  },
-  {
-    cmd: 6012,
-    lightNums: '40005274',
-    packageId: '1050'
-  },
-  {
-    cmd: 6012,
-    lightNums: '40005281',
-    packageId: '1050'
+const setOnTime = async ()=>{
+  if(!onTime.value){
+    ElMessage.error("请选择时间");
+    return;
   }
-]
-const getData = async () => {
-  let process = 0
-  const loading = ElLoading.service({
-    lock: true,
-    text: '正在加载数据' + process + '/' + orignalParams.length,
-    background: 'rgba(200, 200, 200, .8)'
+  const res =  await clientGet<{value:string},CmdResponse>('/lamp/execution/timingOn',{
+    params:{
+      value:onTime.value
+    }
   })
-  const list = []
   try {
-    for (let i = 0; i < orignalParams.length; i++) {
-      const res = await clientGet<StatusParams, StatusResponse>('/pole/instruct/issued/equipmentStatus', {
-        params: orignalParams[i]
-      })
-      list.push(res)
-      process = i + 1
-      loading.setText('正在加载数据' + process + '/' + orignalParams.length)
+    if (res.code !== 200) {
+      if (res.code === 429) {
+        ElMessage.error(res.msg)
+      }
+      if (res.code === 400) {
+        ElMessage.error(res.msg)
+      }
+      ElMessage.error('操作失败')
+    }else {
+      ElMessage.success('操作成功')
     }
-
-    const resList: LightData[] = list.map(res => {
-      return JSON.parse(JSON.parse(res.data).params)
-    })
-    cardDatas.value = resList.flat(-1 >>> 1).map(item => {
-      item.brightness = item.brightness != 0
-      return item
-    })
-  } catch (error) {
-    console.error('数据获取失败:', error)
   } finally {
-    loading.close()
+
   }
 }
-const changeLight = useDebounceFn(async (light: LightData) => {
-  const loading = ElLoading.service({
-    lock: true,
-    text: '正在操作灯杆' + light.light_num,
-    background: 'rgba(200, 200, 200, .8)'
-  })
-  if (typeof light.brightness === 'number') {
-    ElMessage.warning('出现了错误')
-    return
+const setOffTime = async ()=>{
+  console.log(offTime.value)
+  if(!offTime.value){
+    ElMessage.error("请选择时间");
+    return;
   }
+  const res =  await clientGet<{value:string},CmdResponse>('/lamp/execution/timedShutdown',{
+    params:{
+      value:offTime.value
+    }
+  })
   try {
-    const newBrightness = light.brightness ? 0 : 100
-    await clientGet('/pole/instruct/issued/reportEnvironmentalData', {
-      params: {
-        cmd: 6011,
-        lightNums: light.light_num,
-        packageId: '1050',
-        brightness: newBrightness
+    if (res.code !== 200) {
+      if (res.code === 429) {
+        ElMessage.error(res.msg)
       }
-    })
-    const qq = await getSingleLightStatus({
-      cmd: 6012,
-      lightNums: light.light_num,
-      packageId: '1050'
-    })
-    if(qq == null){
-      ElMessage.error('获取状态失败,请重试')
-      return
-    }
-    qq.brightness = qq.brightness != 0
-    const updatedLightIndex = cardDatas.value.findIndex(card => card.light_num === light.light_num)
-    if (updatedLightIndex !== -1) {
-      cardDatas.value[updatedLightIndex] = (qq as LightData);
+      if (res.code === 400) {
+        ElMessage.error(res.msg)
+      }
+      ElMessage.error('操作失败')
+    }else {
+      ElMessage.success('操作成功')
     }
-    ElMessage.success(light.brightness ? '关灯' : '开灯')
-  } catch (error) {
-    console.error('开灯/关灯失败:', error)
-    ElMessage.error('操作失败,请重试')
-  }finally {
-    loading.close()
-  }
-},500);
-const getSingleLightStatus = async (params: StatusParams): Promise<LightData | null> => {
-  try {
-    const res = await clientGet<StatusParams, StatusResponse>('/pole/instruct/issued/equipmentStatus', {
-      params: params
-    });
-    const parsedData = JSON.parse(JSON.parse(res.data).params);
-    return parsedData[0];
-  } catch (error) {
-    console.error('获取单个灯杆状态失败:', error);
-    ElMessage.error('获取状态失败,请重试');
-    return null;
+  } finally {
   }
-};
-const updateCurrentData = async (light:LightData)=>{
-  const loading = ElLoading.service({
-    lock: true,
-    text: '正在获取当前灯杆数据',
-    background: 'rgba(200, 200, 200, .8)'
+}
+
+const contollerLamp = async (cmd:number)=>{
+
+  const res =  await clientGet<{value:number},CmdResponse>('/lamp/execution/firstRelay',{
+    params:{
+      value:cmd
+    }
   })
-  const res = await getSingleLightStatus({cmd:6012,lightNums:light.light_num,packageId:'1050'})
-  if(!res){
-    ElMessage.error('获取状态失败,请重试')
+  if(res.code !== 200){
+    ElMessage.error("操作失败");
     return
   }
-  res.brightness = res.brightness != 0
-  const updatedLightIndex = cardDatas.value.findIndex(card => card.light_num === light.light_num);
-  if (updatedLightIndex !== -1) {
-    cardDatas.value[updatedLightIndex] = res as LightData;
+  if(res.code === 200){
+    ElMessage.success("操作成功");
+    return;
   }
-  loading.close()
 }
-const toOtherLink = (linkStr:'一键报警'|'灯杆显示屏')=>{
-  switch (linkStr){
-    case '一键报警':
-      window.open('https://172.16.102.27:8088/')
-      break;
-    case '灯杆显示屏':
-      linkDialogVisible.value = true
-      break;
+
+const contollerLamp2 = async (cmd:number)=>{
+  const res =  await clientGet<{value:number},CmdResponse>('/lamp/execution/secondRelay',{
+    params:{
+      value:cmd
+    }
+  })
+  if(res.code !== 200){
+    ElMessage.error("操作失败");
+    return
+  }
+  if(res.code === 200){
+    ElMessage.success("操作成功");
+    return
   }
 }
-const init = () => {
-  getData()
-}
-init()
+
+
+
 
 </script>
 
 <template>
-  <div>
-    <el-row :gutter="30" class="p-30px">
-      <el-col :span="24">
-        <el-row>
-          <el-col :span="6">
-            <el-button type="primary" @click="init">获取最新数据</el-button>
-          </el-col>
-          <el-col :span="4" :offset="14">
-            <el-button type="info" @click="toOtherLink('一键报警')">一键报警</el-button>
-            <el-button type="warning" @click="toOtherLink('灯杆显示屏')">灯杆显示屏</el-button>
-          </el-col>
-        </el-row>
-      </el-col>
-      <el-col :span="12" sm="24" v-for="(item,index) in cardDatas" :key="index" class="my-4">
-        <el-card>
-          <template #header>
-            <div class="flex gap-1 justify-between px-3">
-              <div class="flex gap-1">
-                <div class="w-20px h-20px">
-                  <img class="w-full h-full" src="/src/assets/svg/灯杆.svg"  alt="灯杆"/>
+  <el-row :gutter="20" class="p-20px">
+    <el-col class="mb-20px" :lg="12" :sm="24">
+      <el-card class="h-45vh">
+        <template #header>
+          一路继电器-路灯
+        </template>
+        <template #default>
+          <div class="flex items-center gap-20px">
+            <div class="w-50%">
+              <img class="w-full h-full" src="/src/assets/灯杆图片.jpg" alt="路灯图片" />
+            </div>
+            <el-row class="w-50%">
+              <el-col :span="18" :offset="6">
+                <div class="mb-20px">
+                  <el-button type="success" @click="contollerLamp(1)">开启</el-button>
+                </div>
+                <div>
+                  <el-button type="danger" @click="contollerLamp(0)">关闭</el-button>
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+        </template>
+      </el-card>
+    </el-col>
+    <el-col class="mb-20px" :lg="12" :sm="24">
+      <el-card class="h-45vh">
+        <template #header>
+          二路继电器-路灯
+        </template>
+        <template #default>
+          <div class="flex items-center gap-20px">
+            <div class="w-50%">
+              <img class="w-full h-full" src="/src/assets/灯杆图片.jpg" alt="路灯图片" />
+            </div>
+            <el-row class="w-50%">
+              <el-col :span="18" :offset="6">
+                <div class="mb-20px">
+                  <el-button type="success" @click="contollerLamp2(1)">开启</el-button>
+                </div>
+                <div>
+                  <el-button type="danger" @click="contollerLamp2(0)">关闭</el-button>
                 </div>
-                <div>灯杆信息</div>
+              </el-col>
+            </el-row>
+          </div>
+        </template>
+      </el-card>
+    </el-col>
+    <el-col class="mb-20px" :lg="12" :sm="24">
+      <el-card class="h-40vh">
+        <template #header>
+          定时任务
+        </template>
+        <template #default>
+          <div class="mb-20px flex items-center">
+            <div class="w-35%">
+              <img class="w-full h-full" alt="设置的图片" src="/src/assets/设置图片.jpg" />
+            </div>
+            <div class="w-65%">
+              <div class="mb-30px">
+                <el-time-picker v-model="onTime" value-format="HH:mm:ss" placeholder="请选择定时开启时间" />
+                <el-button type="primary" @click="setOnTime">设置定时开启时间</el-button>
               </div>
               <div>
-                <el-button @click="updateCurrentData(item)">更新当前灯杆数据</el-button>
+                <el-time-picker v-model="offTime" value-format="HH:mm:ss" placeholder="请选择定时关闭时间" />
+                <el-button type="primary" @click="setOffTime">设置定时关闭时间</el-button>
               </div>
             </div>
-          </template>
-          <template #default>
-            <el-descriptions :title="'灯杆编号'+item.light_num" :column="2" border>
-              <el-descriptions-item
-                label="电压"
-                label-align="right"
-                align="center"
-              >
-                {{ item.voltage.toFixed(2) + 'V' }}
-              </el-descriptions-item>
-              <el-descriptions-item label="电流" label-align="right" align="center">
-                {{ item.current.toFixed(2) + 'A' }}
-              </el-descriptions-item>
-              <el-descriptions-item label="功率" label-align="right" align="center">
-                {{ item.power.toFixed(3) + 'kW' }}
-              </el-descriptions-item>
-              <el-descriptions-item label="电量" label-align="right" align="center">
-                {{ item.power_quantity.toFixed(2) + '度' }}
-              </el-descriptions-item>
-              <el-descriptions-item label="在线状态" label-align="right" align="center">
-                <el-tag :type="item.onlineStatus==1?'success':'danger'">
-                  <span v-if="item.onlineStatus==1">在线</span>
-                  <span v-else>离线</span>
-                </el-tag>
-              </el-descriptions-item>
-              <el-descriptions-item label="开关" label-align="right" align="center" class-name="flex gap-20px">
-                <el-text>当前
-                  <el-tag :type="item.brightness?'success':'danger'">{{ item.brightness ? '开' : '关' }}</el-tag>
-                </el-text>
-                <el-button :type="item.brightness?'info':'primary'" @click="changeLight(item)">
-                  {{ item.brightness ? '关闭' : '打开' }}
-                </el-button>
-              </el-descriptions-item>
-            </el-descriptions>
-          </template>
-        </el-card>
-      </el-col>
-    </el-row>
-    <el-dialog v-model="linkDialogVisible" title="请下载大屏显示器软件">
-      <template #default>
-        <div class="flex flex-col gap-10px">
-          <div>
-            <a :href="'/LedOK Express.rar'" download="LedOK_Express.rar">下载大屏显示器软件</a>
           </div>
-        </div>
-      </template>
-      <template #footer>
-        <el-button @click="linkDialogVisible=false">关闭</el-button>
-      </template>
-    </el-dialog>
-  </div>
+        </template>
+      </el-card>
+    </el-col>
+  </el-row>
 </template>

+ 11 - 10
vite.config.ts

@@ -28,14 +28,15 @@ export default defineConfig({
       '@': fileURLToPath(new URL('./src', import.meta.url))
     },
   },
-  // server: {
-  //   proxy: {
-  //     '/api': {
-  //       // target: 'http://172.16.102.52:8080',
-  //        target: 'http://192.168.110.13:8080',
-  //       changeOrigin: true,
-  //       rewrite: (path) => path.replace(/^\/api/, '')
-  //     }
-  //   }
-  // }
+  server: {
+    proxy: {
+      '/api': {
+        // target: 'http://172.16.102.52:8080',
+        //  target: 'http://localhost:8080',
+         target: 'http://172.16.102.52:8080',
+        changeOrigin: true,
+        rewrite: (path) => path.replace(/^\/api/, '')
+      }
+    }
+  }
 })