Kaynağa Gözat

Merge branch 'dev-2.19.0' of http://101.36.160.140:21044/province-vue-qh/province-vue-all into dev

chenghanbin 5 ay önce
ebeveyn
işleme
cc121c6a56

+ 4 - 4
src/components/CommonSelector/data.js

@@ -216,8 +216,8 @@ export const PDJG = [
216 216
 ]
217 217
 
218 218
 export const windowCount = [
219
-	{ label: '1x1', value: '1' },
220
-	{ label: '2x2', value: '2' },
221
-	{ label: '3x3', value: '3' },
222
-	{ label: '4x4', value: '4' },
219
+	{ label: '1x1', value: 1 },
220
+	{ label: '2x2', value: 2 },
221
+	{ label: '3x3', value: 3 },
222
+	{ label: '4x4', value: 4 }
223 223
 ]

+ 355 - 128
src/components/video/Live.vue

@@ -1,100 +1,319 @@
1 1
 <!-- 实时视频监控 -->
2 2
 <script setup>
3
-import {getPreview} from "@/api/previewPlayback";
4
-import { useRoute } from 'vue-router';
5
-import commonSelect from '@/components/CommonSelector/index.vue'
6
-const activeKey = ref('1')
7
-const windowCount = ref('1')
8
-const route = useRoute();
9
-const orgId = route.query.orgId
10
-console.log('orgId', orgId)
11
-console.log('player', window.JSPlugin)
12
-const player = ref(null)
13
-const IS_MOVE_DEVICE = false
14
-const isMoveDevice = ref(IS_MOVE_DEVICE)
15
-const splitNum = ref(IS_MOVE_DEVICE ? 1 : 2)
16
-const init = () => {
17
-	window.addEventListener('resize', () => {
18
-		if(player.vlaue)
19
-			player.value.JS_Resize()
20
-	})
21
-}
22
-const createPlayer = () => {
23
-	player.value = new window.JSPlugin({
24
-		szId: 'player',
25
-		szBasePath: "./",
26
-		iMaxSplit: 4,
27
-		iCurrentSplit: parseInt(windowCount.value),
28
-		openDebug: true,
29
-		oStyle: {
30
-			borderSelect: IS_MOVE_DEVICE ? '#000' : '#FFCC00',
3
+	import { getPreview } from '@/api/previewPlayback'
4
+	import { useRoute } from 'vue-router'
5
+	import commonSelect from '@/components/CommonSelector/index.vue'
6
+	import api from '@/api/orgInfo/info'
7
+	import cameraApi from '@/api/camera/index'
8
+	import { message } from 'ant-design-vue'
9
+
10
+	const activeKey = ref('1')
11
+	const route = useRoute()
12
+	const orgId = route.query.orgId
13
+	console.log('orgId', orgId)
14
+	console.log('player', window.JSPlugin)
15
+	const player = ref(null)
16
+	const IS_MOVE_DEVICE = false
17
+	const isMoveDevice = ref(IS_MOVE_DEVICE)
18
+	const splitNum = ref(1)
19
+	const orgTreeData = ref([])
20
+	const cameraListData = ref([])
21
+	let videoMap = {}
22
+	let currentWindowIndex = 0
23
+	const mode = 0 // 0 普通模式  1 高级模式
24
+
25
+	const init = () => {
26
+		window.addEventListener('resize', () => {
27
+			if (player.vlaue) player.value.JS_Resize()
28
+		})
29
+	}
30
+
31
+	const getOrgData = () => {
32
+		orgTreeData.value = []
33
+		api.getAllList({}).then((resp) => {
34
+			const list = resp || []
35
+
36
+			// list[0].parentId = 12
37
+
38
+			const temp = {}
39
+			const leaf = []
40
+			list.forEach((d) => {
41
+				d.children = []
42
+				d.title = d.orgName
43
+				d.key = d.orgId
44
+				temp[d.orgId] = d
45
+			})
46
+			list.forEach((d) => {
47
+				const pid = d.parentId
48
+				if (temp[pid]) {
49
+					temp[pid].children.push(d)
50
+					leaf.push(d.orgId)
51
+				}
52
+			})
53
+			// orgTreeData.value = list.filter((d) => !leaf.includes(d.orgId))
54
+			orgTreeData.value = list
55
+			// console.log('ttttt', list, orgTreeData.value)
56
+		})
57
+	}
58
+
59
+	const createPlayer = () => {
60
+		player.value = new window.JSPlugin({
61
+			szId: 'player',
62
+			szBasePath: './',
63
+			iMaxSplit: 4,
64
+			iCurrentSplit: parseInt(splitNum.value),
65
+			openDebug: true,
66
+			oStyle: {
67
+				borderSelect: IS_MOVE_DEVICE ? '#000' : '#FFCC00'
68
+			}
69
+		})
70
+		player.value.JS_SetWindowControlCallback({
71
+			windowEventSelect: function (iWndIndex) {
72
+				//插件选中窗口回调
73
+				console.log('windowSelect callback: ', iWndIndex)
74
+				currentWindowIndex = iWndIndex
75
+			},
76
+			pluginErrorHandler: function (iWndIndex, iErrorCode, oError) {
77
+				//插件错误回调
78
+				console.log('pluginError callback: ', iWndIndex, iErrorCode, oError)
79
+			},
80
+			windowEventOver: function (iWndIndex) {
81
+				//鼠标移过回调
82
+				//console.log(iWndIndex);
83
+			},
84
+			windowEventOut: function (iWndIndex) {
85
+				//鼠标移出回调
86
+				//console.log(iWndIndex);
87
+			},
88
+			windowEventUp: function (iWndIndex) {
89
+				//鼠标mouseup事件回调
90
+				//console.log(iWndIndex);
91
+			},
92
+			windowFullCcreenChange: function (bFull) {
93
+				//全屏切换回调
94
+				console.log('fullScreen callback: ', bFull)
95
+			},
96
+			firstFrameDisplay: function (iWndIndex, iWidth, iHeight) {
97
+				//首帧显示回调
98
+				console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight)
99
+			},
100
+			performanceLack: function () {
101
+				//性能不足回调
102
+				console.log('performanceLack callback: ')
103
+			}
104
+		})
105
+	}
106
+
107
+	const arrangeWindow = () => {
108
+		let num = parseInt(splitNum.value)
109
+		player.value.JS_ArrangeWindow(num).then(
110
+			() => {
111
+				console.log(`arrangeWindow to ${num}x${num} success`)
112
+			},
113
+			(e) => {
114
+				console.error(e)
115
+			}
116
+		)
117
+	}
118
+
119
+	const wholeFullScreen = () => {
120
+		player.value.JS_FullScreenDisplay(true).then(
121
+			() => {
122
+				console.log(`wholeFullScreen success`)
123
+			},
124
+			(e) => {
125
+				console.error(e)
126
+			}
127
+		)
128
+	}
129
+
130
+	const play = (index, url) => {
131
+		return new Promise((resolve, reject) => {
132
+			player.value.JS_Play(url, { playURL: url, mode }, index).then(
133
+				() => {
134
+					console.log('realplay success')
135
+					resolve()
136
+				},
137
+				(e) => {
138
+					console.error(e)
139
+					reject(e)
140
+				}
141
+			)
142
+		})
143
+	}
144
+
145
+	const stopPlay = () => {
146
+		if (videoMap[currentWindowIndex]) {
147
+			const data = videoMap[currentWindowIndex]
148
+			if (data.taskID) {
149
+				return message.warning('该窗口有正在录制的视频,请先结束录制')
150
+			}
31 151
 		}
32
-	})
33
-	player.value.JS_SetWindowControlCallback({
34
-		windowEventSelect: function (iWndIndex) {  //插件选中窗口回调
35
-			console.log('windowSelect callback: ', iWndIndex);
36
-		},
37
-		pluginErrorHandler: function (iWndIndex, iErrorCode, oError) {  //插件错误回调
38
-			console.log('pluginError callback: ', iWndIndex, iErrorCode, oError);
39
-		},
40
-		windowEventOver: function (iWndIndex) {  //鼠标移过回调
41
-			//console.log(iWndIndex);
42
-		},
43
-		windowEventOut: function (iWndIndex) {  //鼠标移出回调
44
-			//console.log(iWndIndex);
45
-		},
46
-		windowEventUp: function (iWndIndex) {  //鼠标mouseup事件回调
47
-			//console.log(iWndIndex);
48
-		},
49
-		windowFullCcreenChange: function (bFull) {  //全屏切换回调
50
-			console.log('fullScreen callback: ', bFull);
51
-		},
52
-		firstFrameDisplay: function (iWndIndex, iWidth, iHeight) {  //首帧显示回调
53
-			console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);
54
-		},
55
-		performanceLack: function () {  //性能不足回调
56
-			console.log('performanceLack callback: ');
152
+		player.value.JS_Stop().then(
153
+			() => {
154
+				console.log('stop realplay success')
155
+				if (videoMap[currentWindowIndex]) {
156
+					delete videoMap[currentWindowIndex]
157
+				}
158
+			},
159
+			(e) => {
160
+				console.error(e)
161
+			}
162
+		)
163
+	}
164
+
165
+	const stopAllPlay = () => {
166
+		for (const i of Object.keys(videoMap)) {
167
+			const data = videoMap[i]
168
+			if (data.taskID) {
169
+				return message.warning('该窗口有正在录制的视频,请先结束录制')
170
+			}
171
+		}
172
+		player.value.JS_StopRealPlayAll().then(
173
+			() => {
174
+				console.log('stopAllPlay success')
175
+				videoMap = {}
176
+			},
177
+			(e) => {
178
+				console.error(e)
179
+			}
180
+		)
181
+	}
182
+
183
+	const doControl = (command, action = 0, speed = 50, presetIndex = 10) => {
184
+		if (videoMap[currentWindowIndex]) {
185
+			const data = videoMap[currentWindowIndex]
186
+			const cmd = {
187
+				action,
188
+				command,
189
+				speed,
190
+				presetIndex,
191
+				cameraIndexCode: data.cameraIndexCode
192
+			}
193
+			controlling(cmd)
194
+		} else {
195
+			return message.warning('请选择播放中的窗口')
57 196
 		}
58
-	});
59
-}
60
-
61
-const arrangeWindow = () => {
62
-	let num = splitNum.value
63
-	player.value.JS_ArrangeWindow(num).then(
64
-		() => { console.log(`arrangeWindow to ${num}x${num} success`) },
65
-		e => { console.error(e) }
66
-	)
67
-}
68
-
69
-const wholeFullScreen = () => {
70
-	player.value.JS_FullScreenDisplay(true).then(
71
-		() => { console.log(`wholeFullScreen success`) },
72
-		e => { console.error(e) }
73
-	)
74
-}
75
-
76
-onMounted(() => {
77
-	init()
78
-	createPlayer()
79
-	getPreview({cameraIndexCode: '0'})
80
-})
197
+	}
198
+
199
+	const startTrack = () => {
200
+		doControl('START_TRACK', 0)
201
+	}
202
+
203
+	const stopTrack = () => {
204
+		doControl('STOP_TRACK', 1)
205
+	}
206
+
207
+	const orgSelect = (orgId, event) => {
208
+		const org = event.node
209
+		cameraListData.value = []
210
+		cameraApi.getNVRVideo({ orgId: org.orgId }).then((resp) => {
211
+			console.log('摄像头列表', resp)
212
+			const list = resp || []
213
+			const tree = [
214
+				{
215
+					root: true,
216
+					title: '仓内',
217
+					key: 'root1',
218
+					children: []
219
+				},
220
+				{
221
+					root: true,
222
+					title: '业务',
223
+					key: 'root2',
224
+					children: []
225
+				},
226
+				{
227
+					root: true,
228
+					title: '安防',
229
+					key: 'root3',
230
+					children: []
231
+				}
232
+			]
233
+			list.forEach((d) => {
234
+				const type = d.cameraType
235
+				const temp = {
236
+					title: d.cameraName,
237
+					key: d.cameraId,
238
+					...d
239
+				}
240
+				if (type === '1') {
241
+					tree[0].children.push(temp)
242
+				} else if (type === '2') {
243
+					tree[1].children.push(temp)
244
+				} else if (type === '3') {
245
+					{
246
+						tree[2].children.push(temp)
247
+					}
248
+				}
249
+			})
250
+			cameraListData.value = tree
251
+		})
252
+	}
253
+
254
+	const cameraSelect = (cameraId, event) => {
255
+		const camera = event.node
256
+		if (camera.root) return
257
+		console.log('选择摄像头', camera)
258
+		const { cameraIndexCode } = camera
259
+		getPreview({ cameraIndexCode, protocol: 'WS' }).then((resp) => {
260
+			if (!resp || !resp.url) return message.error('无法获取视频地址')
261
+
262
+			const exists = Object.values(videoMap).findIndex((u) => u.url === url)
263
+			if (exists >= 0) {
264
+				return message.warning(`该视频已经在 ${exists + 1} 窗口播放`)
265
+			}
266
+			play(currentWindowIndex, url)
267
+				.then((_) => {
268
+					videoMap[currentWindowIndex] = {
269
+						url,
270
+						cameraIndexCode: n.cameraIndexCode,
271
+						cameraId
272
+					}
273
+				})
274
+				.catch((err) => {
275
+					console.error('play error', err)
276
+					message.error('播放失败')
277
+				})
278
+		})
279
+	}
280
+
281
+	onMounted(() => {
282
+		getOrgData()
283
+		init()
284
+		createPlayer()
285
+		getPreview({ cameraIndexCode: '0' })
286
+	})
81 287
 </script>
82 288
 
83 289
 <template>
84 290
 	<div class="flex mt-[5px]">
85
-		<div class="tree w-[20%] mr-4">树</div>
291
+		<div class="tree w-[20%] mr-4">
292
+			<a-tree :tree-data="orgTreeData" @select="orgSelect">
293
+				<template #title="{ title, key }">
294
+					<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
295
+					<template v-else>{{ title }}</template>
296
+				</template>
297
+			</a-tree>
298
+		</div>
86 299
 		<div class="player mr-4">
87
-			<div class="w-full h-[25px] bg-black text-white pl-5">
88
-				播放通道
89
-			</div>
300
+			<div class="w-full h-[25px] bg-black text-white pl-5">播放通道</div>
90 301
 			<div id="player"></div>
91 302
 		</div>
92 303
 		<div class="control w-[20%] h-full">
93 304
 			<a-tabs v-model:activeKey="activeKey">
94
-				<a-tab-pane key="1" tab="摄像头列表"></a-tab-pane>
305
+				<a-tab-pane key="1" tab="摄像头列表">
306
+					<a-tree :tree-data="cameraListData" @select="cameraSelect" class="w-full">
307
+						<template #title="{ title, key }">
308
+							<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
309
+							<template v-else>{{ title }}</template>
310
+						</template>
311
+					</a-tree>
312
+				</a-tab-pane>
95 313
 				<a-tab-pane key="2" tab="操作" force-render>
96 314
 					<div class="row">
97
-						<span class="w-[30%]">窗口数量:</span> <common-select v-model:value="windowCount" type="windowCount" class="w-[70%]"/>
315
+						<span class="w-[30%]">窗口数量:</span>
316
+						<common-select v-model:value="splitNum" type="windowCount" class="w-[70%]" @on-change="arrangeWindow" />
98 317
 					</div>
99 318
 					<div class="row">
100 319
 						<a-button type="primary" class="mr-5 btn">轮巡</a-button>
@@ -102,27 +321,39 @@ onMounted(() => {
102 321
 					</div>
103 322
 					<div class="row">
104 323
 						<a-button type="primary" class="mr-5 btn">窗口抓图</a-button>
105
-						<a-button type="primary" class="btn">窗口关闭</a-button>
324
+						<a-button type="primary" class="btn" @click="stopPlay">窗口关闭</a-button>
106 325
 					</div>
107 326
 					<div class="row">
108 327
 						<a-button type="primary" class="mr-5 btn">全部抓图</a-button>
109
-						<a-button type="primary" class="btn">全部关闭</a-button>
328
+						<a-button type="primary" class="btn" @click="stopAllPlay">全部关闭</a-button>
110 329
 					</div>
111 330
 					<div v-if="hasPerm(['controlCloud'])" class="flex flex-col">
112 331
 						<div>云控制台</div>
113 332
 						<div>
114 333
 							<template
115 334
 								v-for="list in [
116
-									[{label: '↖', code: 'LEFT_UP'}, {label: '↑', code: 'UP'}, {label: '↗', code: 'RIGHT_UP'}],
117
-									[{label: '←', code: 'LEFT'}, {label: 'center', code: 'GOTO_PRESET'}, {label: '→', code: 'RIGHT'}],
118
-									[{label: '↙', code: 'LEFT_DOWN'}, {label: '↓', code: 'DOWN'}, {label: '↘', code: 'RIGHT_DOWN'}]]" >
335
+									[
336
+										{ label: '↖', code: 'LEFT_UP' },
337
+										{ label: '↑', code: 'UP' },
338
+										{ label: '↗', code: 'RIGHT_UP' }
339
+									],
340
+									[
341
+										{ label: '←', code: 'LEFT' },
342
+										{ label: 'center', code: 'GOTO_PRESET' },
343
+										{ label: '→', code: 'RIGHT' }
344
+									],
345
+									[
346
+										{ label: '↙', code: 'LEFT_DOWN' },
347
+										{ label: '↓', code: 'DOWN' },
348
+										{ label: '↘', code: 'RIGHT_DOWN' }
349
+									]
350
+								]"
351
+							>
119 352
 								<div class="control-row">
120 353
 									<template v-for="item in list">
121
-										<a-button
122
-											v-if="item.code !== 'GOTO_PRESET'"
123
-											:key="item.code"
124
-											class="small-btn"
125
-										>{{ item.label }}</a-button>
354
+										<a-button v-if="item.code !== 'GOTO_PRESET'" :key="item.code" class="small-btn"
355
+											>{{ item.label }}
356
+										</a-button>
126 357
 										<a-button v-else class="small-btn">
127 358
 											<template #icon>
128 359
 												<UndoOutlined />
@@ -134,21 +365,15 @@ onMounted(() => {
134 365
 						</div>
135 366
 					</div>
136 367
 					<div class="row">
137
-						<a-button type="primary" class="mr-5 btn">
138
-							+ 聚焦
139
-						</a-button>
368
+						<a-button type="primary" class="mr-5 btn"> + 聚焦 </a-button>
140 369
 						<a-button type="primary" class="btn">- 聚焦</a-button>
141 370
 					</div>
142 371
 					<div class="row">
143
-						<a-button type="primary" class="mr-5 btn">
144
-							+ 调焦
145
-						</a-button>
372
+						<a-button type="primary" class="mr-5 btn"> + 调焦 </a-button>
146 373
 						<a-button type="primary" class="btn">- 调焦</a-button>
147 374
 					</div>
148 375
 					<div class="row">
149
-						<a-button type="primary" class="mr-5 btn">
150
-							录像开始
151
-						</a-button>
376
+						<a-button type="primary" class="mr-5 btn"> 录像开始 </a-button>
152 377
 						<a-button type="primary" class="btn">录像结束</a-button>
153 378
 					</div>
154 379
 				</a-tab-pane>
@@ -158,31 +383,33 @@ onMounted(() => {
158 383
 </template>
159 384
 
160 385
 <style scoped lang="less">
161
-.player {
162
-	#player {
163
-		width: 55vw;
164
-		height: calc((55vw) * 5 / 8);
165
-	}
166
-}
167
-
168
-.row {
169
-	margin-bottom: 10px;
170
-	display: flex;
171
-	justify-content: center;
172
-	align-items: center;
173
-	.btn {
174
-		width: 120px;
175
-		margin-top: 5px;
176
-	}
177
-}
178
-.control-row {
179
-	display: flex;
180
-	justify-content: center;
181
-	align-items: center;
182
-	.small-btn {
183
-		width: 80px;
184
-		margin-top: 5px;
185
-	}
186
-}
187
-</style>
386
+	.player {
387
+		#player {
388
+			width: 55vw;
389
+			height: calc((55vw) * 5 / 8);
390
+		}
391
+	}
392
+
393
+	.row {
394
+		margin-bottom: 10px;
395
+		display: flex;
396
+		justify-content: center;
397
+		align-items: center;
398
+
399
+		.btn {
400
+			width: 120px;
401
+			margin-top: 5px;
402
+		}
403
+	}
404
+
405
+	.control-row {
406
+		display: flex;
407
+		justify-content: center;
408
+		align-items: center;
188 409
 
410
+		.small-btn {
411
+			width: 80px;
412
+			margin-top: 5px;
413
+		}
414
+	}
415
+</style>

+ 215 - 103
src/components/video/Replay.vue

@@ -1,100 +1,212 @@
1 1
 <script setup>
2
-import {getPreview} from "@/api/previewPlayback";
3
-import { useRoute } from 'vue-router';
4
-import commonSelect from '@/components/CommonSelector/index.vue'
5
-const activeKey = ref('1')
6
-const windowCount = ref('1')
7
-const route = useRoute();
8
-const orgId = route.query.orgId
9
-console.log('orgId', orgId)
10
-console.log('player', window.JSPlugin)
11
-const player = ref(null)
12
-const IS_MOVE_DEVICE = false
13
-const isMoveDevice = ref(IS_MOVE_DEVICE)
14
-const splitNum = ref(IS_MOVE_DEVICE ? 1 : 2)
15
-const init = () => {
16
-	window.addEventListener('resize', () => {
17
-		if(player.vlaue)
18
-			player.value.JS_Resize()
19
-	})
20
-}
21
-const createPlayer = () => {
22
-	player.value = new window.JSPlugin({
23
-		szId: 'player',
24
-		szBasePath: "./",
25
-		iMaxSplit: 4,
26
-		iCurrentSplit: parseInt(windowCount.value),
27
-		openDebug: true,
28
-		oStyle: {
29
-			borderSelect: IS_MOVE_DEVICE ? '#000' : '#FFCC00',
30
-		}
31
-	})
32
-	player.value.JS_SetWindowControlCallback({
33
-		windowEventSelect: function (iWndIndex) {  //插件选中窗口回调
34
-			console.log('windowSelect callback: ', iWndIndex);
35
-		},
36
-		pluginErrorHandler: function (iWndIndex, iErrorCode, oError) {  //插件错误回调
37
-			console.log('pluginError callback: ', iWndIndex, iErrorCode, oError);
38
-		},
39
-		windowEventOver: function (iWndIndex) {  //鼠标移过回调
40
-			//console.log(iWndIndex);
41
-		},
42
-		windowEventOut: function (iWndIndex) {  //鼠标移出回调
43
-			//console.log(iWndIndex);
44
-		},
45
-		windowEventUp: function (iWndIndex) {  //鼠标mouseup事件回调
46
-			//console.log(iWndIndex);
47
-		},
48
-		windowFullCcreenChange: function (bFull) {  //全屏切换回调
49
-			console.log('fullScreen callback: ', bFull);
50
-		},
51
-		firstFrameDisplay: function (iWndIndex, iWidth, iHeight) {  //首帧显示回调
52
-			console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);
53
-		},
54
-		performanceLack: function () {  //性能不足回调
55
-			console.log('performanceLack callback: ');
56
-		}
57
-	});
58
-}
2
+	import { getPreview } from '@/api/previewPlayback'
3
+	import { useRoute } from 'vue-router'
4
+	import commonSelect from '@/components/CommonSelector/index.vue'
5
+	import api from '@/api/orgInfo/info'
6
+	import cameraApi from '@/api/camera/index'
7
+	import { message } from 'ant-design-vue'
8
+
9
+	const activeKey = ref('1')
10
+	const route = useRoute()
11
+	const orgId = route.query.orgId
12
+	console.log('orgId', orgId)
13
+	console.log('player', window.JSPlugin)
14
+	const player = ref(null)
15
+	const IS_MOVE_DEVICE = false
16
+	const isMoveDevice = ref(IS_MOVE_DEVICE)
17
+	const splitNum = ref(1)
18
+	const orgTreeData = ref([])
19
+	const cameraListData = ref([])
20
+	let videoMap = {}
21
+	let currentWindowIndex = 0
22
+	const mode = 0 // 0 普通模式  1 高级模式
23
+
24
+	const init = () => {
25
+		window.addEventListener('resize', () => {
26
+			if (player.vlaue) player.value.JS_Resize()
27
+		})
28
+	}
29
+
30
+	const getOrgData = () => {
31
+		orgTreeData.value = []
32
+		api.getAllList({}).then((resp) => {
33
+			const list = resp || []
34
+
35
+			// list[0].parentId = 12
36
+
37
+			const temp = {}
38
+			const leaf = []
39
+			list.forEach((d) => {
40
+				d.children = []
41
+				d.title = d.orgName
42
+				d.key = d.orgId
43
+				temp[d.orgId] = d
44
+			})
45
+			list.forEach((d) => {
46
+				const pid = d.parentId
47
+				if (temp[pid]) {
48
+					temp[pid].children.push(d)
49
+					leaf.push(d.orgId)
50
+				}
51
+			})
52
+			// orgTreeData.value = list.filter((d) => !leaf.includes(d.orgId))
53
+			orgTreeData.value = list
54
+		})
55
+	}
56
+
57
+	const createPlayer = () => {
58
+		player.value = new window.JSPlugin({
59
+			szId: 'player',
60
+			szBasePath: './',
61
+			iMaxSplit: 4,
62
+			iCurrentSplit: parseInt(splitNum.value),
63
+			openDebug: true,
64
+			oStyle: {
65
+				borderSelect: IS_MOVE_DEVICE ? '#000' : '#FFCC00'
66
+			}
67
+		})
68
+		player.value.JS_SetWindowControlCallback({
69
+			windowEventSelect: function (iWndIndex) {
70
+				//插件选中窗口回调
71
+				console.log('windowSelect callback: ', iWndIndex)
72
+			},
73
+			pluginErrorHandler: function (iWndIndex, iErrorCode, oError) {
74
+				//插件错误回调
75
+				console.log('pluginError callback: ', iWndIndex, iErrorCode, oError)
76
+			},
77
+			windowEventOver: function (iWndIndex) {
78
+				//鼠标移过回调
79
+				//console.log(iWndIndex);
80
+			},
81
+			windowEventOut: function (iWndIndex) {
82
+				//鼠标移出回调
83
+				//console.log(iWndIndex);
84
+			},
85
+			windowEventUp: function (iWndIndex) {
86
+				//鼠标mouseup事件回调
87
+				//console.log(iWndIndex);
88
+			},
89
+			windowFullCcreenChange: function (bFull) {
90
+				//全屏切换回调
91
+				console.log('fullScreen callback: ', bFull)
92
+			},
93
+			firstFrameDisplay: function (iWndIndex, iWidth, iHeight) {
94
+				//首帧显示回调
95
+				console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight)
96
+			},
97
+			performanceLack: function () {
98
+				//性能不足回调
99
+				console.log('performanceLack callback: ')
100
+			}
101
+		})
102
+	}
103
+
104
+	const arrangeWindow = () => {
105
+		let num = splitNum.value
106
+		player.value.JS_ArrangeWindow(num).then(
107
+			() => {
108
+				console.log(`arrangeWindow to ${num}x${num} success`)
109
+			},
110
+			(e) => {
111
+				console.error(e)
112
+			}
113
+		)
114
+	}
59 115
 
60
-const arrangeWindow = () => {
61
-	let num = splitNum.value
62
-	player.value.JS_ArrangeWindow(num).then(
63
-		() => { console.log(`arrangeWindow to ${num}x${num} success`) },
64
-		e => { console.error(e) }
65
-	)
66
-}
116
+	const wholeFullScreen = () => {
117
+		player.value.JS_FullScreenDisplay(true).then(
118
+			() => {
119
+				console.log(`wholeFullScreen success`)
120
+			},
121
+			(e) => {
122
+				console.error(e)
123
+			}
124
+		)
125
+	}
67 126
 
68
-const wholeFullScreen = () => {
69
-	player.value.JS_FullScreenDisplay(true).then(
70
-		() => { console.log(`wholeFullScreen success`) },
71
-		e => { console.error(e) }
72
-	)
73
-}
127
+	const orgSelect = (orgId, event) => {
128
+		const org = event.node
129
+		cameraListData.value = []
130
+		cameraApi.getNVRVideo({ orgId: org.orgId }).then((resp) => {
131
+			console.log('摄像头列表', resp)
132
+			const list = resp || []
133
+			const tree = [
134
+				{
135
+					root: true,
136
+					title: '仓内',
137
+					key: 'root1',
138
+					children: []
139
+				},
140
+				{
141
+					root: true,
142
+					title: '业务',
143
+					key: 'root2',
144
+					children: []
145
+				},
146
+				{
147
+					root: true,
148
+					title: '安防',
149
+					key: 'root3',
150
+					children: []
151
+				}
152
+			]
153
+			list.forEach((d) => {
154
+				const type = d.cameraType
155
+				const temp = {
156
+					title: d.cameraName,
157
+					key: d.cameraId,
158
+					...d
159
+				}
160
+				if (type === '1') {
161
+					tree[0].children.push(temp)
162
+				} else if (type === '2') {
163
+					tree[1].children.push(temp)
164
+				} else if (type === '3') {
165
+					{
166
+						tree[2].children.push(temp)
167
+					}
168
+				}
169
+			})
170
+			cameraListData.value = tree
171
+		})
172
+	}
74 173
 
75
-onMounted(() => {
76
-	init()
77
-	createPlayer()
78
-	getPreview({cameraIndexCode: '0'})
79
-})
174
+	onMounted(() => {
175
+		getOrgData()
176
+		init()
177
+		createPlayer()
178
+		getPreview({ cameraIndexCode: '0' })
179
+	})
80 180
 </script>
81 181
 
82 182
 <template>
83 183
 	<div class="flex mt-[5px]">
84
-		<div class="tree w-[20%] mr-4">树</div>
184
+		<div class="tree w-[20%] mr-4">
185
+			<a-tree :tree-data="orgTreeData" @select="orgSelect">
186
+				<template #title="{ title, key }">
187
+					<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
188
+					<template v-else>{{ title }}</template>
189
+				</template>
190
+			</a-tree>
191
+		</div>
85 192
 		<div class="player mr-4">
86
-			<div class="w-full h-[25px] bg-black text-white pl-5">
87
-				播放通道
88
-			</div>
193
+			<div class="w-full h-[25px] bg-black text-white pl-5">播放通道</div>
89 194
 			<div id="player"></div>
90 195
 		</div>
91 196
 		<div class="control w-[20%] h-full">
92 197
 			<a-tabs v-model:activeKey="activeKey">
93 198
 				<a-tab-pane key="1" tab="摄像头列表">
94
-					回放日期  <a-range-picker value-format="YYYY-MM-DD HH:mm:ss" show-time />
199
+					回放日期 <a-range-picker value-format="YYYY-MM-DD HH:mm:ss" show-time />
200
+					<div class="mt-5">
201
+						<a-tree :tree-data="cameraListData" @select="cameraSelect" class="w-full">
202
+							<template #title="{ title, key }">
203
+								<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
204
+								<template v-else>{{ title }}</template>
205
+							</template>
206
+						</a-tree>
207
+					</div>
95 208
 				</a-tab-pane>
96 209
 				<a-tab-pane key="2" tab="操作" force-render>
97
-
98 210
 					<div class="row">
99 211
 						<a-button type="primary" class="mr-5 btn">&lt;&lt; 慢放</a-button>
100 212
 						<a-button type="primary" class="btn">快放 &gt;&gt;</a-button>
@@ -112,30 +224,30 @@ onMounted(() => {
112 224
 </template>
113 225
 
114 226
 <style scoped lang="less">
115
-.player {
116
-	#player {
117
-		width: 55vw;
118
-		height: calc((55vw) * 5 / 8);
227
+	.player {
228
+		#player {
229
+			width: 55vw;
230
+			height: calc((55vw) * 5 / 8);
231
+		}
119 232
 	}
120
-}
121 233
 
122
-.row {
123
-	margin-bottom: 10px;
124
-	display: flex;
125
-	justify-content: center;
126
-	align-items: center;
127
-	.btn {
128
-		width: 120px;
129
-		margin-top: 5px;
234
+	.row {
235
+		margin-bottom: 10px;
236
+		display: flex;
237
+		justify-content: center;
238
+		align-items: center;
239
+		.btn {
240
+			width: 120px;
241
+			margin-top: 5px;
242
+		}
130 243
 	}
131
-}
132
-.control-row {
133
-	display: flex;
134
-	justify-content: center;
135
-	align-items: center;
136
-	.small-btn {
137
-		width: 80px;
138
-		margin-top: 5px;
244
+	.control-row {
245
+		display: flex;
246
+		justify-content: center;
247
+		align-items: center;
248
+		.small-btn {
249
+			width: 80px;
250
+			margin-top: 5px;
251
+		}
139 252
 	}
140
-}
141 253
 </style>

+ 7 - 4
src/views/enforcementSupervision/caseInquiry/index.vue

@@ -50,11 +50,10 @@
50 50
 				<div class="silt-title" style="width: 400px">
51 51
 					<span style="width: 70px; display: block">{{ '受理日期' }}</span>
52 52
 					<a-range-picker
53
-						show-time
54 53
 						style="width: 340px"
55 54
 						v-model:value="dateValue"
56
-						@change="handleChange1"
57
-						valueFormat="YYYY-MM-DD HH:mm:ss"
55
+						@change="handleChange"
56
+						valueFormat="YYYY-MM-DD"
58 57
 					>
59 58
 					</a-range-picker>
60 59
 				</div>
@@ -92,6 +91,7 @@ import enforcementSupervisionApi from '@/api/enforcementSupervision.info/enforce
92 91
 import DetailFrom from '../caseManagement/form.vue'
93 92
 import * as echarts from 'echarts'
94 93
 import { cloneDeep } from 'lodash-es'
94
+import dayjs from 'dayjs'
95 95
 import { Empty } from 'ant-design-vue'
96 96
 const dateValue = ref([])
97 97
 const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE
@@ -160,7 +160,10 @@ const columns = [
160 160
 		title: '案件日期',
161 161
 		dataIndex: 'caseDate',
162 162
 		align: 'center',
163
-		key: 'caseDate'
163
+		key: 'caseDate',
164
+		customRender: ({ text, record, index }) => {
165
+			return dayjs(text).format('YYYY-MM-DD')
166
+		}
164 167
 	},
165 168
 	{
166 169
 		title: '操作',

+ 2 - 4
src/views/enforcementSupervision/caseManagement/form.vue

@@ -72,13 +72,11 @@
72 72
 					></a-col>
73 73
 					<a-col :span="8"
74 74
 						><a-form-item
75
-							:rules="[
76
-								{ required: true, message: '请输入身份证号', trigger: 'blur' },
77
-								{ validator: isSocialCreditOrIdCode, trigger: 'blur' }
78
-							]"
75
+							:rules="[{ required: true, message: '请输入身份证号', trigger: 'blur' }]"
79 76
 							label="身份证号"
80 77
 							name="idCardNumbers"
81 78
 						>
79
+							<!-- { validator: validateMultipleIDCards, trigger: 'blur' } -->
82 80
 							<a-input
83 81
 								:disabled="flag == 2 || flag == 4"
84 82
 								class="int-box"

+ 7 - 3
src/views/enforcementSupervision/caseManagement/index.vue

@@ -27,11 +27,10 @@
27 27
 				<div class="silt-title" style="width: 400px">
28 28
 					<span style="width: 70px; display: block">{{ '受理日期' }}</span>
29 29
 					<a-range-picker
30
-						show-time
31 30
 						style="width: 340px"
32 31
 						v-model:value="dateValue"
33 32
 						@change="handleChange"
34
-						valueFormat="YYYY-MM-DD HH:mm:ss"
33
+						valueFormat="YYYY-MM-DD"
35 34
 					>
36 35
 					</a-range-picker>
37 36
 				</div>
@@ -73,6 +72,8 @@
73 72
 // import AddForm from './add.vue'
74 73
 import enforcementSupervisionApi from '@/api/enforcementSupervision.info/enforcementSupervision.js'
75 74
 // import EditForm from './edit.vue'
75
+import dayjs from 'dayjs'
76
+
76 77
 import DetailFrom from './form.vue'
77 78
 import { Modal } from 'ant-design-vue'
78 79
 const dateValue = ref('')
@@ -141,7 +142,10 @@ const columns = [
141 142
 		title: '案件日期',
142 143
 		dataIndex: 'caseDate',
143 144
 		align: 'center',
144
-		key: 'caseDate'
145
+		key: 'caseDate',
146
+		customRender: ({ text, record, index }) => {
147
+			return dayjs(text).format('YYYY-MM-DD')
148
+		}
145 149
 	},
146 150
 	{
147 151
 		title: '操作',

+ 1 - 1
src/views/enforcementSupervision/enforcementBasis/form.vue

@@ -78,7 +78,7 @@
78 78
 			</a-form>
79 79
 			<div class="btn-box">
80 80
 				<a-button @click="isClose">取消</a-button>
81
-				<a-button @click="submit" style="background-color: #25c8c8; color: white">保存</a-button>
81
+				<a-button @click="submit" v-if="flag!=2" style="background-color: #25c8c8; color: white">保存</a-button>
82 82
 			</div>
83 83
 		</a-modal>
84 84
 	</div>

+ 2 - 2
src/views/enforcementSupervision/management/form.vue

@@ -141,7 +141,7 @@
141 141
 						</a-form-item>
142 142
 					</a-col>
143 143
 					<a-col :span="8"
144
-						><a-form-item :rules="[{ required: true }]" label="所属行政管理位" name="administrativeUnit">
144
+						><a-form-item :rules="[{ required: true }]" label="所属行政管理位" name="administrativeUnit">
145 145
 							<a-input
146 146
 								autocomplete="off"
147 147
 								v-model:value="formState.administrativeUnit"
@@ -158,7 +158,7 @@
158 158
 			</a-form>
159 159
 			<div class="btn-box">
160 160
 				<a-button @click="isClose">取消</a-button>
161
-				<a-button @click="submit" style="background-color: #25c8c8; color: white">保存</a-button>
161
+				<a-button @click="submit" v-if="flag!=2" style="background-color: #25c8c8; color: white">保存</a-button>
162 162
 			</div>
163 163
 		</a-modal>
164 164
 	</div>

+ 1 - 1
src/views/enforcementSupervision/processManagement/courseManagement/form.vue

@@ -133,7 +133,7 @@
133 133
 			</a-form>
134 134
 			<div class="btn-box">
135 135
 				<a-button @click="isClose">取消</a-button>
136
-				<a-button @click="submit" style="background-color: #169bd5; color: white">保存</a-button>
136
+				<a-button @click="submit" v-if="flag!=2" style="background-color: #169bd5; color: white">保存</a-button>
137 137
 			</div>
138 138
 		</a-modal>
139 139
 	</div>

+ 1 - 1
src/views/enforcementSupervision/processManagement/processManagement/form.vue

@@ -127,7 +127,7 @@
127 127
 			</a-form>
128 128
 			<div class="btn-box">
129 129
 				<a-button @click="isClose">取消</a-button>
130
-				<a-button @click="submit" style="background-color: #169bd5; color: white">保存</a-button>
130
+				<a-button @click="submit" v-if="flag!=2" style="background-color: #169bd5; color: white">保存</a-button>
131 131
 			</div>
132 132
 		</a-modal>
133 133
 	</div>

+ 7 - 1
src/views/enforcementSupervision/specialInspection/modalModule/addModal.vue

@@ -29,7 +29,13 @@
29 29
 				</a-select>
30 30
 			</a-form-item>
31 31
 			<a-form-item label="数量" name="quantity">
32
-				<a-input-number :min="0" style="width: 100%" v-model:value="formData.quantity" placeholder="请输入数量" />
32
+				<a-input-number
33
+					:min="0"
34
+					addon-after="kg"
35
+					style="width: 100%"
36
+					v-model:value="formData.quantity"
37
+					placeholder="请输入数量"
38
+				/>
33 39
 			</a-form-item>
34 40
 		</a-form>
35 41
 	</a-modal>

+ 1 - 1
src/views/enforcementSupervision/specialInspection/modalModule/jcjgcjhz.vue

@@ -272,7 +272,7 @@
272 272
 			dataIndex: 'grainVarietyId'
273 273
 		},
274 274
 		{
275
-			title: '数量',
275
+			title: '数量(kg)',
276 276
 			align: 'center',
277 277
 			key: 'quantity'
278 278
 		},

+ 1 - 1
src/views/enforcementSupervision/supervisionPersonnel/form.vue

@@ -228,7 +228,7 @@
228 228
 			</a-form>
229 229
 			<div class="btn-box">
230 230
 				<a-button @click="isClose">取消</a-button>
231
-				<a-button @click="submit" style="background-color: #25c8c8; color: white">保存</a-button>
231
+				<a-button @click="submit" v-if="flag!=2" style="background-color: #25c8c8; color: white">保存</a-button>
232 232
 			</div>
233 233
 		</a-modal>
234 234
 	</div>

+ 19 - 13
src/views/grainQualityManagement/storehouseWholeInspectEdit.vue

@@ -8,6 +8,7 @@
8 8
 	import { just_required, number_required, required_array } from '@/utils/rules'
9 9
 	import { deleteField, genKey } from '@/utils/systemUtils'
10 10
 	import { getDetail } from '@/api/grainQualityManagement/storehouseWholeInspect'
11
+	import {getNameByIdSync} from "@/utils/systemEnum";
11 12
 
12 13
 	const props = defineProps({
13 14
 		visible: {
@@ -165,7 +166,6 @@
165 166
 	const getData = () => {
166 167
 		getDetail(props.editData.id).then((resp) => {
167 168
 			const items = resp.items
168
-
169 169
 			if (resp.zbjgpd) {
170 170
 				resp.zbjgpd = resp.zbjgpd.split('|')
171 171
 			}
@@ -199,6 +199,8 @@
199 199
 			basicStorehouseId: null, // integer(int32) basic_storehouse的id;仓房id
200 200
 			bgcjsj: null, // string(date-time) 报告出具时间,格式:yyyy-MM-dd
201 201
 			bz: null, // string 备注
202
+			address: null, // string 库区地址
203
+			modifyDate: null, // string 入库日期
202 204
 			checkResult: null, // integer(int32) 检验结果
203 205
 			createdate: null, // string(date-time) 创建日期
204 206
 			dbsl: null, // number 代表数量,单位:公斤
@@ -216,14 +218,16 @@
216 218
 			jyyj: null, // string 检验依据,1:国标,
217 219
 			orgId: null, // integer(int32) 库区id
218 220
 			orgName: null, // string 库区名称
219
-			produceArea: null, // string 产地
221
+			// produceArea: null, // string 产地
222
+			gb: null, // string 产地
220 223
 			qfrq: null, // string 签发日期,格式:yyyy-MM-dd
221 224
 			qydbh: null, // string 抽样单编号;扦样单编号
222 225
 			qyqy: null, // string 扦样区域
223 226
 			qyrxm: null, // string 抽样人员;扦样人姓名
224 227
 			qysj: null, // string(date-time) 抽样日期;扦样时间,格式:yyyy-MM-dd
225
-			receiveYear: null, // string 收获年度
226
-			rkrq: null, // string(date-time) 入库日期,格式:yyyy-MM-dd
228
+			// receiveYear: null, // string 收获年度
229
+			scnf: null, // string 收获年度
230
+			// rkrq: null, // string(date-time) 入库日期,格式:yyyy-MM-dd
227 231
 			samplePackageModel: null, // string 样品包装型号
228 232
 			sampleStatus: null, // string 样品状态
229 233
 			sfzcccnx: null, // string 是否正常存储年限,0:否,
@@ -252,7 +256,7 @@
252 256
 		grainGradeId: just_required,
253 257
 		xzId: just_required,
254 258
 		produceArea: just_required,
255
-		rkrq: just_required,
259
+		modifyDate: just_required,
256 260
 		jydw: just_required,
257 261
 		jyyj: just_required,
258 262
 		jysj: just_required,
@@ -350,8 +354,8 @@
350 354
 					</a-form-item>
351 355
 				</a-col>
352 356
 				<a-col :span="8">
353
-					<a-form-item label="库区地址" name="registeredAddress">
354
-						<a-input :disabled="readonly" v-model:value="formData.registeredAddress" />
357
+					<a-form-item label="库区地址" name="address">
358
+						<a-input :disabled="readonly" v-model:value="formData.address" />
355 359
 					</a-form-item>
356 360
 				</a-col>
357 361
 			</a-row>
@@ -424,18 +428,20 @@
424 428
 
425 429
 			<a-row :gutter="42">
426 430
 				<a-col :span="8">
427
-					<a-form-item label="入库日期" name="rkrq">
428
-						<a-date-picker v-model:value="formData.rkrq" valueFormat="YYYY-MM-DD" :disabled="readonly" />
431
+					<a-form-item label="入库日期" name="modifyDate">
432
+						<a-date-picker v-model:value="formData.modifyDate" valueFormat="YYYY-MM-DD" :disabled="readonly" />
429 433
 					</a-form-item>
430 434
 				</a-col>
431 435
 				<a-col :span="8">
432
-					<a-form-item label="收获年度" name="receiveYear">
433
-						<a-date-picker v-model:value="formData.receiveYear" picker="year" valueFormat="YYYY" :disabled="readonly" />
436
+					<a-form-item label="收获年度" name="scnf">
437
+						<a-input :disabled="readonly" v-model:value="formData.scnf" />
438
+<!--						<a-input :disabled="readonly" :value="getNameByIdSync(formData.scnf).name" />-->
439
+<!--						<a-date-picker v-model:value="formData.receiveYear" picker="year" valueFormat="YYYY" :disabled="readonly" />-->
434 440
 					</a-form-item>
435 441
 				</a-col>
436 442
 				<a-col :span="8">
437
-					<a-form-item label="产地" name="produceArea">
438
-						<a-input :disabled="readonly" v-model:value="formData.produceArea" />
443
+					<a-form-item label="产地" name="gb">
444
+						<a-input :disabled="readonly" v-model:value="formData.gb" />
439 445
 					</a-form-item>
440 446
 				</a-col>
441 447
 			</a-row>