From 30566d41a16d4f87e9c58db316d6831abbb4a035 Mon Sep 17 00:00:00 2001 From: houzhongjian <houzhongyi@126.com> Date: 星期四, 24 十月 2024 17:39:51 +0800 Subject: [PATCH] 数据采集增加摄像头管理相关页面 --- src/views/data/dev/camera/camera.vue | 201 ++++++++++++ src/views/data/dev/nvr/index.vue | 242 +++++++++++++++ src/api/data/dev/camera/index.ts | 45 ++ src/views/data/dev/nvr/NvrForm.vue | 182 +++++++++++ src/utils/dict.ts | 79 ---- src/api/data/dev/nvr/index.ts | 50 +++ src/views/data/dev/camera/CameraForm.vue | 134 ++++++++ 7 files changed, 856 insertions(+), 77 deletions(-) diff --git a/src/api/data/dev/camera/index.ts b/src/api/data/dev/camera/index.ts new file mode 100644 index 0000000..b4b7719 --- /dev/null +++ b/src/api/data/dev/camera/index.ts @@ -0,0 +1,45 @@ +import request from '@/config/axios' + +export interface CameraVO { + id: undefined, + nvrId: string, + code: undefined, + channel: undefined, + location: undefined, + remark: undefined +} + +// 查询列表 +export const getCameraPage = (params: PageParam) => { + return request.get({ url: '/data/dev/camera/page', params }) +} + +// 获得 +export const getCamera = (id: number) => { + return request.get({ url: '/data/dev/camera/get?id=' + id }) +} + +// 查询应用列表 +export const getCameraList = () => { + return request.get({ url: '/data/dev/camera/list' }) +} + +// 新增 +export const createCamera = (data: CameraVO) => { + return request.post({ url: '/data/dev/camera/create', data }) +} + +// 修改 +export const updateCamera = (data: CameraVO) => { + return request.put({ url: '/data/dev/camera/update', data }) +} + +// 删除 +export const deleteCamera = (id: number) => { + return request.delete({ url: '/data/dev/camera/delete?id=' + id }) +} + +// 导出 +export const exportCamera = (params: CameraVO) => { + return request.download({ url: '/data/dev/camera/export-excel', params }) +} diff --git a/src/api/data/dev/nvr/index.ts b/src/api/data/dev/nvr/index.ts new file mode 100644 index 0000000..1ddf890 --- /dev/null +++ b/src/api/data/dev/nvr/index.ts @@ -0,0 +1,50 @@ +import request from '@/config/axios' + +export interface NvrVO { + id: undefined, + brand: undefined, + code: undefined, + name: undefined, + ip: undefined, + port: undefined, + username: undefined, + password: undefined, + device: undefined, + position: undefined, + remark: undefined +} + +// 查询列表 +export const getNvrPage = (params: PageParam) => { + return request.get({ url: '/data/dev/nvr/page', params }) +} + +// 获得 +export const getNvr = (id: number) => { + return request.get({ url: '/data/dev/nvr/get?id=' + id }) +} + +// 查询应用列表 +export const getNvrList = () => { + return request.get({ url: '/data/dev/nvr/list' }) +} + +// 新增 +export const createNvr = (data: NvrVO) => { + return request.post({ url: '/data/dev/nvr/create', data }) +} + +// 修改 +export const updateNvr = (data: NvrVO) => { + return request.put({ url: '/data/dev/nvr/update', data }) +} + +// 删除 +export const deleteNvr = (id: number) => { + return request.delete({ url: '/data/dev/nvr/delete?id=' + id }) +} + +// 导出 +export const exportNvr = (params: NvrVO) => { + return request.download({ url: '/data/dev/nvr/export-excel', params }) +} diff --git a/src/utils/dict.ts b/src/utils/dict.ts index dab3868..a9b5c62 100644 --- a/src/utils/dict.ts +++ b/src/utils/dict.ts @@ -153,83 +153,6 @@ BPM_PROCESS_LISTENER_TYPE = 'bpm_process_listener_type', BPM_PROCESS_LISTENER_VALUE_TYPE = 'bpm_process_listener_value_type', - // ========== PAY 模块 ========== - PAY_CHANNEL_CODE = 'pay_channel_code', // 支付渠道编码类型 - PAY_ORDER_STATUS = 'pay_order_status', // 商户支付订单状态 - PAY_REFUND_STATUS = 'pay_refund_status', // 退款订单状态 - PAY_NOTIFY_STATUS = 'pay_notify_status', // 商户支付回调状态 - PAY_NOTIFY_TYPE = 'pay_notify_type', // 商户支付回调状态 - PAY_TRANSFER_STATUS = 'pay_transfer_status', // 转账订单状态 - PAY_TRANSFER_TYPE = 'pay_transfer_type', // 转账订单状态 - - // ========== MP 模块 ========== - MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型 - MP_MESSAGE_TYPE = 'mp_message_type', // 消息类型 - - // ========== Member 会员模块 ========== - MEMBER_POINT_BIZ_TYPE = 'member_point_biz_type', // 积分的业务类型 - MEMBER_EXPERIENCE_BIZ_TYPE = 'member_experience_biz_type', // 会员经验业务类型 - - // ========== MALL - 商品模块 ========== - PRODUCT_SPU_STATUS = 'product_spu_status', //商品状态 - - // ========== MALL - 交易模块 ========== - EXPRESS_CHARGE_MODE = 'trade_delivery_express_charge_mode', //快递的计费方式 - TRADE_AFTER_SALE_STATUS = 'trade_after_sale_status', // 售后 - 状态 - TRADE_AFTER_SALE_WAY = 'trade_after_sale_way', // 售后 - 方式 - TRADE_AFTER_SALE_TYPE = 'trade_after_sale_type', // 售后 - 类型 - TRADE_ORDER_TYPE = 'trade_order_type', // 订单 - 类型 - TRADE_ORDER_STATUS = 'trade_order_status', // 订单 - 状态 - TRADE_ORDER_ITEM_AFTER_SALE_STATUS = 'trade_order_item_after_sale_status', // 订单项 - 售后状态 - TRADE_DELIVERY_TYPE = 'trade_delivery_type', // 配送方式 - BROKERAGE_ENABLED_CONDITION = 'brokerage_enabled_condition', // 分佣模式 - BROKERAGE_BIND_MODE = 'brokerage_bind_mode', // 分销关系绑定模式 - BROKERAGE_BANK_NAME = 'brokerage_bank_name', // 佣金提现银行 - BROKERAGE_WITHDRAW_TYPE = 'brokerage_withdraw_type', // 佣金提现类型 - BROKERAGE_RECORD_BIZ_TYPE = 'brokerage_record_biz_type', // 佣金业务类型 - BROKERAGE_RECORD_STATUS = 'brokerage_record_status', // 佣金状态 - BROKERAGE_WITHDRAW_STATUS = 'brokerage_withdraw_status', // 佣金提现状态 - - // ========== MALL - 营销模块 ========== - PROMOTION_DISCOUNT_TYPE = 'promotion_discount_type', // 优惠类型 - PROMOTION_PRODUCT_SCOPE = 'promotion_product_scope', // 营销的商品范围 - PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE = 'promotion_coupon_template_validity_type', // 优惠劵模板的有限期类型 - PROMOTION_COUPON_STATUS = 'promotion_coupon_status', // 优惠劵的状态 - PROMOTION_COUPON_TAKE_TYPE = 'promotion_coupon_take_type', // 优惠劵的领取方式 - PROMOTION_ACTIVITY_STATUS = 'promotion_activity_status', // 优惠活动的状态 - PROMOTION_CONDITION_TYPE = 'promotion_condition_type', // 营销的条件类型枚举 - PROMOTION_BARGAIN_RECORD_STATUS = 'promotion_bargain_record_status', // 砍价记录的状态 - PROMOTION_COMBINATION_RECORD_STATUS = 'promotion_combination_record_status', // 拼团记录的状态 - PROMOTION_BANNER_POSITION = 'promotion_banner_position', // banner 定位 - - // ========== CRM - 客户管理模块 ========== - CRM_AUDIT_STATUS = 'crm_audit_status', // CRM 审批状态 - CRM_BIZ_TYPE = 'crm_biz_type', // CRM 业务类型 - CRM_BUSINESS_END_STATUS_TYPE = 'crm_business_end_status_type', // CRM 商机结束状态类型 - CRM_RECEIVABLE_RETURN_TYPE = 'crm_receivable_return_type', // CRM 回款的还款方式 - CRM_CUSTOMER_INDUSTRY = 'crm_customer_industry', // CRM 客户所属行业 - CRM_CUSTOMER_LEVEL = 'crm_customer_level', // CRM 客户级别 - CRM_CUSTOMER_SOURCE = 'crm_customer_source', // CRM 客户来源 - CRM_PRODUCT_STATUS = 'crm_product_status', // CRM 商品状态 - CRM_PERMISSION_LEVEL = 'crm_permission_level', // CRM 数据权限的级别 - CRM_PRODUCT_UNIT = 'crm_product_unit', // CRM 产品单位 - CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // CRM 跟进方式 - - // ========== ERP - 企业资源计划模块 ========== - ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态 - ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type', // 库存明细的业务类型 - - // ========== AI - 人工智能模块 ========== - AI_PLATFORM = 'ai_platform', // AI 平台 - AI_IMAGE_STATUS = 'ai_image_status', // AI 图片状态 - AI_MUSIC_STATUS = 'ai_music_status', // AI 音乐状态 - AI_GENERATE_MODE = 'ai_generate_mode', // AI 生成模式 - AI_WRITE_TYPE = 'ai_write_type', // AI 写作类型 - AI_WRITE_LENGTH = 'ai_write_length', // AI 写作长度 - AI_WRITE_FORMAT = 'ai_write_format', // AI 写作格式 - AI_WRITE_TONE = 'ai_write_tone', // AI 写作语气 - AI_WRITE_LANGUAGE = 'ai_write_language', // AI 写作语言 - // ========== MODEL - 模型管理模块 ========== SCHE_MODEL_TYPE = 'sche_model_type', SCHE_MODEL_INVOCATION = 'sche_model_invocation', @@ -257,4 +180,6 @@ DATA_POINT_TYPE = 'data_point_type', MINFREQID = 'minfreqid', VALUETYPE = 'value_type', + NVR_ONLINE_STATUS = 'nvr_online_status', + CAMERA_BRAND = 'camera_brand', } diff --git a/src/views/data/dev/camera/CameraForm.vue b/src/views/data/dev/camera/CameraForm.vue new file mode 100644 index 0000000..d41a825 --- /dev/null +++ b/src/views/data/dev/camera/CameraForm.vue @@ -0,0 +1,134 @@ +<template> + <Dialog v-model="dialogVisible" :title="dialogTitle" width="50%"> + <el-form + ref="formRef" + v-loading="formLoading" + :model="formData" + :rules="formRules" + label-width="80px" + > + <el-row> + <el-col :span="12"> + <el-form-item label="编码" prop="code"> + <el-input v-model="formData.code" placeholder="请输入编码" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="通道" prop="channel"> + <el-input v-model="formData.channel" placeholder="请输入通道" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="监控区域" prop="location"> + <el-input v-model="formData.location" placeholder="请输入监控区域" /> + </el-form-item> + </el-col> + </el-row> + + <el-row> + <el-col :span="24"> + <el-form-item label="备注" prop="remark"> + <el-input v-model="formData.remark" clearable type="textarea" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> + <el-button @click="dialogVisible = false">取 消</el-button> + </template> + </Dialog> +</template> +<script lang="ts" setup> +import * as CameraApi from '@/api/data/dev/camera' + +defineOptions({ name: 'CameraForm' }) + +const { t } = useI18n() // 国际化 +const message = useMessage() // 消息弹窗 +const dialogVisible = ref(false) // 弹窗的是否展示 +const dialogTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const nvrId = ref('') // 录像机id +const formType = ref('') // 表单的类型:create - 新增;update - 修改 +const formData = ref({ + id: undefined, + nvrId: '', + code: undefined, + channel: undefined, + location: undefined, + remark: undefined +}) +const formRules = reactive({ + code: [{ required: true, message: '编码不能为空', trigger: 'blur' }], + channel: [{ required: true, message: '通道不能为空', trigger: 'blur' }], + location: [{ required: true, message: '监控区域不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref + +/** 打开弹窗 */ +const open = async (type: string, id?: number, nvr_id?: string) => { + dialogVisible.value = true + if (nvr_id != null) { + nvrId.value = nvr_id + } + dialogTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await CameraApi.getCamera(id) + } finally { + formLoading.value = false + } + } +} +defineExpose({ open }) // 提供 open 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value as unknown as CameraApi.CameraVO + if (formType.value === 'create') { + data.nvrId = nvrId.value + await CameraApi.createCamera(data) + message.success(t('common.createSuccess')) + } else { + await CameraApi.updateCamera(data) + message.success(t('common.updateSuccess')) + } + dialogVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} + +/** 重置表单 */ +const resetForm = () => { + formData.value = { + id: undefined, + brand: undefined, + code: undefined, + name: undefined, + ip: undefined, + port: undefined, + username: undefined, + password: undefined, + remark: undefined + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/data/dev/camera/camera.vue b/src/views/data/dev/camera/camera.vue new file mode 100644 index 0000000..69dcfcb --- /dev/null +++ b/src/views/data/dev/camera/camera.vue @@ -0,0 +1,201 @@ +<template> + <!-- 搜索 --> + <el-drawer + direction="rtl" + v-model="visible" + @close="handleClose" + size="60%"> + <div class="mod-dev__camera" style="padding: 10px;"> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > + <el-form-item label="监控区域" prop="code"> + <el-input + v-model="queryParams.location" + placeholder="请输入监控区域" + clearable + @keyup.enter="handleQuery" + class="!w-240px" + /> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"> + <Icon icon="ep:search" class="mr-5px" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon icon="ep:refresh" class="mr-5px" /> + 重置 + </el-button> + <el-button + type="primary" + plain + @click="openForm('create')" + > + <Icon icon="ep:plus" class="mr-5px" /> + 新增 + </el-button> + <el-button + type="success" + plain + @click="handleExport" + :loading="exportLoading" + v-hasPermi="['dev:camera:export']" + > + <Icon icon="ep:download" class="mr-5px" /> + 导出 + </el-button> + </el-form-item> + </el-form> + + <!-- 列表 --> + <el-table v-loading="loading" :data="list"> + <el-table-column label="编码" align="center" prop="code" /> + <el-table-column label="通道" align="center" prop="channel" /> + <el-table-column label="监控区域" align="center" prop="location" /> + <el-table-column label="备注" align="center" prop="remark" width="200" /> + <el-table-column label="操作" align="center" min-width="110" fixed="right"> + <template #default="scope"> + <el-button + link + type="primary" + @click="openForm('update', scope.row.id)" + > + 编辑 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + > + 删除 + </el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页 --> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </div> + </el-drawer> + + <!-- 表单弹窗:添加/修改 --> + <CameraForm ref="formRef" @success="getList" /> + + +</template> +<script lang="ts" setup> +import download from '@/utils/download' +import * as CameraApi from '@/api/data/dev/camera' +import CameraForm from './CameraForm.vue' + +defineOptions({name: 'Camera'}) + +const message = useMessage() // 消息弹窗 +const {t} = useI18n() // 国际化 + +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref([]) // 列表的数据 + +const nvrId = ref('') //录像机id + +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + nvrId: '', + location: undefined, + status: undefined +}) +const queryFormRef = ref() // 搜索的表单 +const exportLoading = ref(false) // 导出的加载中 + +const visible = ref(false) + +/** 打开弹窗 */ +const open = async (nvr_id: string) => { + visible.value = true + nvrId.value = nvr_id + queryParams.nvrId = nvr_id + await getList() +} + +defineExpose({ open }) // 提供 open 方法,用于打开弹窗 + +/** 查询列表 */ +const getList = async () => { + loading.value = true + try { + const data = await CameraApi.getCameraPage(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } +} + +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() +} + +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() +} + +/** 添加/修改操作 */ +const formRef = ref() +const openForm = (type: string, id?: number) => { + formRef.value.open(type, id, nvrId.value) +} + +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await CameraApi.deleteCamera(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch { + } +} + +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await CameraApi.exportCamera(queryParams) + download.excel(data, '摄像头列表.xls') + } catch { + } finally { + exportLoading.value = false + } +} + +const handleClose = () => { + queryFormRef.value.resetFields() + visible.value = false +} + +/** 初始化 **/ +onMounted(async () => { + await getList() +}) +</script> diff --git a/src/views/data/dev/nvr/NvrForm.vue b/src/views/data/dev/nvr/NvrForm.vue new file mode 100644 index 0000000..08ad22f --- /dev/null +++ b/src/views/data/dev/nvr/NvrForm.vue @@ -0,0 +1,182 @@ +<template> + <Dialog v-model="dialogVisible" :title="dialogTitle" width="50%"> + <el-form + ref="formRef" + v-loading="formLoading" + :model="formData" + :rules="formRules" + label-width="80px" + > + <el-row> + <el-col :span="12"> + <el-form-item label="品牌"> + <el-select v-model="formData.brand" placeholder="请选择"> + <el-option + v-for="dict in getIntDictOptions(DICT_TYPE.CAMERA_BRAND)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="formData.brand == 1"> + <el-col :span="12"> + <el-form-item label="编码" prop="code"> + <el-input v-model="formData.code" placeholder="请输入编码" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="名称" prop="name"> + <el-input v-model="formData.name" placeholder="请输入名称" /> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="formData.brand == 2"> + <el-col :span="12"> + <el-form-item label="设备类型" prop="device"> + <el-input v-model="formData.device" placeholder="请输入设备类型" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="位置" prop="position"> + <el-input v-model="formData.position" placeholder="请输入位置" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="IP" prop="ip"> + <el-input v-model="formData.ip" placeholder="请输入IP" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="端口" prop="port"> + <el-input v-model="formData.port" placeholder="请输入端口" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="用户名" prop="username"> + <el-input v-model="formData.username" placeholder="请输入用户名" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="密码" prop="password"> + <el-input show-password v-model="formData.password" placeholder="请输入密码" /> + </el-form-item> + </el-col> + </el-row> + + <el-row> + <el-col :span="24"> + <el-form-item label="备注" prop="remark"> + <el-input v-model="formData.remark" clearable type="textarea" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> + <el-button @click="dialogVisible = false">取 消</el-button> + </template> + </Dialog> +</template> +<script lang="ts" setup> + import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' + import * as NvrApi from '@/api/data/dev/nvr' + + defineOptions({ name: 'NvrForm' }) + + const { t } = useI18n() // 国际化 + const message = useMessage() // 消息弹窗 + const dialogVisible = ref(false) // 弹窗的是否展示 + const dialogTitle = ref('') // 弹窗的标题 + const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 + const formType = ref('') // 表单的类型:create - 新增;update - 修改 + const formData = ref({ + id: undefined, + brand: undefined, + code: undefined, + name: undefined, + ip: undefined, + port: undefined, + username: undefined, + password: undefined, + device: undefined, + position: undefined, + remark: undefined + }) + const formRules = reactive({ + brand: [{ required: true, message: '品牌不能为空', trigger: 'blur' }], + code: [{ required: true, message: '编码不能为空', trigger: 'blur' }], + device: [{ required: true, message: '设备类型不能为空', trigger: 'blur' }], + name: [{ required: true, message: '名称不能为空', trigger: 'blur' }], + ip: [{ required: true, message: 'IP不能为空', trigger: 'blur' }], + port: [{ required: true, message: '端口不能为空', trigger: 'blur' }] + }) + const formRef = ref() // 表单 Ref + + /** 打开弹窗 */ + const open = async (type: string, id?: number) => { + dialogVisible.value = true + dialogTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await NvrApi.getNvr(id) + } finally { + formLoading.value = false + } + } + } + defineExpose({ open }) // 提供 open 方法,用于打开弹窗 + + /** 提交表单 */ + const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 + const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value as unknown as NvrApi.NvrVO + console.log(data) + if (formType.value === 'create') { + await NvrApi.createNvr(data) + message.success(t('common.createSuccess')) + } else { + await NvrApi.updateNvr(data) + message.success(t('common.updateSuccess')) + } + dialogVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } + } + + /** 重置表单 */ + const resetForm = () => { + formData.value = { + id: undefined, + brand: undefined, + code: undefined, + name: undefined, + ip: undefined, + port: undefined, + username: undefined, + password: undefined, + remark: undefined + } + formRef.value?.resetFields() + } +</script> diff --git a/src/views/data/dev/nvr/index.vue b/src/views/data/dev/nvr/index.vue new file mode 100644 index 0000000..07f69c9 --- /dev/null +++ b/src/views/data/dev/nvr/index.vue @@ -0,0 +1,242 @@ +<template> + <!-- 搜索 --> + <ContentWrap> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="68px" + > + <el-form-item label="品牌" prop="status"> + <el-select + v-model="queryParams.brand" + placeholder="品牌" + clearable + class="!w-120px" + > + <el-option + v-for="dict in getIntDictOptions(DICT_TYPE.CAMERA_BRAND)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="编号" prop="code"> + <el-input + v-model="queryParams.code" + placeholder="请输入编号" + clearable + @keyup.enter="handleQuery" + class="!w-120px" + /> + </el-form-item> + <el-form-item label="IP" prop="name"> + <el-input + v-model="queryParams.ip" + placeholder="请输入IP" + clearable + @keyup.enter="handleQuery" + class="!w-120px" + /> + </el-form-item> + <el-form-item label="名称" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="请输入名称" + clearable + @keyup.enter="handleQuery" + class="!w-120px" + /> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"> + <Icon icon="ep:search" class="mr-5px" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon icon="ep:refresh" class="mr-5px" /> + 重置 + </el-button> + <el-button + type="primary" + plain + @click="openForm('create')" + v-hasPermi="['dev:nvr:save']" + > + <Icon icon="ep:plus" class="mr-5px" /> + 新增 + </el-button> + <el-button + type="success" + plain + @click="handleExport" + :loading="exportLoading" + v-hasPermi="['dev:nvr:export']" + > + <Icon icon="ep:download" class="mr-5px" /> + 导出 + </el-button> + </el-form-item> + </el-form> + </ContentWrap> + + <!-- 列表 --> + <ContentWrap> + <el-table v-loading="loading" :data="list"> + <el-table-column label="品牌" align="center" prop="brand" width="80"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.CAMERA_BRAND" :value="scope.row.brand" /> + </template> + </el-table-column> + <el-table-column label="设备类型" align="center" prop="device" width="200"/> + <el-table-column label="位置" align="center" prop="position" /> + <el-table-column label="编码" align="center" prop="code" width="100"/> + <el-table-column label="名称" align="center" prop="name"/> + <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="username" width="100"/> + <el-table-column label="状态" prop="status" width="80"> + <template #default="scope"> + <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"> + <el-button + link + type="primary" + @click="openForm('update', scope.row.id)" + v-hasPermi="['dev:nvr:update']" + > + 编辑 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['dev:nvr:delete']" + > + 删除 + </el-button> + <el-button v-if="scope.row.brand == 1" type="text" size="small" @click="cameraHandle(scope.row.id)">摄像头</el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页 --> + <Pagination + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </ContentWrap> + + <!-- 表单弹窗:添加/修改 --> + <NvrForm ref="formRef" @success="getList" /> + + <!-- 弹窗, 摄像头 --> + <Camera ref="devCameraRef"/> + +</template> +<script lang="ts" setup> +import {DICT_TYPE, getIntDictOptions} from '@/utils/dict' + import download from '@/utils/download' + import * as NvrApi from '@/api/data/dev/nvr' + import NvrForm from './NvrForm.vue' + import Camera from '../camera/camera.vue' + + defineOptions({name: 'Nvr'}) + + const message = useMessage() // 消息弹窗 + const {t} = useI18n() // 国际化 + + const loading = ref(true) // 列表的加载中 + const total = ref(0) // 列表的总页数 + const list = ref([]) // 列表的数据 + const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + brand: undefined, + ip: undefined, + code: undefined, + name: undefined, + status: undefined + }) + const queryFormRef = ref() // 搜索的表单 + const exportLoading = ref(false) // 导出的加载中 + + const devCameraRef = ref() + + /** 查询列表 */ + const getList = async () => { + loading.value = true + try { + const data = await NvrApi.getNvrPage(queryParams) + list.value = data.list + total.value = data.total + } finally { + loading.value = false + } + } + + const cameraHandle = (id: string) => { + // devCameraVisible.value = true + devCameraRef.value.open(id) + } + + /** 搜索按钮操作 */ + const handleQuery = () => { + queryParams.pageNo = 1 + getList() + } + + /** 重置按钮操作 */ + const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() + } + + /** 添加/修改操作 */ + const formRef = ref() + const openForm = (type: string, id?: number) => { + formRef.value.open(type, id) + } + + /** 删除按钮操作 */ + const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await NvrApi.deleteNvr(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch { + } + } + + /** 导出按钮操作 */ + const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await NvrApi.exportNvr(queryParams) + download.excel(data, '录像机列表.xls') + } catch { + } finally { + exportLoading.value = false + } + } + + /** 初始化 **/ + onMounted(async () => { + await getList() + }) +</script> -- Gitblit v1.9.3