door-content-r.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. <template>
  2. <div class="door-content-r">
  3. <div class="content-r-btn">
  4. <a-button type="primary" @click="handlerOpenOrClose('open')">
  5. <SvgIcon class="icon-style" size="14" color="#30b3fc" name="open-door" />
  6. 同步开启
  7. </a-button>
  8. <a-button type="primary" class="btn-control" @click="handlerOpenOrClose('close')">
  9. <SvgIcon class="icon-style" size="14" color="#30b3fc" name="close-door" />
  10. 同步关闭
  11. </a-button>
  12. <a-button type="primary" @click="handlerTimeSet">
  13. <SvgIcon class="icon-style" size="14" color="#30b3fc" name="time-setting-door" />
  14. 定时设置
  15. </a-button>
  16. <a-button class="btn-control" type="primary" @click="handlerOperation">操作日志</a-button>
  17. <a-button type="primary" @click="handlerClock">同步PLC时钟</a-button>
  18. <a-button class="btn-control" type="primary" @click="handlerCameraDetail">视频墙详情</a-button>
  19. <a-button :class="index % 2 == 1 ? 'btn-control' : ''" v-for="(item, index) in dictCodes" :key="index"
  20. type="primary" @click="handlerFz(item)">{{ item.title }}</a-button>
  21. <a-button class="device-control-btn" type="primary" @click="handlerDeviceChoice">集控设备选择</a-button>
  22. </div>
  23. <div class="content-r-container">
  24. <div class="content-r-box" v-for="(item, index) in infoDatas" :key="index" @click="handlerAddorDel(item)">
  25. <div class="box-title">
  26. <SvgIcon v-show="item.iconControl" class="title-icon" size="16" name="select-control" />
  27. <SvgIcon v-show="!item.iconControl" class="title-icon" size="16" name="unselect-control" />
  28. <div class="title-text">{{ item.strinstallpos }}</div>
  29. <div class="title-detail" @click="handlerDetail(item.deviceID)">详情</div>
  30. </div>
  31. <div class="box-content">
  32. <!-- plc时钟显示 -->
  33. <div class="timePlcNow">{{ item.nowTime }}</div>
  34. <!-- 二三维信息 -->
  35. <gateSVG v-if="item.gateStyle == 'fmSp1' || item.gateStyle == 'fm_fc_ssl'"
  36. :ref="(el) => setChildRef(el, index)" :identify="index">
  37. </gateSVG>
  38. <gateDualSVG v-else :ref="(el) => setChildRef(el, index)" :identify="index">
  39. </gateDualSVG>
  40. </div>
  41. <img src="@/assets/images/camera.png" alt="" @click="handlerCamera(item, index)" />
  42. <div class="setting-time">
  43. <div>
  44. <span>定时开启时间:</span>
  45. <span class="set-time">{{ item.doorOpenTime }}</span>
  46. </div>
  47. <div>
  48. <span>启用状态:</span>
  49. <span class="set-time">{{ item.timerSwitch == '1' ? '启用' : '禁用' }}</span>
  50. </div>
  51. <div>
  52. <span>定时关闭时间:</span>
  53. <span class="set-time">{{ item.doorCloseTime }}</span>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. <!-- 同步开启/关闭弹窗 -->
  59. <syncModal :visible="visible" :tooltipText="tooltipText" @handleCancel="handleCancel" @handleOk="handleOk">
  60. </syncModal>
  61. <!-- 定时设置弹窗 -->
  62. <timeSetModal :visibleTime="visibleTime" @handleCancelTime="handleCancelTime" @handleOk="handleOkTime">
  63. </timeSetModal>
  64. <!--30s延时提示弹窗-->
  65. <tipModal></tipModal>
  66. <!-- 摄像头信息 -->
  67. <Modal :visible="modalVisible" :centered="true" :destroyOnClose="true" @cancel="handleCancelCamera">
  68. <CameraModal :deviceId="deviceId"></CameraModal>
  69. </Modal>
  70. <!-- 操作日志 -->
  71. <operationModal :visible="visibleOperation" @handleCancel="handleCancelOperation">
  72. </operationModal>
  73. <!-- 集控设备选择 -->
  74. <DeviceControl v-if="visibleDeviceControl" :deviceControlData="gateControlData" @confirmChoice="handlerChoice">
  75. </DeviceControl>
  76. <!-- 视屏墙详情 -->
  77. <Modal :title="cameraDetailTitle" :widthV="'1450px'" :footer="null" :visible="cameraDetailVisible" :centered="true"
  78. :destroyOnClose="true" @cancel="handleCancelCameraDetail">
  79. <CameraDetailModal :cameraData="cameraData"></CameraDetailModal>
  80. </Modal>
  81. </div>
  82. </template>
  83. <script setup lang="ts">
  84. import { reactive, ref, inject, watch, nextTick, onMounted } from 'vue';
  85. import syncModal from './syncModal.vue';
  86. import timeSetModal from './timeSetModal.vue';
  87. import CameraModal from './cameraModal.vue';
  88. import CameraDetailModal from './cameraDetailModal.vue'
  89. import Modal from './Modal.vue';
  90. import tipModal from './tipModal.vue'
  91. import gateDualSVG from './gateDualSVG.ssl.vue'
  92. import gateSVG from './gateSVG.ssl.vue'
  93. import operationModal from './operationModal.vue'
  94. import DeviceControl from './deviceControl.vue'
  95. import { useRouter } from 'vue-router';
  96. import { devicecontrol, insertSyncRule, GetSyncRule, controlList, confirmChoice, manualTimeSync, isPasswordCurrect, editDoor } from '../airdoor.api'
  97. import { doorStatus } from '../airdoor.data'
  98. // import { getModelComponent } from '../airdoor.data'
  99. import { useMessage } from '/@/hooks/web/useMessage';
  100. import { SvgIcon } from '/@/components/Icon';
  101. import { getDictItemsByCode } from '/@/utils/dict';
  102. let props = defineProps({
  103. infoData: {
  104. type: Array,
  105. default: () => {
  106. return [];
  107. },
  108. },
  109. });
  110. const { createMessage } = useMessage();
  111. const globalConfig = inject<any>('globalConfig');
  112. let router = useRouter();
  113. //判断当前开启的是同步/集控密码弹窗
  114. let isTbOrJk = ref('')
  115. let infoDatas = ref<any[]>([])
  116. //同步开启/关闭弹窗-控制显示与隐藏
  117. let visible = ref(false);
  118. let visibleStatus = ref('')
  119. //设置定时弹窗-控制显示与影藏
  120. let visibleTime = ref(false);
  121. let Ids = ref('')
  122. //摄像头-控制显示与隐藏
  123. let modalVisible = ref(false);
  124. let deviceId = ref('')
  125. //操作日志弹窗显示/关闭
  126. let visibleOperation = ref(false)
  127. const childRefs = ref<any[]>([])
  128. //集控风门列表
  129. let gateControlData = ref<any[]>([])
  130. //集控设备弹窗显示
  131. let visibleDeviceControl = ref(false)
  132. let tooltipText = ref('')
  133. //视屏墙详情
  134. let cameraDetailVisible = ref(false)
  135. let cameraDetailTitle = ref('视屏墙详情信息')
  136. let cameraData = ref<any[]>([])
  137. //风门集控类型-字典
  138. const dictCodes = getDictItemsByCode('gateCentralizedControl');
  139. //是否开启分组
  140. let isOpenFz = ref('')
  141. //分组选中
  142. let choiceFzData = ref<any[]>([])
  143. const setChildRef = (el, index) => {
  144. childRefs.value[index] = el
  145. }
  146. //同步开启/关闭--弹窗
  147. function handlerOpenOrClose(data) {
  148. visible.value = true;
  149. visibleStatus.value = data
  150. isTbOrJk.value = 'Tb'
  151. tooltipText.value = '您正在执行 “开启/关闭” 全部风门的操作,请输入密码执行。'
  152. }
  153. //确定
  154. async function handleOk(param) {
  155. if (isTbOrJk.value == 'Tb') {
  156. let deviceStr = isOpenFz ? choiceFzData.value.map(v => v.deviceID).join(',') : infoDatas.value.map(v => v.deviceID).join(',')
  157. let paramcode = visibleStatus.value == 'open' ? 'sameTimeOpen' : 'sameTimeClose'
  158. let res = await devicecontrol({ deviceids: deviceStr, paramcode: paramcode, password: param.pass || globalConfig?.simulatedPassword })
  159. if (res) {
  160. visible.value = param.visib
  161. // visibleStatus.value = ''
  162. doorStatus.openOrclose = true
  163. doorStatus.statusCode = visibleStatus.value
  164. setTimeout(() => {
  165. doorStatus.openOrclose = false
  166. doorStatus.statusCode = ''
  167. }, 60000 * 5)
  168. }
  169. } else {
  170. let res = await isPasswordCurrect({ password: param.pass })
  171. if (res === true) {
  172. visible.value = param.visib
  173. visibleDeviceControl.value = true
  174. } else {
  175. visible.value = param.visib
  176. }
  177. }
  178. }
  179. //取消
  180. function handleCancel(param) {
  181. visible.value = param;
  182. visibleStatus.value = ''
  183. isTbOrJk.value = ''
  184. tooltipText.value = ''
  185. }
  186. //定时设置
  187. async function handlerTimeSet() {
  188. visibleTime.value = true;
  189. let res = await GetSyncRule({})
  190. Ids.value = res[0]['id'] || ''
  191. console.log(res, '读取规则')
  192. }
  193. //确定
  194. async function handleOkTime(param) {
  195. let timerSwitch = param.formState.checked ? '1' : '0'
  196. let res = await insertSyncRule({ timerSwitch: timerSwitch, settimeOnHour: param.formState.hourS, settimeOnMin: param.formState.minuteS, settimeOffHour: param.formState.hourE, settimeOffMin: param.formState.minuteE, password: param.formState.passWord })
  197. if (res) {
  198. visibleTime.value = param.visib
  199. Ids.value = ''
  200. if (res.code == 500) {
  201. createMessage.error(res.message);
  202. } else {
  203. createMessage.success(res.message);
  204. }
  205. }
  206. }
  207. //取消
  208. function handleCancelTime(param) {
  209. visibleTime.value = param;
  210. }
  211. //详情跳转
  212. function handlerDetail(id) {
  213. router.push(`/monitorChannel/monitor-gate?id=${id}&deviceType=gate`);
  214. }
  215. //摄像头切换
  216. function handlerCamera(item, index) {
  217. modalVisible.value = true;
  218. deviceId.value = item.deviceID
  219. }
  220. //摄像头弹窗关闭
  221. function handleCancelCamera(param) {
  222. modalVisible.value = param;
  223. }
  224. //操作日志弹窗-打开
  225. function handlerOperation() {
  226. visibleOperation.value = true
  227. }
  228. //操作日志弹窗-关闭
  229. function handleCancelOperation(param) {
  230. visibleOperation.value = param
  231. }
  232. //模型动画
  233. function monitorAnimation(selectData, index) {
  234. childRefs.value[index]?.animate?.(selectData.frontGateOpen == '1', selectData.midGateOpen == '1', selectData.rearGateOpen == '1');
  235. }
  236. //获取集控风门列表
  237. async function getControlList() {
  238. let res = await controlList({ devicekind: 'gate', pageNo: 1, pageSize: 100 })
  239. gateControlData.value = res.records || []
  240. }
  241. //集控设备选择点击
  242. function handlerDeviceChoice() {
  243. isTbOrJk.value = 'Jk'
  244. visible.value = true;
  245. tooltipText.value = '您正在执行 “集控” 全部风门的操作,请输入密码执行。'
  246. }
  247. //集控设备确定选择
  248. async function handlerChoice(param) {
  249. let data: any[] = []
  250. param.forEach(el => {
  251. let list = gateControlData.value.find(v => v.id == el)
  252. list.isAutosync = '1'
  253. data.push(list)
  254. })
  255. let res = await confirmChoice({ obj: data })
  256. if (res) {
  257. visibleDeviceControl.value = false
  258. }
  259. }
  260. //同步PLC时钟
  261. async function handlerClock() {
  262. let res = await manualTimeSync()
  263. if (res) {
  264. createMessage.success('PLC时钟同步成功!');
  265. }
  266. }
  267. //视屏详情-点击
  268. function handlerCameraDetail() {
  269. cameraData.value.length = 0
  270. infoDatas.value.forEach(el => {
  271. if (el.cameras.length) {
  272. cameraData.value.push(...el.cameras)
  273. }
  274. })
  275. cameraDetailVisible.value = true
  276. }
  277. //视屏墙详情关闭
  278. function handleCancelCameraDetail(param) {
  279. cameraDetailVisible.value = param
  280. }
  281. //设备集控-分组控制
  282. function handlerFz(item) {
  283. isOpenFz.value = item.value
  284. if (item.value == '0') {
  285. infoDatas.value.forEach(el => {
  286. el.iconControl = true
  287. })
  288. choiceFzData.value = [...infoDatas.value]
  289. } else {
  290. infoDatas.value.forEach(el => {
  291. if (el.gateCentralizedControl == item.value) {
  292. el.iconControl = true
  293. } else {
  294. el.iconControl = false
  295. }
  296. })
  297. choiceFzData.value = infoDatas.value.filter(v => v.gateCentralizedControl == item.value)
  298. }
  299. }
  300. //分组中添加或删除元素
  301. async function handlerAddorDel(item) {
  302. if (isOpenFz.value) {
  303. item.iconControl = !item.iconControl
  304. if (item.iconControl) {
  305. choiceFzData.value.push(item)
  306. } else {
  307. choiceFzData.value.pop()
  308. }
  309. // // let res = await editDoor({ gateCentralizedControl: isOpenFz.value, id: item.deviceID })
  310. console.log(choiceFzData.value, '开启分组并且当前点击项已有分组')
  311. } else {
  312. isOpenFz.value = ''
  313. }
  314. }
  315. watch(() => props.infoData, (newV, oldV) => {
  316. infoDatas.value = newV
  317. isOpenFz.value = ''
  318. if (infoDatas.value.length) {
  319. infoDatas.value.forEach((el: any, index: number) => {
  320. el = Object.assign(el, el.readData)
  321. el.iconControl = false
  322. el.nowTime = el.PLCyear ? `20${el.PLCyear}-${el.PLCmonth}-${el.PLCday} ${el.PLChour}:${el.PLCminute}:${el.PLCsecond}` : ''
  323. el.doorOpenTime = el.time_on_hour ? `${el.time_on_hour.length != 1 ? el.time_on_hour : 0 + el.time_on_hour}:${el.time_on_min.length != 1 ? el.time_on_min : 0 + el.time_on_min}` : '--'
  324. el.doorCloseTime = el.time_off_hour ? `${el.time_off_hour.length != 1 ? el.time_off_hour : 0 + el.time_off_hour}:${el.time_off_hour.length != 1 ? el.time_off_hour : 0 + el.time_off_hour}` : '--'
  325. monitorAnimation(el, index);
  326. })
  327. }
  328. })
  329. onMounted(() => {
  330. getControlList()
  331. })
  332. </script>
  333. <style lang="less" scoped>
  334. @import '/@/design/theme.less';
  335. @{theme-deepblue} {
  336. .door-content-r {
  337. --image-camera_bg: url('/@/assets/images/themify/deepblue/vent/camera_bg.png');
  338. --image-btn: url(/@/assets/images/themify/deepblue/files/details/btn.png);
  339. }
  340. }
  341. .door-content-r {
  342. --image-camera_bg: url('/@/assets/images/vent/camera_bg.png');
  343. --image-btn: url(/@/assets/images/files/details/btn.png);
  344. width: 100%;
  345. height: 100%;
  346. .icon-style {
  347. margin-right: 5px;
  348. }
  349. .content-r-btn {
  350. width: 100%;
  351. height: 40px;
  352. padding: 0px 10px;
  353. display: flex;
  354. // align-items: center;
  355. .device-control-btn {
  356. position: absolute;
  357. right: 35px;
  358. top: 30px;
  359. }
  360. }
  361. .content-r-container {
  362. width: 100%;
  363. height: calc(100% - 40px);
  364. display: flex;
  365. justify-content: flex-start;
  366. flex-wrap: wrap;
  367. .content-r-box {
  368. position: relative;
  369. width: 376px;
  370. height: 270px;
  371. margin: 10px 5px;
  372. background: var(--image-camera_bg);
  373. background-size: 100% 100%;
  374. .box-title {
  375. position: absolute;
  376. left: 50%;
  377. top: 12px;
  378. transform: translate(-50%, 0);
  379. width: 95%;
  380. height: 28px;
  381. line-height: 28px;
  382. text-align: center;
  383. color: #fff;
  384. background-color: rgba(51, 211, 255, 0.2);
  385. }
  386. .title-icon {
  387. position: absolute;
  388. left: 10px;
  389. top: 7px;
  390. }
  391. .title-detail {
  392. position: absolute;
  393. right: 12px;
  394. top: 0px;
  395. color: rgba(60, 242, 255);
  396. font-size: 12px;
  397. cursor: pointer;
  398. }
  399. .box-content {
  400. position: absolute;
  401. left: 50%;
  402. top: 40px;
  403. transform: translate(-50%, 0);
  404. width: 95%;
  405. height: calc(100% - 40px);
  406. }
  407. .timePlcNow {
  408. position: absolute;
  409. right: 5px;
  410. top: 0px;
  411. color: #fff;
  412. font-size: 12px;
  413. }
  414. .setting-time {
  415. width: 100%;
  416. position: absolute;
  417. bottom: -25px;
  418. left: 0;
  419. display: flex;
  420. justify-content: space-around;
  421. color: #fff;
  422. font-size: 12px;
  423. padding: 0px 25px;
  424. }
  425. .set-time {
  426. color: rgba(60, 242, 255);
  427. margin: 0px 5px;
  428. }
  429. img {
  430. position: absolute;
  431. right: 20px;
  432. bottom: 15px;
  433. width: 20px;
  434. height: 20px;
  435. cursor: pointer;
  436. }
  437. }
  438. }
  439. .btn-control {
  440. margin: 0px 10px;
  441. }
  442. }
  443. ::v-deep .zxm-btn-primary {
  444. background-color: transparent;
  445. border: none;
  446. background: var(--image-btn) no-repeat !important;
  447. background-size: 100% 100% !important;
  448. }
  449. </style>