houzhongjian
2024-11-15 aed8e13b3cbca5c83fbd0d8a57a3e0d9e6e8c561
1、大华和海康摄像头图像采集功能开发
已添加2个文件
已删除1个文件
已修改9个文件
276 ■■■■ 文件已修改
src/api/data/video/image/index.ts 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/hostMap.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/is.ts 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home/Index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/LoginForm.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/index.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/simpleWorkflow/index.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/video/camera/CameraImage.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/video/camera/index.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/video/nvr/NvrCamera.vue 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/video/nvr/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/env.d.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/data/video/image/index.ts
对比新文件
@@ -0,0 +1,50 @@
import request from '@/config/axios'
export interface ImageVO {
  id: undefined,
  cameraId: string,
  imagePath: string,
  imageUrl: string,
  createDate: undefined,
}
// 查询列表
export const getImagePage = (params: PageParam) => {
  return request.get({url: '/data/video/image/page', params})
}
// 获得
export const getImage = (id: number) => {
  return request.get({url: '/data/video/image/get?id=' + id})
}
// 查询应用列表
export const getImageList = () => {
  return request.get({url: '/data/video/image/list'})
}
// 新增
export const createImage = (data: ImageVO) => {
  return request.post({url: '/data/video/image/create', data})
}
// 修改
export const updateImage = (data: ImageVO) => {
  return request.put({url: '/data/video/image/update', data})
}
// 删除
export const deleteImage = (id: number) => {
  return request.delete({url: '/data/video/image/delete?id=' + id})
}
// 导出
export const exportImage = (params: ImageVO) => {
  return request.download({url: '/data/video/image/export-excel', params})
}
//预览摄像头截图
export const getPreviewUrl = (url: string) => {
  const host = import.meta.env.VITE_VIDEO_CAMERA_DOMAIN ? import.meta.env.VITE_VIDEO_CAMERA_DOMAIN : window.location.host
  return `http://${host}:8899` + url
}
src/utils/hostMap.ts
@@ -1,6 +1,6 @@
const map = {
  "//localhost:7200/": "//wujie-micro.github.io/demo-vue2/",
  "//localhost:90/": "//localhost:90/",
  "//localhost:9000/": "//localhost:9000/",
  "//localhost:8000/": "//wujie-micro.github.io/demo-main-vue/",
};
src/utils/is.ts
@@ -98,8 +98,9 @@
export const isClient = !isServer
export const isUrl = (path: string): boolean => {
  // fix:修复hash路由无法跳转的问题
  const reg =
    /(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/
    /(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%#\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/
  return reg.test(path)
}
src/views/Home/Index.vue
@@ -19,7 +19,6 @@
import * as AppApi from '@/api/system/app'
import {Apps} from "@/views/Home/types";
import {CACHE_KEY, useCache} from "@/hooks/web/useCache";
import * as authUtil from "@/utils/auth";
defineOptions({ name: 'Home' })
@@ -35,7 +34,7 @@
  appList = Object.assign(appList, data)
}
const getAppMenuList = async (id) => {
const getAppMenuList = async (id, appCode) => {
  const data = await AppApi.getAppMenuList(id)
  let userInfo = wsCache.get(CACHE_KEY.USER)
  userInfo.menus = data
@@ -55,19 +54,24 @@
// 进入应用
const gotoApp = async (item) => {
  let path = window.location.pathname
  let appName = path.split("/")[0]
  console.log(appName)
  let id = item.id
  let type = item.type
  let appCode = item.appCode
  if(type === 0) {
    getAppMenuList(id)
    await getAppMenuList(id, appCode)
  } else {
    const data = await AppApi.getAppMenuList(id)
    let userInfo = wsCache.get(CACHE_KEY.USER)
    userInfo.menus = data
    wsCache.set(CACHE_KEY.USER, userInfo)
    wsCache.set(CACHE_KEY.ROLE_ROUTERS, data)
    // await OAuth2Login(formData.value)
    // window.open(item.appDomain + '/login?appid=' + item.id + "&username=" + authUtil.getLoginForm().username, '_blank')
    window.open(item.appDomain + '/index', '_blank')
    // window.open('/plat/shasteel', '_blank')
    // window.location.href = '/plat/shasteel'
    // window.location.href = `/plat/shasteel?key=energy&url=http://localhost:9000&energy=/energy/demo`
  }
}
@@ -80,6 +84,7 @@
  display: inline-block;
  background: transparent;
}
.card{
  border: thin dashed gainsboro;
  width: 150px;
src/views/Login/components/LoginForm.vue
@@ -199,7 +199,7 @@
      authUtil.removeLoginForm()
    }
    authUtil.setToken(res)
    if (!redirect.value) {
    if (!redirect.value || redirect.value == "/") {
      redirect.value = '/index'
    }
    // 判断是否为SSO登录
src/views/bpm/model/index.vue
@@ -163,14 +163,6 @@
          <el-button
            link
            type="primary"
            @click="handleSimpleDesign(scope.row.id)"
            v-hasPermi="['bpm:model:update']"
          >
            仿钉钉设计流程
          </el-button>
          <el-button
            link
            type="primary"
            @click="handleDeploy(scope.row)"
            v-hasPermi="['bpm:model:deploy']"
          >
@@ -328,15 +320,6 @@
const handleDesign = (row) => {
  push({
    name: 'BpmModelEditor',
    query: {
      modelId: row.id
    }
  })
}
const handleSimpleDesign = (row) => {
  push({
    name: 'SimpleWorkflowDesignEditor',
    query: {
      modelId: row.id
    }
src/views/bpm/simpleWorkflow/index.vue
文件已删除
src/views/data/video/camera/CameraImage.vue
对比新文件
@@ -0,0 +1,114 @@
<template>
  <el-dialog v-model="dialogVisible" :title="dialogTitle" :close="handleClose"
             style="width: 50%; margin-top: 20px; overflow: auto; z-index: 1">
    <!-- 列表 -->
    <el-table v-loading="loading" :data="list">
      <el-table-column
        label="截图时间"
        align="center"
        prop="createDate"
        :formatter="dateFormatter"
        width="200"
      />
      <el-table-column label="图片路径" align="center" prop="imagePath" width="500"
                       :show-overflow-tooltip="true"/>
      <el-table-column label="图片预览" align="center" prop="imageUrl">
        <template #default="scope">
          <el-image style="height: 50px; z-index: 1"
                    :src="getPreviewUrl(scope.row.imageUrl)"
                    :preview-src-list="getPreviewSrcList(scope.row.imageUrl)" fit="cover"
                    preview-teleported/>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" min-width="60" fixed="right">
        <template #default="scope">
          <el-button
            link
            type="danger"
            style="z-index: 1"
            @click="handleDelete(scope.row.id)"
            v-hasPermi="['video:camera:delete']"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <Pagination
      :total="total"
      v-model:page="queryParams.pageNo"
      v-model:limit="queryParams.pageSize"
      @pagination="open"
    />
  </el-dialog>
</template>
<script lang="ts" setup>
import * as ImageApi from '@/api/data/video/image'
import {getPreviewUrl} from "@/api/data/video/image";
import {dateFormatter} from "@/utils/formatTime";
defineOptions({name: 'CameraImage'})
const message = useMessage() // 消息弹窗
const {t} = useI18n() // 国际化
const dialogTitle = ref('截图列表')
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  id: undefined,
  brand: undefined,
  code: undefined,
  device: undefined,
  cameraId: '',
  imagePath: undefined,
  imageUrl: undefined,
  createDate: undefined,
})
const cameraId = ref('')
const dialogVisible = ref(false)
/** 查询列表 */
const open = async (camera_id: string) => {
  dialogVisible.value = true
  cameraId.value = camera_id
  queryParams.cameraId = camera_id
  loading.value = true
  try {
    const data = await ImageApi.getImagePage(queryParams)
    list.value = data.list
    total.value = data.total
  } finally {
    loading.value = false
  }
}
defineExpose({open}) // 提供 open 方法,用于打开弹窗
const handleClose = async () => {
  dialogVisible.value = false
}
const getPreviewSrcList = (imageUrl: string) => {
  let previewSrcList: string[] = []
  previewSrcList.push(getPreviewUrl(imageUrl))
  return previewSrcList
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
  try {
    // 删除的二次确认
    await message.delConfirm()
    // 发起删除
    await ImageApi.deleteImage(id)
    message.success(t('common.delSuccess'))
    // 刷新列表
    await open(cameraId.value)
  } catch {
  }
}
</script>
src/views/data/video/camera/index.vue
@@ -102,7 +102,8 @@
      <el-table-column label="设备类型" align="center" prop="device" width="200"/>
      <el-table-column label="编码" align="center" prop="code" width="200"/>
      <el-table-column label="IP" align="center" prop="ip" />
      <el-table-column label="端口" align="center" prop="port" width="100"/>
      <el-table-column label="端口" align="center" prop="port" width="80"/>
      <el-table-column label="通道" align="center" prop="channel" width="80"/>
      <el-table-column label="用户名" align="center" prop="username" width="100"/>
      <el-table-column label="状态" prop="status" width="80">
        <template #default="scope">
@@ -129,6 +130,14 @@
          >
            删除
          </el-button>
          <el-button
            link
            type="success"
            @click="imageHandle(scope.row.id)"
            v-hasPermi="['video:image:query']"
          >
            查看截图
          </el-button>
        </template>
      </el-table-column>
    </el-table>
@@ -144,6 +153,7 @@
  <!-- 表单弹窗:添加/修改 -->
  <CameraForm ref="formRef" @success="getList" />
  <CameraImage ref="imageFormRef"/>
</template>
<script lang="ts" setup>
@@ -151,6 +161,8 @@
  import download from '@/utils/download'
  import * as CameraApi from '@/api/data/video/camera'
  import CameraForm from './CameraForm.vue'
import CameraImage from './CameraImage.vue'
  defineOptions({name: 'Camera'})
@@ -195,6 +207,7 @@
  /** 重置按钮操作 */
  const resetQuery = () => {
    queryFormRef.value.resetFields()
  queryParams.brand = undefined
    handleQuery()
  }
@@ -218,6 +231,12 @@
    }
  }
/** 查看截图 */
const imageFormRef = ref()
const imageHandle = (id: string) => {
  imageFormRef.value.open(id)
}
  /** 导出按钮操作 */
  const handleExport = async () => {
    try {
src/views/data/video/nvr/NvrCamera.vue
@@ -79,6 +79,14 @@
          >
            删除
          </el-button>
            <el-button
              link
              type="success"
              @click="imageHandle(scope.row.id)"
              v-hasPermi="['video:image:query']"
            >
              查看截图
            </el-button>
        </template>
      </el-table-column>
    </el-table>
@@ -95,6 +103,7 @@
  <!-- 表单弹窗:添加/修改 -->
  <NvrCameraForm ref="formRef" @success="getList" />
  <CameraImage ref="imageFormRef"/>
</template>
<script lang="ts" setup>
@@ -102,6 +111,7 @@
import * as CameraApi from '@/api/data/video/camera'
import NvrCameraForm from './NvrCameraForm.vue'
import {DICT_TYPE} from "@/utils/dict";
import CameraImage from "../camera/CameraImage.vue";
defineOptions({name: 'NvrCamera'})
@@ -148,6 +158,12 @@
  }
}
/** 查看截图 */
const imageFormRef = ref()
const imageHandle = (id: string) => {
  imageFormRef.value.open(id)
}
/** 搜索按钮操作 */
const handleQuery = () => {
  queryParams.pageNo = 1
@@ -156,7 +172,7 @@
/** 重置按钮操作 */
const resetQuery = () => {
  queryFormRef.value.resetFields()
  queryParams.location = undefined
  handleQuery()
}
src/views/data/video/nvr/index.vue
@@ -100,7 +100,6 @@
          <dict-tag :type="DICT_TYPE.NVR_ONLINE_STATUS" :value="scope.row.status" />
        </template>
      </el-table-column>
      <el-table-column label="位置" align="center" prop="position" />
      <el-table-column label="备注" align="center" prop="remark" width="150"/>
      <el-table-column label="操作" align="center" min-width="110" fixed="right">
        <template #default="scope">
@@ -120,7 +119,8 @@
          >
            删除
          </el-button>
          <el-button link type="success" size="small" @click="cameraHandle(scope.row.id)">摄像头</el-button>
          <el-button link type="success" size="small" @click="cameraHandle(scope.row.id)">摄像头
          </el-button>
        </template>
      </el-table-column>
    </el-table>
@@ -195,6 +195,7 @@
  /** 重置按钮操作 */
  const resetQuery = () => {
    queryFormRef.value.resetFields()
  queryParams.brand = undefined
    handleQuery()
  }
types/env.d.ts
@@ -25,6 +25,7 @@
  readonly VITE_UPLOAD_URL: string
  readonly VITE_API_URL: string
  readonly VITE_BASE_PATH: string
  readonly VITE_VIDEO_CAMERA_DOMAIN: string
  readonly VITE_DROP_DEBUGGER: string
  readonly VITE_DROP_CONSOLE: string
  readonly VITE_SOURCEMAP: string