|
@@ -0,0 +1,445 @@
|
|
|
+<template>
|
|
|
+ <xn-form-container
|
|
|
+ :title="formData.id ? '编辑采集器' : '新增采集器'"
|
|
|
+ :width="'60%'"
|
|
|
+ :visible="visible"
|
|
|
+ :destroy-on-close="true"
|
|
|
+ @close="onClose"
|
|
|
+ >
|
|
|
+ <a-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="formRules"
|
|
|
+ layout="inline"
|
|
|
+ :label-col="{ style: { width: '100px', justifyContent: 'end' } }"
|
|
|
+ >
|
|
|
+ <a-tabs v-model:activeKey="activeKey" type="editable-card" @edit="onEdit">
|
|
|
+ <a-tab-pane tab="对象信息" key="object" :closable="false">
|
|
|
+ <a-row :gutter="10">
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="采集器名称" name="name">
|
|
|
+ <a-input v-model:value="formData.name" placeholder="请输入采集器名称" allow-clear />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="采集器编号" name="code">
|
|
|
+ <a-input v-model:value="formData.code" placeholder="请输入采集器编号" allow-clear />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="采集器条码" name="barcode">
|
|
|
+ <a-input v-model:value="formData.barcode" placeholder="请输入采集器条码" allow-clear />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="品牌" name="brand">
|
|
|
+ <a-input v-model:value="formData.brand" placeholder="请输入品牌" allow-clear />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="状态" name="state">
|
|
|
+ <a-select ref="select" v-model:value="formData.state">
|
|
|
+ <a-select-option value="1">正常</a-select-option>
|
|
|
+ <a-select-option value="2">维修</a-select-option>
|
|
|
+ <a-select-option value="3">闲置</a-select-option>
|
|
|
+ <a-select-option value="4">报废</a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="所属部门">
|
|
|
+ <a-input v-model:value="formData.division" placeholder="请输入所属部门" allow-clear />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="采集时间">
|
|
|
+ <a-time-range-picker v-model:value="formData.collectionTime" style="width: 100%" />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
|
|
+ <a-form-item label="位置">
|
|
|
+ <a-input v-model:value="formData.location" placeholder="请输入位置" allow-clear />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
|
|
+ <a-form-item label="备注">
|
|
|
+ <a-textarea
|
|
|
+ v-model:value="formData.remarks"
|
|
|
+ placeholder="请输入备注"
|
|
|
+ allow-clear
|
|
|
+ :maxlength="200"
|
|
|
+ :rows="4"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ </a-tab-pane>
|
|
|
+ <a-tab-pane tab="报警信息" key="report" :closable="false">
|
|
|
+ <a-form-item :label-col="{ style: { width: '200px' } }">
|
|
|
+ <template #label>
|
|
|
+ <a-tooltip>
|
|
|
+ <template #title>
|
|
|
+ 重复通知间隔:同一设备同一故障类型出现报警进行过一次报警通知后,进行下一次报普通知的间隔时间,如果在这个时间间隔内该设备同一故障类型
|
|
|
+ 还在产生报警则不再进行通知。
|
|
|
+ 最多报警次数:同一设备同一故障类型连续报警最多报警通知次数,在达到最多报警次数后如果报警还未及时处理,系统也不再进行报警通知。
|
|
|
+ 延时时间:为屏蔽误报,系统报警在达到延时时间之后才进行报警通知。
|
|
|
+ </template>
|
|
|
+ <question-circle-outlined />
|
|
|
+ </a-tooltip>
|
|
|
+ 重复发送通知:
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <a-radio-group v-model:value="formData.repeat">
|
|
|
+ <a-radio value="1">1次</a-radio>
|
|
|
+ <a-radio value="2">多次</a-radio>
|
|
|
+ </a-radio-group>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="延时报警" :label-col="{ style: { width: '200px' } }">
|
|
|
+ <a-radio-group v-model:value="formData.delayed">
|
|
|
+ <a-radio value="1">是</a-radio>
|
|
|
+ <a-radio value="0">否</a-radio>
|
|
|
+ </a-radio-group>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="报警关闭发送通知" :label-col="{ style: { width: '200px' } }">
|
|
|
+ <a-radio-group v-model:value="formData.close">
|
|
|
+ <a-radio value="1">是</a-radio>
|
|
|
+ <a-radio value="0">否</a-radio>
|
|
|
+ </a-radio-group>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="多级报警" :label-col="{ style: { width: '200px' } }">
|
|
|
+ <a-radio-group v-model:value="formData.multistage">
|
|
|
+ <a-radio value="1">是</a-radio>
|
|
|
+ <a-radio value="0">否</a-radio>
|
|
|
+ </a-radio-group>
|
|
|
+ </a-form-item>
|
|
|
+
|
|
|
+ <a-form-item label="报警通知方式" :label-col="{ style: { width: '200px' } }">
|
|
|
+ <a-checkbox-group v-model:value="formData.noticeway" style="width: 100%">
|
|
|
+ <a-checkbox value="1">短信</a-checkbox>
|
|
|
+ <a-checkbox value="2">电话</a-checkbox>
|
|
|
+ <a-checkbox value="3">微信</a-checkbox>
|
|
|
+ <a-checkbox value="4">电子邮件</a-checkbox>
|
|
|
+ <a-checkbox value="5">弹出</a-checkbox>
|
|
|
+ <a-checkbox value="6">音乐</a-checkbox>
|
|
|
+ </a-checkbox-group>
|
|
|
+ </a-form-item>
|
|
|
+
|
|
|
+ <!-- 表格区域 -->
|
|
|
+ <div>
|
|
|
+ <a-button type="primary" style="margin-left: 90%; margin-bottom: 5px" @click="tableAdd">
|
|
|
+ <template #icon><plus-outlined /></template>新增
|
|
|
+ </a-button>
|
|
|
+ <a-table
|
|
|
+ ref="tableRef"
|
|
|
+ bordered
|
|
|
+ :columns="columns"
|
|
|
+ :data-source="formData.loadData"
|
|
|
+ :row-key="(record) => record.startTime"
|
|
|
+ >
|
|
|
+ <template #bodyCell="{ column, record, index }">
|
|
|
+ <!-- 表格内容 -->
|
|
|
+ <template v-if="column.dataIndex === 'startTime'">
|
|
|
+ <a-date-picker
|
|
|
+ v-model:value="record.startTime"
|
|
|
+ show-time
|
|
|
+ format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ style="width: 100%"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="column.dataIndex === 'endTime'">
|
|
|
+ <a-date-picker
|
|
|
+ v-model:value="record.endTime"
|
|
|
+ show-time
|
|
|
+ format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ style="width: 100%"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="column.dataIndex === 'name'">
|
|
|
+ <a-input v-model:value="record.name" placeholder="请输入姓名" />
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="column.dataIndex === 'remindType'">
|
|
|
+ <a-select v-model:value="record.remindType" placeholder="请选择提醒方式" style="width: 100%">
|
|
|
+ <a-select-option value="1">短信报警</a-select-option>
|
|
|
+ <a-select-option value="2">电话报警</a-select-option>
|
|
|
+ <a-select-option value="3">微信公众号报警</a-select-option>
|
|
|
+ <a-select-option value="4">邮件报警</a-select-option>
|
|
|
+ <a-select-option value="5">弹出报警</a-select-option>
|
|
|
+ <a-select-option value="6">音乐报警</a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="column.dataIndex === 'level'">
|
|
|
+ <a-select v-model:value="record.level" placeholder="请选择提醒方式" style="width: 100px">
|
|
|
+ <a-select-option value="1">1</a-select-option>
|
|
|
+ <a-select-option value="2">2</a-select-option>
|
|
|
+ <a-select-option value="3">3</a-select-option>
|
|
|
+ <a-select-option value="4">4</a-select-option>
|
|
|
+ <a-select-option value="5">5</a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="column.dataIndex === 'phone'">
|
|
|
+ <a-input v-model:value="record.phone" placeholder="请输入电话号码" />
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="column.dataIndex === 'action'">
|
|
|
+ <a-popconfirm title="确定要删除吗?" @confirm="tableDelete(record, index)">
|
|
|
+ <a-button type="link" danger size="small">删除</a-button>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
+ </div>
|
|
|
+ </a-tab-pane>
|
|
|
+
|
|
|
+ <a-tab-pane v-for="pane in panes" :key="pane.key" :tab="pane.title" :closable="pane.closable">
|
|
|
+ <!-- 新增路数-->
|
|
|
+ <div v-for="(item, index) in formData.list" :key="index">
|
|
|
+ <a-row :gutter="10" v-if="activeKey == item.key">
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="传感器路数">
|
|
|
+ <a-input v-model:value="item.number" placeholder="请输入传感器路数" allow-clear />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+
|
|
|
+ <a-col :xs="24" :sm="24" :md="12" :lg="8" :xl="12">
|
|
|
+ <a-form-item label="传感器类型">
|
|
|
+ <a-select ref="select" v-model:value="item.sensorType" placeholder="请选择传感器类型">
|
|
|
+ <a-select-option value="1">温度</a-select-option>
|
|
|
+ <a-select-option value="2">温湿度</a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+
|
|
|
+ <a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
|
|
+ <a-form-item label="备注">
|
|
|
+ <a-textarea
|
|
|
+ v-model:value="item.numberRemarks"
|
|
|
+ placeholder="请输入备注"
|
|
|
+ allow-clear
|
|
|
+ :maxlength="200"
|
|
|
+ :rows="4"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ </div>
|
|
|
+ </a-tab-pane>
|
|
|
+ </a-tabs>
|
|
|
+ </a-form>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <a-button class="xn-mr8" @click="onClose">退出</a-button>
|
|
|
+ <a-button type="primary" @click="onSubmit">保存</a-button>
|
|
|
+ </template>
|
|
|
+ <Icon-selector ref="iconSelectorRef" @iconCallBack="iconCallBack" />
|
|
|
+ </xn-form-container>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+ import jobApi from '@/api/dev/jobApi'
|
|
|
+ import { required } from '@/utils/formRules'
|
|
|
+ import moduleApi from '@/api/sys/resource/moduleApi'
|
|
|
+
|
|
|
+ import IconSelector from '@/components/Selector/iconSelector.vue'
|
|
|
+ // 默认是关闭状态
|
|
|
+ const visible = ref(false)
|
|
|
+ const emit = defineEmits({ successful: null })
|
|
|
+ const formRef = ref()
|
|
|
+ const iconSelectorRef = ref()
|
|
|
+
|
|
|
+ const tableRef = ref()
|
|
|
+
|
|
|
+ const columns = [
|
|
|
+ {
|
|
|
+ title: '开始时间',
|
|
|
+ dataIndex: 'startTime',
|
|
|
+ rules: [{ required: true, message: '请选择开始时间' }]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '结束时间',
|
|
|
+ dataIndex: 'endTime',
|
|
|
+ rules: [{ required: true, message: '请选择结束时间' }]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '姓名',
|
|
|
+ dataIndex: 'name',
|
|
|
+ rules: [{ required: true, message: '请输入姓名' }]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '提醒方式',
|
|
|
+ dataIndex: 'remindType',
|
|
|
+ rules: [{ required: true, message: '请选择提醒方式' }]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '级别',
|
|
|
+ dataIndex: 'level',
|
|
|
+ rules: [{ required: true, message: '请选择级别' }]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '电话号码',
|
|
|
+ dataIndex: 'phone',
|
|
|
+ rules: [
|
|
|
+ { required: true, message: '请输入电话号码' },
|
|
|
+ { pattern: /^[0-9]{11}$/, message: '请输入有效的电话号码' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ dataIndex: 'action',
|
|
|
+ scopedSlots: { customRender: 'action' }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ // 表单数据
|
|
|
+ const formData = ref({
|
|
|
+ repeat: '1',
|
|
|
+ delayed: '0',
|
|
|
+ close: '1',
|
|
|
+ multistage: '0',
|
|
|
+ noticeway: ['1'],
|
|
|
+ loadData: [],
|
|
|
+ list: []
|
|
|
+ })
|
|
|
+
|
|
|
+ // 打开抽屉
|
|
|
+ const onOpen = (record) => {
|
|
|
+ visible.value = true
|
|
|
+ activeKey.value = 'object'
|
|
|
+ panes.value = []
|
|
|
+ newTabIndex.value = 1
|
|
|
+ if (record) {
|
|
|
+ formData.value = Object.assign({}, record)
|
|
|
+ } else {
|
|
|
+ formData.value = {
|
|
|
+ repeat: '1',
|
|
|
+ delayed: '0',
|
|
|
+ close: '1',
|
|
|
+ multistage: '0',
|
|
|
+ noticeway: ['1'],
|
|
|
+ loadData: [],
|
|
|
+ list: []
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 关闭抽屉
|
|
|
+ const onClose = () => {
|
|
|
+ formRef.value.resetFields()
|
|
|
+ visible.value = false
|
|
|
+ }
|
|
|
+
|
|
|
+ // 默认要校验的
|
|
|
+ const formRules = {
|
|
|
+ name: [required('请输入采集器名称')],
|
|
|
+ code: [required('请输入采集器编号')]
|
|
|
+ }
|
|
|
+
|
|
|
+ // 表格添加一行空数据
|
|
|
+ const tableAdd = () => {
|
|
|
+ const newRow = {
|
|
|
+ startTime: null,
|
|
|
+ endTime: null,
|
|
|
+ name: '',
|
|
|
+ level: '',
|
|
|
+ phone: ''
|
|
|
+ }
|
|
|
+ formData.value.loadData.push(newRow)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除某一行
|
|
|
+ const tableDelete = (record, index) => {
|
|
|
+ formData.value.loadData.splice(index, 1)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证并提交数据
|
|
|
+ const onSubmit = async () => {
|
|
|
+ try {
|
|
|
+ // 校验主表单数据
|
|
|
+ await formRef.value.validate()
|
|
|
+ console.log('主表单数据验证通过')
|
|
|
+
|
|
|
+ // 校验表格行数据
|
|
|
+ for (const [index, row] of formData.value.loadData.entries()) {
|
|
|
+ const rowForm = tableRef.value.$el.querySelectorAll('.ant-form')[index]
|
|
|
+ console.log(rowForm, 'rowForm')
|
|
|
+
|
|
|
+ // const formInstance = rowForm.__vue__
|
|
|
+ // await formInstance.validate() // 校验单行表单
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('表单数据验证通过,开始提交...')
|
|
|
+ } catch (error) {
|
|
|
+ console.log('表单验证失败', error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 新增或删除路数
|
|
|
+ const onEdit = (targetKey, action) => {
|
|
|
+ if (action === 'add') {
|
|
|
+ add()
|
|
|
+ } else {
|
|
|
+ remove(targetKey)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const activeKey = ref('object') //选中的tabs
|
|
|
+ const panes = ref([]) //tabs数组
|
|
|
+ const newTabIndex = ref(1)
|
|
|
+ // 添加tabs
|
|
|
+ const add = () => {
|
|
|
+ const newIndex = newTabIndex.value++
|
|
|
+ if (panes.value.length >= 5) return //最多只能5路
|
|
|
+ panes.value.push({
|
|
|
+ title: `${newIndex}路`,
|
|
|
+ key: newIndex
|
|
|
+ })
|
|
|
+
|
|
|
+ formData.value.list.push({
|
|
|
+ title: `${newIndex}路`,
|
|
|
+ key: newIndex
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除tabs
|
|
|
+ const remove = (targetKey) => {
|
|
|
+ let lastIndex = 0
|
|
|
+ panes.value.forEach((pane, i) => {
|
|
|
+ if (pane.key === targetKey) {
|
|
|
+ lastIndex = i - 1
|
|
|
+ }
|
|
|
+ })
|
|
|
+ panes.value = panes.value.filter((pane) => pane.key !== targetKey)
|
|
|
+ if (panes.value.length && activeKey.value === targetKey) {
|
|
|
+ if (lastIndex >= 0) {
|
|
|
+ activeKey.value = panes.value[lastIndex].key
|
|
|
+ } else {
|
|
|
+ activeKey.value = panes.value[0].key
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (panes.value.length == 0) {
|
|
|
+ activeKey.value = 'object'
|
|
|
+ }
|
|
|
+
|
|
|
+ formData.value.list = formData.value.list.filter((item) => item.key !== targetKey) //删除表单
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用这个函数将子组件的一些数据和方法暴露出去
|
|
|
+ defineExpose({
|
|
|
+ onOpen
|
|
|
+ })
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less" scoped>
|
|
|
+ .ant-tabs {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ :deep(.ant-col) {
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+</style>
|