index.vue 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  1. <template>
  2. <div class="app-container" style="padding-top: 20px;height: 120vh;" >
  3. <div class="ntgs">
  4. <el-row :gutter="10" class="mb8">
  5. <div class="iuer" style="margin-bottom:10px;">
  6. <!-- <div style="display: flex;align-items: center; " class="ingaqe">
  7. <el-select v-model="queryParams.name" placeholder="请选监控名称" clearable>
  8. <el-option
  9. v-for="dict in postList"
  10. :key="dict.indexCode"
  11. :label="dict.name"
  12. :value="dict.name"
  13. />
  14. </el-select>
  15. <div class="ksfpofg" @click="handleQuery">
  16. 搜索
  17. </div>
  18. </div> -->
  19. <!-- <div class="ite">
  20. <div class="ksfpo" @click="osge" v-hasPermi="['system:camera:openDz']">
  21. <img src="../../../assets/images/icon_ssjk_kman_open.png" alt="" style="width:10px;height: 10px;">
  22. 开门</div>
  23. <div class="ksfpo ksfpok" @click="osgef" v-hasPermi="['system:camera:closeDz']">
  24. <img src="../../../assets/images/icon_ssjk_kman_close.png" alt="" style="width:10px;height: 10px;">
  25. 关门</div>
  26. </div> -->
  27. <!-- -->
  28. </div>
  29. <!-- <el-col :span="1.5">
  30. <el-button
  31. type="primary"
  32. plain
  33. icon="el-icon-plus"
  34. size="mini"
  35. @click="handleAdd"
  36. v-hasPermi="['investigate:table:add']"
  37. >新增</el-button>
  38. </el-col>
  39. <el-col :span="1.5">
  40. <el-button
  41. type="danger"
  42. plain
  43. icon="el-icon-delete"
  44. size="mini"
  45. :disabled="multiple"
  46. @click="handleDelete"
  47. v-hasPermi="['investigate:table:remove']"
  48. >删除</el-button>
  49. </el-col> -->
  50. <!-- <el-col :span="1.5">
  51. <el-button
  52. type="warning"
  53. plain
  54. icon="el-icon-download"
  55. size="mini"
  56. @click="handleExport"
  57. v-hasPermi="['investigate:table:export']"
  58. >导出</el-button>
  59. </el-col> -->
  60. <!-- <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> -->
  61. </el-row>
  62. <div>
  63. <el-row :gutter="20">
  64. <!-- postList -->
  65. <el-col :span='5'>
  66. <div style="background-color: #fff;border-radius: 10px;padding: 20px 20px;height: 100vh;">
  67. <p style="margin: 0;border-left: 6px solid #03BF8A;margin-left: -20px;padding-left: 10px;font-weight: 800;">通道列表</p>
  68. <div :class="ishge == index ? 'anche' : ''" style=" height: 36px;;line-height: 36px;margin-top: 10px;padding: 0 10px ;"v-for="(item,index) in channelNumberList" :key="index">
  69. <div @click="ishg(item,index)" style="display: flex;align-items: center;justify-content: space-between;">
  70. <div style="font-size: 16px;
  71. color: #333333;"> {{item.channelNum == null?'暂无数据' : item.channelNum}}</div>
  72. <img src="../../../assets/images/icon_htgl_zd.png" alt="" style="width: 10px;height: 12px;">
  73. </div>
  74. </div>
  75. <div>
  76. </div>
  77. </div>
  78. </el-col>
  79. <!-- v-if="isshoe" -->
  80. <el-col :span='19' style="padding-left: 30px; background-color: #fff;border-radius: 10px;padding: 20px; height: 100vh;" >
  81. <div style="display: flex;align-items: center;justify-content: space-between;margin-bottom: 18px;">
  82. <p style="margin: 0;border-left: 6px solid #03BF8A;margin-left: -20px;padding-left: 10px;font-weight: 800;">实时预览
  83. <span style="font-size: 12px; color: red;cursor: pointer;" @click="xiazag">下载插件</span>
  84. </p>
  85. </p>
  86. <div>
  87. <!-- <el-button type="danger" plain>删除</el-button>
  88. <el-button type="warning" plain>置顶</el-button> -->
  89. <!-- <el-button type="success" plain>关闭</el-button> -->
  90. </div>
  91. </div>
  92. <div style="width: 100%; height: 480px;">
  93. <div v-if="isfse" id="divPlugin" style="width: 100%; height: 440px;" ></div>
  94. </div>
  95. <!-- <img src="../../../assets/images/pic_ssyl_lt.png" alt="" style="width: 100%; margin-top: 20px;"> -->
  96. <!-- 344 -->
  97. <!-- <video id="video" controls autoplay muted width="100%" height="480px"style="margin-top: 20px;"></video> -->
  98. <!-- <video
  99. class="videosmall"
  100. ref="videosmallone"
  101. preload="auto"
  102. muted
  103. autoplay
  104. width="95%"
  105. type="rtmp/flv"
  106. >
  107. <source src="" />
  108. </video> -->
  109. </el-col>
  110. <!-- <el-col :span="24">
  111. <div class="ihgswq wrapper" ref="wrapper" style=" overflow: hidden;">
  112. <div class="fijge content nhgwesvq" ref="content" style="width:1610px;">
  113. <div class='shotw ' v-for="(item,index) in postList" :key="index" @click="isfgw(item)" >
  114. <img src="../../../assets/images/fengm.png" alt="">
  115. <img src="../../../assets/images/icon_spjk_play.png" alt="" class="iges">
  116. <p style="font-size: 14px;">{{item.name}}</p>
  117. </div>
  118. </div>
  119. </div>
  120. </el-col> -->
  121. </el-row>
  122. <!-- <pagination
  123. v-show="total>0"
  124. :total="total"
  125. :page.sync="queryParams.pageNo"
  126. :limit.sync="queryParams.pageSize"
  127. @pagination="getList"
  128. /> -->
  129. </div>
  130. </div>
  131. <!-- 添加或修改岗位对话框 -->
  132. <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
  133. </el-dialog>
  134. <el-dialog :title="titles" :visible.sync="opens" width="1000px" append-to-body>
  135. </el-dialog>
  136. <el-dialog title="页面二维码" :visible.sync="opent" width="200px" style="padding: 0;" class="nhgrls" append-to-body>
  137. <div v-show="opent" style="display: flex;justify-content: center;align-items: center;">
  138. <!-- <span>{{'https://qszdh.qs163.cn/pages/index/index?id=' + this.bg}}</span> -->
  139. <!-- <vue-qr :text="'https://qszdh.qs163.cn/pages/index/index?id=' + this.bg" :size="200"></vue-qr> -->
  140. </div>
  141. </el-dialog>
  142. </div>
  143. </template>
  144. <script>
  145. import { listChannelNumber, listChannelNumbernopa,getChannelNumber, delChannelNumber, addChannelNumber, updateChannelNumber } from "@/api/system/channelNumber"
  146. import { listWarnManage, getWarnManage, delWarnManage, addWarnManage, updateWarnManage } from "@/api/manage/warnManage"
  147. // import { listPost, getPost, delPost, addPost, updatePost,updateFs,updateGx } from "@/api/kaoch/renyuan";
  148. // import { listReservat,camera,cameraIndexCode, listReservatd, getReservat, delReservat, addReservat, updateReservat,setPass,delReservathx,openDz,closeDz } from "@/api/tonggi/houtai";
  149. // import vueQr from "vue-qr";
  150. // import videojs from 'video.js'
  151. // import 'video.js/dist/video-js.css'
  152. // import {videoPlayer} from 'vue-video-player'
  153. // import 'videojs-flash'
  154. // import flvjs from 'flv.js/dist/flv.min.js'
  155. // import flvjs from "flv.js";
  156. import mqtt from 'mqtt';
  157. import { MqttClient } from 'mqtt'
  158. // 状态变量
  159. // const client = mqtt.connect('ws://13.229.167.76:1884/mqtt')
  160. var client = MqttClient||null
  161. import Bscroll from "better-scroll";
  162. export default {
  163. name: "Post",
  164. dicts: ['sys_normal_disable','sys_yes_no','youke','tjzh','youkes','lafafen','fange','jluly'],
  165. // components: {
  166. // vueQr,
  167. // videoPlayer
  168. // },
  169. data() {
  170. return {
  171. // 遮罩层
  172. loading: true,
  173. opent:false,
  174. bg:null,
  175. titles:'',
  176. editableTabsValue:'6',
  177. opens:false,
  178. // 通道管理表格数据
  179. channelNumberList: [],
  180. imageUrl:'@/assets/logo/logo.png',
  181. printObj: {
  182. id: "nhgrew", // 这里是要打印元素的ID
  183. popTitle: "", // 打印的标题
  184. },
  185. pickerOptions:{
  186. disabledDate (time) {
  187. //disabledDate 文档上:设置禁用状态,参数为当前日期,要求返回 Boolean
  188. // return time.getTime() > Date.now()//选当前时间之前的时间
  189. return time.getTime() < Date.now() - 8.64e7;//选当前时间之后的时间
  190. }
  191. },
  192. // 选中数组
  193. ids: [],
  194. // 非单个禁用
  195. single: true,
  196. checkedScoreDataDetails: [],
  197. scoreDataDetailsList:[],
  198. tabPosition:'left',
  199. // 非多个禁用
  200. multiple: true,
  201. // 显示搜索条件
  202. showSearch: true,
  203. // 总条数
  204. total: 0,
  205. // 岗位表格数据
  206. postList: [],
  207. // 弹出层标题
  208. title: "",
  209. // 是否显示弹出层
  210. open: false,
  211. // 查询参数
  212. queryParams: {
  213. pageNo: 1,
  214. pageSize:500,
  215. name:null,
  216. postCode: undefined,
  217. postName: undefined,
  218. status: undefined,
  219. reservatType:undefined
  220. },
  221. // 表单参数
  222. form: {},
  223. // 表单校验
  224. rules: {
  225. receptionId: [
  226. { required: true, message: "不能为空", trigger: "blur" }
  227. ],
  228. },
  229. ruless:{
  230. visitName: [
  231. { required: true, message: "不能为空", trigger: "blur" }
  232. ],
  233. visitPhone: [
  234. { required: true, message: "不能为空", trigger: "blur" }
  235. ],
  236. visitNum: [
  237. { required: true, message: "不能为空", trigger: "blur" }
  238. ],
  239. visitDate: [
  240. { required: true, message: "不能为空", trigger: "blur" }
  241. ],
  242. visitTime: [
  243. { required: true, message: "不能为空", trigger: "blur" }
  244. ],
  245. },
  246. forms:{},
  247. tableMaxHeight:'200',
  248. kje:0,
  249. ksjegsg:[],
  250. Scroll: null,
  251. videoShow: false,
  252. flvPlayer:null,
  253. player: null,
  254. name:null,
  255. isshiwa:false,
  256. isjfwe:{},
  257. isshoe:false,
  258. webRtcServer: null,
  259. camera_ip: '127.0.0.1:8000',
  260. g_iWndIndex:0,
  261. iRtspPort:'',//预览中的ip
  262. szDeviceIdentify:'',//ip_port,
  263. isfse:false,
  264. g_bEnableDraw:false,
  265. // 所有绘制的图形
  266. shapes: [],
  267. // 禁用
  268. isdisflag:false,
  269. connectionStatus:'',
  270. isConnected:false,
  271. connecting:false,
  272. messages:[{ type: 'sent' , content: '', timestamp: '' }],
  273. messageToSend:[],
  274. mqttConfig:{
  275. url: 'ws://13.229.167.76:1884/mqtt',
  276. topic: 'detection/rect'
  277. },
  278. mqttThemeName:{
  279. url: 'ws://13.229.167.76:1884/mqtt',
  280. topic: 'detection/rect'
  281. },
  282. ishge:0
  283. };
  284. },
  285. created() {
  286. this.isfse = false
  287. // this.getList();
  288. this.getListtd()
  289. window.onresize = () => {
  290. this.changeTableMaxHeight()
  291. }
  292. this.changeTableMaxHeight()
  293. },
  294. mounted() {
  295. // this.toggleConnection()
  296. // this.webRtcServer = new WebRtcStreamer('video', location.protocol + '//' + this.camera_ip)
  297. // //需要查看的rtsp地址,根据自己的摄像头传入对应的rtsp地址即可。注意:视频编码格式必须是H264的,否则无法正常显示,编码格式可在摄像头的后台更改
  298. // this.webRtcServer.connect('rtsp://admin:zxy123456@192.168.101.64:554/h264/ch1/main/av_stream')
  299. window.onresize = () => {
  300. this.changeTableMaxHeight()
  301. }
  302. this.changeTableMaxHeight()
  303. this.$nextTick(() => {
  304. this.initScroll()
  305. })
  306. },
  307. beforeDestroy() {
  308. // this.destoryVideo()
  309. if(WebVideoCtrl){
  310. console.log(this.szDeviceIdentify)
  311. WebVideoCtrl.I_Logout(this.szDeviceIdentify)
  312. WebVideoCtrl.I_StopAllPlay()
  313. WebVideoCtrl.I_DestroyPlugin()
  314. WebVideoCtrl.I_Resize()
  315. }
  316. },
  317. methods: {
  318. /** 查询通道管理列表 */
  319. getListtd() {
  320. this.loading = true
  321. let queryParams = {}
  322. listChannelNumbernopa().then(response => {
  323. this.channelNumberList = response.rows
  324. if(this.channelNumberList.length !=0){
  325. let snghs = this.channelNumberList[0].videoAddress.split('@')
  326. let snghst = snghs[1].split(':')
  327. let snsgduan = snghst[1].split('/')
  328. console.log(snghs,snghst,snsgduan)
  329. let sgse={'ip':snghst[0],'duank':snsgduan[0],
  330. 'account':this.channelNumberList[0].account,
  331. 'password':this.channelNumberList[0].password,
  332. 'port':this.channelNumberList[0].port
  333. }
  334. this.getVideo(sgse)
  335. WebVideoCtrl.I_ShowPlugin()
  336. this.loading = false
  337. }
  338. // getWarnManage(this.$route.query.id).then(response => {
  339. // this.form = response.data
  340. this.loading = false
  341. })
  342. },
  343. clickEnableDraw() {
  344. WebVideoCtrl.I_SetDrawStatus(true).then(() => {
  345. this.g_bEnableDraw = true;
  346. // showOPInfo("启用绘制成功!");
  347. }, (oError) => {
  348. // showOPInfo("启用绘制失败!", oError.errorCode, oError.errorMsg);
  349. });
  350. },
  351. getdrawFn(){
  352. this.isdisflag=!this.isdisflag;
  353. if(this.isdisflag){
  354. this.clickDisableDraw()
  355. }else{
  356. this.clickEnableDraw()
  357. }
  358. },
  359. // 禁用多边形绘制
  360. clickDisableDraw() {
  361. WebVideoCtrl.I_SetDrawStatus(false).then(() => {
  362. this.g_bEnableDraw = false;
  363. // showOPInfo("禁用绘制成功!");
  364. this.clickAddSnapPolygon()
  365. }, (oError) => {
  366. // showOPInfo("禁用绘制失败!", oError.errorCode, oError.errorMsg);
  367. });
  368. },
  369. clickGetSnapPolygon() {
  370. var that=this;
  371. WebVideoCtrl.I_GetSnapPolygonInfo(this.g_iWndIndex).then((szXml) => {
  372. console.log('获取图形:', szXml);
  373. that.getpoint(szXml)
  374. });
  375. },
  376. //获取x,y轴
  377. getpoint(xmlString){
  378. var that=this;
  379. const parser = new DOMParser();
  380. const xmlDoc = parser.parseFromString(xmlString, "text/xml");
  381. // 获取所有 SnapPolygon 节点
  382. const polygonNodes = xmlDoc.querySelectorAll("SnapPolygon");
  383. var newArr=[];
  384. var arr1=JSON.parse(JSON.stringify(this.shapes))
  385. // 提取每个多边形的 id 和坐标点
  386. this.polygons = Array.from(polygonNodes).map((polygonNode) => {
  387. const id = polygonNode.querySelector("id").textContent;
  388. const pointNodes = polygonNode.querySelectorAll("point");
  389. const points = Array.from(pointNodes).map((pointNode) => ({
  390. x: pointNode.querySelector("x").textContent,
  391. y: pointNode.querySelector("y").textContent,
  392. }));
  393. var newobj={
  394. id:id,
  395. points:points
  396. }
  397. newArr.push(newobj)
  398. // return { id, points };
  399. });
  400. this.shapes = arr1.map(item1 => {
  401. const matchedItem = newArr.find(item2 => item2.id == item1.id);
  402. return {
  403. id: item1.id,
  404. points: matchedItem ? matchedItem.points : item1.points
  405. };
  406. });
  407. // this.shapes=JSON.parse(JSON.stringify(newArr))
  408. this.messageToSend = this.shapes
  409. this.sendMessage()
  410. console.log(this.shapes)
  411. },
  412. toggleConnection(){
  413. if (this.isConnected) {
  414. // 断开连接
  415. client.end()
  416. this.isConnected= false
  417. this.connectionStatus = 'Disconnected'
  418. return
  419. }
  420. // 建立连接
  421. this.connecting = true
  422. try {
  423. client= mqtt.connect(this.mqttConfig.url, {
  424. clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
  425. keepalive: 60,
  426. clean: true,
  427. connectTimeout: 4000,
  428. reconnectPeriod: 1000
  429. })
  430. client.on('connect', () => {
  431. this.isConnected = true
  432. this.connectionStatus= 'Connected'
  433. this.connecting = false
  434. console.log(3)
  435. // 订阅主题
  436. client.subscribe(this.mqttConfig.topic, (err) => {
  437. if (err) {
  438. console.error('Subscribe error:', err)
  439. }else{
  440. console.log('成功订阅 detection/rect 主题!')
  441. }
  442. })
  443. })
  444. client.on('message', (topic, message) => {
  445. // 接受信息
  446. console.log(topic,message)
  447. this.messages.unshift({
  448. type: 'received',
  449. content: message.toString(),
  450. timestamp: new Date().toLocaleTimeString()
  451. })
  452. })
  453. client.on('error', (err) => {
  454. console.error('MQTT Error:', err)
  455. this.connectionStatus= 'Error'
  456. this.connecting = false
  457. })
  458. } catch (error) {
  459. console.error('Connection error:', error)
  460. this.connectionStatus= 'Error'
  461. this.connecting = false
  462. }
  463. },
  464. sendMessage(){
  465. if (!client || !this.messageToSend) return
  466. this.messageToSend = JSON.stringify(this.messageToSend)
  467. console.log(this.messageToSend)
  468. client.publish(this.mqttConfig.topic, this.messageToSend)
  469. this.messages.unshift({
  470. type: 'sent',
  471. content: this.messageToSend,
  472. timestamp: new Date().toLocaleTimeString()
  473. })
  474. this.messageToSend = []
  475. },
  476. // 添加图形,最多不超过16个图形
  477. clickAddSnapPolygon() {
  478. var that=this;
  479. if (!this.g_bEnableDraw) {
  480. return;
  481. }
  482. var shapes=JSON.parse(JSON.stringify(this.shapes))
  483. let szId = 1; // 默认从 1 开始
  484. if(shapes&&shapes.length>0){
  485. const ids = shapes.map(item => item.id).sort((a, b) => a - b);
  486. for (const id of ids) {
  487. if (id > szId) {
  488. // 如果当前 id > szId,说明 szId 未被使用
  489. break;
  490. }
  491. szId = Number(id) + 1; // 否则,继续检查下一个
  492. }
  493. }
  494. if (!/^[1-9]\d*$/.test(szId)) {
  495. alert("图形ID只能为正整数!");
  496. return
  497. }
  498. if (Number(szId) > 32) {
  499. alert("图形ID范围1-32!");
  500. return
  501. }
  502. console.log(szId)
  503. // var szName = encodeString($("#snapName").val());
  504. var szName = '';
  505. var szInfo={
  506. }
  507. var szInfo = "<?xml version='1.0' encoding='utf-8'?>";
  508. szInfo += "<SnapPolygonList>";
  509. szInfo += "<SnapPolygon>";
  510. szInfo += "<id>" + szId + "</id>"; // [1, 32]
  511. szInfo += "<polygonType>0</polygonType>"; //如果想绘制多边形,polygonType指需要改为1
  512. szInfo += "<PointNumMax>17</PointNumMax>"; // [MinClosed, 17]
  513. szInfo += "<MinClosed>4</MinClosed>"; // [4, 17]
  514. szInfo += "<tips>#" + szId + "#" + szName + "</tips>";
  515. szInfo += "<isClosed>false</isClosed>";
  516. szInfo += "<color><r>0</r><g>255</g><b>0</b></color>";
  517. szInfo += "<pointList/>";
  518. szInfo += "</SnapPolygon>";
  519. szInfo += "</SnapPolygonList>";
  520. WebVideoCtrl.I_SetSnapPolygonInfo(this.g_iWndIndex, szInfo).then(() => {
  521. // showOPInfo("添加图形成功!");
  522. var obj={
  523. id:szId,
  524. points:[]
  525. }
  526. if(this.shapes&&this.shapes.length){
  527. this.shapes.splice(Number(szId)-1,0,obj)
  528. }else{
  529. this.shapes.push(obj)
  530. }
  531. });
  532. WebVideoCtrl.I_SetSnapDrawMode(this.g_iWndIndex, 2);
  533. },
  534. //删除图形
  535. clickDelSnapPolygon(szId,idx) {
  536. if (!this.g_bEnableDraw) {
  537. return;
  538. }
  539. var aShapes = [];
  540. aShapes.push({
  541. polygonType: 0,
  542. id: szId
  543. });
  544. this.shapes.splice(idx,1)
  545. WebVideoCtrl.I_ClearSnapInfo(this.g_iWndIndex, aShapes);
  546. },
  547. // 清空图形
  548. clickDelAllSnapPolygon() {
  549. if (!this.g_bEnableDraw) {
  550. return;
  551. }
  552. WebVideoCtrl.I_ClearSnapInfo(this.g_iWndIndex).then(() => {
  553. // showOPInfo("清空图形成功!");
  554. this.shapes=[];
  555. }, (oError) => {
  556. // showOPInfo("清空图形失败!", oError.errorCode, oError.errorMsg);
  557. });
  558. },
  559. // 通道点击
  560. ishg(val,row){
  561. this.ishge = row
  562. this.isfse = false
  563. if(WebVideoCtrl){
  564. console.log(this.szDeviceIdentify)
  565. this.clickDelAllSnapPolygon()
  566. WebVideoCtrl.I_Logout(this.szDeviceIdentify)
  567. WebVideoCtrl.I_StopAllPlay()
  568. WebVideoCtrl.I_DestroyPlugin()
  569. WebVideoCtrl.I_Resize()
  570. }
  571. let snghs = val.videoAddress.split('@')
  572. let snghst = snghs[1].split(':')
  573. let snsgduan = snghst[1].split('/')
  574. console.log(snghs,snghst,snsgduan)
  575. let sgse={'ip':snghst[0],'duank':snsgduan[0],
  576. 'account':val.account,
  577. 'password':val.password,
  578. 'port':val.port
  579. }
  580. this.getVideo(sgse)
  581. WebVideoCtrl.I_ShowPlugin()
  582. // this.clickStartRealPlay('192.168.101.64', '80',1, 0, 1);
  583. },
  584. init(val) { //这个val 就是一个地址,例如: http://192.168.2.201:85/live/9311272c49b845baa2b2810ad9bf3f68.flv 这是个服务器返回给我的一个监控视频流地址
  585. setTimeout(() => { //使用定时器是因为,在mounted声明周期里调用,可能会出现DOM没加载出来的原因
  586. var videoElement = this.$refs.videosmallone; // 获取到html中的video标签
  587. this.isshiwa = true
  588. if (flvjs.isSupported()) {
  589. //因为我这个是复用组件,进来先判断 player是否存在,如果存在,销毁掉它,不然会占用TCP名额
  590. if (this.player !== null) {
  591. this.player.pause();
  592. this.player.unload();
  593. this.player.detachMediaElement();
  594. this.player.destroy();
  595. this.player = null;
  596. }
  597. this.player = flvjs.createPlayer( //创建直播流,加载到DOM中去
  598. {
  599. type: "flv",
  600. url: val, //你的url地址
  601. isLive: true, //数据源是否为直播流
  602. hasAudio: false, //数据源是否包含有音频
  603. hasVideo: true, //数据源是否包含有视频
  604. enableStashBuffer: true, //是否启用缓存区
  605. },
  606. {
  607. enableWorker: false, //不启用分离线程
  608. enableStashBuffer: false, //关闭IO隐藏缓冲区
  609. autoCleanupSourceBuffer: true, //自动清除缓存
  610. lazyLoad: false,
  611. }
  612. );
  613. this.isshoe = true
  614. this.player.attachMediaElement(videoElement); //放到dom中去
  615. //!!!!!!这里需要注意,有的时候load加载完成不一定可以播放,要是播放不成功,用settimeout 给下面的this.player.play() 延时几百毫秒再播放
  616. // setTimeout(this.player.play(), 48000);
  617. setTimeout(() =>{
  618. //到时间时只执行一次就停止
  619. this.player.load();//准备完成
  620. this.player.play()
  621. console.log('播放')
  622. },900)
  623. }
  624. }, 500);
  625. },
  626. createVideo() {
  627. if (flvjs.isSupported()) {
  628. console.log(1)
  629. var videoElement = document.getElementById('myFlvVideo')
  630. console.log(videoElement,flvjs)
  631. this.flvPlayer = flvjs.createPlayer(
  632. {
  633. type: 'application/x-mpegURL',
  634. isLive: true,
  635. hasAudio: false,
  636. url:'https://stream1.freetv.fun/86d463c0006da643e45e26b34875df87059dcba13e69d0a5471b185793c122a2.m3u8'
  637. },
  638. {
  639. cors: true, // 是否跨域
  640. enableWorker: false, // 是否多线程工作
  641. enableStashBuffer: false, // 是否启用缓存
  642. stashInitialSize: 400, // 缓存大小(kb) 默认384kb
  643. autoCleanupSourceBuffer: true // 是否自动清理缓存
  644. }
  645. )
  646. this.flvPlayer.attachMediaElement(videoElement)
  647. this.flvPlayer.load()
  648. this.flvPlayer.play()
  649. console.log(1244)
  650. // 报错重连
  651. this.flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
  652. console.log('errorType:', errType)
  653. console.log('errorDetail:', errDetail)
  654. if (this.flvPlayer) {
  655. this.destoryVideo()
  656. this.createVideo()
  657. }
  658. })
  659. }
  660. console.log(this.flvPlayer.play())
  661. },
  662. destoryVideo() {
  663. this.player.pause()
  664. this.player.unload()
  665. this.player.detachMediaElement()
  666. this.player.destroy()
  667. this.player = null
  668. },
  669. initScroll() {
  670. // 给内层盒子设置宽度,不设置宽度的话无法滚动
  671. // let width = this.goods.length * 60
  672. // // 如果有外边距,可以这样写。需要去掉最后一个元素的外边距,在后面减一下
  673. // let width = this.goodslength * (60 + 10) - 10
  674. let width = 6 * (200 + 10) - 10
  675. // this.$refs.content.style.width = width + 'px'
  676. this.$nextTick(()=>{
  677. if(!this.Scroll) {
  678. this.Scroll = new Bscroll(this.$refs.wrapper,{
  679. click: true, // 配置允许点击事件
  680. scrollX: true, // 开启横向滚动
  681. eventPassthrough: 'vertical', // 当设置 eventPassthrough 为 'vertical' 的时候,scrollY 无效
  682. mouseWheel: true,
  683. scrollbar: { // 滚动条, 要加相对位置
  684. fade: true
  685. }
  686. })
  687. } else {
  688. this.Scroll.refresh() // 重新计算 better-scroll,当 DOM 结构发生变化的时确保滚动效果正常
  689. }
  690. })
  691. },
  692. // 取消按钮
  693. cancel() {
  694. this.open = false;
  695. this.opens = false;
  696. this.reset();
  697. },
  698. // 表单重置
  699. reset() {
  700. this.form = {
  701. receptionId:undefined,
  702. receptionPhone:undefined,
  703. // postSort: 0,
  704. // status: "0",
  705. receptionName: undefined
  706. };
  707. this.resetForm("form");
  708. },
  709. iszheg(event){
  710. console.log(event);
  711. // 校验身份证:
  712. console.log(reg.test(this.form.idCard),23741)
  713. if ( reg.test(this.form.idCard)|| _IDre15.test(this.form.idCard)) {
  714. // this.idea();
  715. this.go(this.form.idCard);
  716. // callback()
  717. } else {
  718. if(ncjsle.test(this.form.idCard) || nhyeli.test(this.form.idCard)){
  719. console.log(3)
  720. }else{
  721. if(gnse.test(this.form.idCard) ){
  722. console.log(4)
  723. }else{
  724. if(tw.test(this.form.idCard) || twe.test(this.form.idCard)){
  725. console.log(5)
  726. }else{
  727. this.$message.error('证件格式不正确');
  728. }
  729. }
  730. }
  731. }
  732. },
  733. erw(row){
  734. this.$router.push({
  735. path: '/reny/ewm',
  736. query:{
  737. 'tenantId':row.investigateTableId
  738. }
  739. })
  740. },
  741. hussar_17Click(val) {
  742. const _this = this
  743. var url =process.env.VUE_APP_BASE_API + 'pages/index/index?id=' + val.investigateTableId;
  744. console.log(url,this.$refs.canvas,6)
  745. this.opent = true
  746. QRCode.toCanvas(
  747. canvas,
  748. url,//生成二维码的数据
  749. {width: 100, height:100, margin: 1.5},//margin调整二维码的白边大小
  750. function (error) {
  751. if (error) {
  752. console.log(error);
  753. }
  754. }
  755. );
  756. // console.log(qrcode,987)
  757. },
  758. /** 成绩_子添加按钮操作 */
  759. handleAddScoreDataDetails() {
  760. let obj = {};
  761. obj.duty = "";
  762. obj.idCard = "";
  763. obj.phonenumber = "";
  764. obj.userName = "";
  765. this.scoreDataDetailsList.push(obj);
  766. console.log(this.scoreDataDetailsList)
  767. },
  768. /** 成绩_子删除按钮操作 */
  769. handleDeleteScoreDataDetails() {
  770. if (this.checkedScoreDataDetails.length == 0) {
  771. this.$modal.msgError("请先选择要删除的数据");
  772. } else {
  773. const scoreDataDetailsList = this.scoreDataDetailsList;
  774. const checkedScoreDataDetails = this.checkedScoreDataDetails;
  775. this.scoreDataDetailsList = scoreDataDetailsList.filter(function(item) {
  776. return checkedScoreDataDetails.indexOf(item.index) == -1
  777. });
  778. }
  779. },
  780. /** 复选框选中数据 */
  781. handleScoreDataDetailsSelectionChange(selection) {
  782. this.checkedScoreDataDetails = selection.map(item => item.index)
  783. },
  784. /** 成绩_子序号 */
  785. rowScoreDataDetailsIndex({ row, rowIndex }) {
  786. row.index = rowIndex + 1;
  787. },
  788. /** 删除按钮操作 */
  789. handleDelete(row) {
  790. const postIds = row.recordId || this.ids;
  791. delReservat(postIds).then(response => {
  792. this.$modal.msgSuccess("操作成功");
  793. this.getList();
  794. });
  795. // this.$modal.confirm('是否确认删除数据项?').then(function() {
  796. // return delPost(postIds);
  797. // }).then(() => {
  798. // this.getList();
  799. // this.$modal.msgSuccess("删除成功");
  800. // }).catch(() => {});
  801. },
  802. handleDeletehx(row) {
  803. const postIds = row.reservatId || this.ids;
  804. let nhg={}
  805. nhg.reservatId = postIds
  806. delReservathx(nhg).then(response => {
  807. this.$modal.msgSuccess("操作成功");
  808. this.getList();
  809. });
  810. // this.$modal.confirm('是否确认删除数据项?').then(function() {
  811. // return delPost(postIds);
  812. // }).then(() => {
  813. // this.getList();
  814. // this.$modal.msgSuccess("删除成功");
  815. // }).catch(() => {});
  816. },
  817. // 发送短信
  818. handleUpdatefas(row){
  819. updateFs(row).then(response => {
  820. this.$modal.msgSuccess("发送成功");
  821. // this.getList();
  822. });
  823. },
  824. handleDeletegx(row){
  825. updateGx(row).then(response => {
  826. this.$modal.msgSuccess("发送成功");
  827. // this.getList();
  828. });
  829. },
  830. /** 导出按钮操作 */
  831. handleExport() {
  832. this.download('system/reservat/export', {
  833. ...this.queryParams
  834. }, `预约人员.xlsx`)
  835. },
  836. // 获取屏幕高度
  837. showFilterForm () {
  838. this.filterActive = !this.filterActive
  839. this.changeTableMaxHeight()
  840. },
  841. changeTableMaxHeight () {
  842. let height = document.body.offsetHeight // 网页可视区域高度
  843. // if (this.filterActive) {
  844. // this.tableMaxHeight = height - 320
  845. // } else {
  846. this.tableMaxHeight = height - 350
  847. // }
  848. console.log(height)
  849. },
  850. // 播放摄像头
  851. getVideo(row) {
  852. var that=this;
  853. this.isfse = true
  854. console.log(row)
  855. this.initVideoPlay(row.ip, row.port, row.account, row.password,'divPlugin')
  856. },
  857. // 有插件
  858. initVideoPlay(ip, port, username, password,id) {
  859. var that = this;
  860. var g_iWndIndex = 0; //可以不用设置这个变量,有窗口参数的接口中,不用传值,开发包会默认使用当前选择窗口
  861. var g_oLocalConfig = null; //本地配置
  862. // let ip = this.szIP //硬盘录像机ip
  863. // let port = this.szPort //默认为80端口
  864. // let username = this.szUsername //账号:
  865. // let password = this.szPassword // 密码
  866. var iRtspPort = ''
  867. // 1.初始化插件参数及插入插件
  868. WebVideoCtrl.I_InitPlugin({
  869. bWndFull: true, //是否支持单窗口双击全屏,默认支持 true:支持 false:不支持
  870. iWndowType: 1,
  871. bDebugMode: true,
  872. cbSelWnd: function(xmlDoc) {
  873. g_iWndIndex = parseInt($(xmlDoc).find("SelectWnd").eq(0).text(), 10);
  874. const szInfo = "当前选择的窗口编号:" + g_iWndIndex;
  875. this.g_iWndIndex = g_iWndIndex;
  876. console.log(szInfo, "szInfo");
  877. },
  878. cbDoubleClickWnd: function(iWndIndex, bFullScreen) {
  879. let szInfo = "当前放大的窗口编号:" + iWndIndex;
  880. if (!bFullScreen) {
  881. szInfo = "当前还原的窗口编号:" + iWndIndex;
  882. }
  883. // console.log(szInfo, "szInfo");
  884. },
  885. cbEvent: function(iEventType, iParam1, iParam2) {
  886. if (2 == iEventType) {
  887. // 回放正常结束
  888. console.log("窗口" + iParam1 + "回放结束!");
  889. } else if (-1 == iEventType) {
  890. console.log("设备" + iParam1 + "网络错误!");
  891. } else if (3001 == iEventType) {
  892. clickStopRecord(g_szRecordType, iParam1);
  893. }
  894. },
  895. //2.登录摄像头
  896. cbInitPluginComplete: function() {
  897. const oLiveView = {
  898. iProtocol: 1, // protocol 1:http, 2:https
  899. szIP: ip, // protocol ip
  900. szPort: port, // protocol port
  901. szUsername: username, // device username
  902. szPassword: password, // device password
  903. iStreamType: 1, // stream 1:main stream 2:sub-stream 3:third stream 4:transcode stream
  904. iChannelID: 1, // channel no
  905. bZeroChannel: false, // zero channel
  906. };
  907. // var swidth=Number((that.width*Number(that.scale))).toFixed(2)
  908. // var sheight=Number((that.height*Number(that.scale))).toFixed(2)
  909. // that.swidth=swidth
  910. // that.sheight=sheight
  911. WebVideoCtrl.I_InsertOBJECTPlugin(id).then(
  912. () => {
  913. // setTimeout(function(){
  914. // WebVideoCtrl.I_Resize(swidth,sheight)
  915. // },300)
  916. WebVideoCtrl.I_Login(
  917. oLiveView.szIP,
  918. oLiveView.iProtocol,
  919. oLiveView.szPort,
  920. oLiveView.szUsername,
  921. oLiveView.szPassword, {
  922. timeout: 3000,
  923. async: false,
  924. success: function(xmlDoc) {
  925. console.log(" 登录成功!");
  926. let a = ip
  927. let b = port
  928. setTimeout(function() {
  929. //延迟方法
  930. setTimeout(function() {
  931. //调用预览摄像头这里可以循环创建
  932. that.clickStartRealPlay(a, b,1, 0, 1);
  933. // that.clickStartRealPlay(a, b, 1, 1,2);
  934. // that.clickStartRealPlay(a, b, 1, 2,3);
  935. // clickStartRealPlay(a,b, 1, 3, 4);
  936. // clickStartRealPlay(a,b, 1, 4, 5);
  937. // clickStartRealPlay(a,b, 1, 5, 6);
  938. // clickStartRealPlay(a,b, 1, 6, 7);
  939. // clickStartRealPlay(a,b, 1, 7, 8);
  940. }, 1000);
  941. setTimeout(function() {
  942. // 获取通道 (如果多个摄像头需要获取多个通道需要调用)
  943. // getChannelInfo(a);
  944. //获取端口 (在这里获取RTSP 端口号 预览时传入)
  945. getDevicePort(a);
  946. }, 10)
  947. }, 10);
  948. },
  949. error: function(oError) {
  950. console.log(" 登录失败!", oError);
  951. },
  952. }
  953. );
  954. // 检查插件是否最新
  955. WebVideoCtrl.I_CheckPluginVersion().then((bFlag) => {
  956. if (bFlag) {
  957. alert(
  958. "检测到新的插件版本,双击开发包目录里的HCWebSDKPlugin.exe升级!"
  959. );
  960. }
  961. });
  962. },
  963. () => {
  964. alert(
  965. "插件初始化失败,请确认是否已安装插件;如果未安装,请双击开发包目录里的HCWebSDKPlugin.exe安装!"
  966. );
  967. }
  968. );
  969. },
  970. });
  971. // 3.获取通道
  972. function getChannelInfo(a) {
  973. var szDeviceIdentify = a,
  974. oSel = null; //通道列表
  975. if (null == szDeviceIdentify) {
  976. return;
  977. }
  978. // 模拟通道 有
  979. WebVideoCtrl.I_GetAnalogChannelInfo(szDeviceIdentify, {
  980. success: function(xmlDoc) {
  981. var oChannels = $(xmlDoc).find("VideoInputChannel");
  982. $.each(oChannels, function(i) {
  983. var id = $(this).find("id").eq(0).text(),
  984. name = $(this).find("name").eq(0).text();
  985. if ("" == name) {
  986. name = "Camera " + (i < 9 ? "0" + (i + 1) : (i + 1));
  987. }
  988. // console.log(id + "通道id是")
  989. // console.log(name + "通道name是")
  990. });
  991. console.log(szDeviceIdentify + " 获取模拟通道成功!");
  992. },
  993. error: function(oError) {
  994. console.log(szDeviceIdentify + " 获取模拟通道失败!", oError.errorCode, oError.errorMsg);
  995. }
  996. });
  997. // 数字通道
  998. WebVideoCtrl.I_GetDigitalChannelInfo(szDeviceIdentify, {
  999. success: function(xmlDoc) {
  1000. var oChannels = $(xmlDoc).find("InputProxyChannelStatus");
  1001. $.each(oChannels, function(i) {
  1002. var id = $(this).find("id").eq(0).text(),
  1003. name = $(this).find("name").eq(0).text(),
  1004. online = $(this).find("online").eq(0).text();
  1005. if ("false" == online) { // 过滤禁用的数字通道
  1006. return true;
  1007. }
  1008. if ("" == name) {
  1009. name = "IPCamera " + (i < 9 ? "0" + (i + 1) : (i + 1));
  1010. }
  1011. });
  1012. console.log(szDeviceIdentify + " 获取数字通道成功!");
  1013. },
  1014. error: function(oError) {
  1015. console.log(szDeviceIdentify + " 获取数字通道失败!", oError.errorCode, oError.errorMsg);
  1016. }
  1017. });
  1018. // 零通道
  1019. WebVideoCtrl.I_GetZeroChannelInfo(szDeviceIdentify, {
  1020. success: function(xmlDoc) {
  1021. var oChannels = $(xmlDoc).find("ZeroVideoChannel");
  1022. $.each(oChannels, function(i) {
  1023. var id = $(this).find("id").eq(0).text(),
  1024. name = $(this).find("name").eq(0).text();
  1025. if ("" == name) {
  1026. name = "Zero Channel " + (i < 9 ? "0" + (i + 1) : (i + 1));
  1027. }
  1028. if ("true" == $(this).find("enabled").eq(0).text()) { // 过滤禁用的零通道
  1029. }
  1030. });
  1031. console.log(szDeviceIdentify + " 获取零通道成功!");
  1032. },
  1033. error: function(oError) {
  1034. console.log(szDeviceIdentify + " 获取零通道失败!", oError.errorCode, oError.errorMsg);
  1035. }
  1036. });
  1037. };
  1038. //4.获取端口
  1039. function getDevicePort(a) {
  1040. var szDeviceIdentify = a;
  1041. if (null == szDeviceIdentify) {
  1042. return;
  1043. }
  1044. WebVideoCtrl.I_GetDevicePort(szDeviceIdentify).then((oPort) => {
  1045. // console.log(oPort.iDevicePort + "iDevicePort的值是")
  1046. // console.log(oPort.iRtspPort + "iRtspPort的值是")
  1047. console.log(szDeviceIdentify + " 获取端口成功!");
  1048. iRtspPort = oPort.iRtspPort
  1049. that.iRtspPort = iRtspPort
  1050. }, (oError) => {
  1051. var szInfo = "获取端口失败!";
  1052. console.log(szDeviceIdentify + szInfo, oError.errorCode, oError.errorMsg);
  1053. });
  1054. };
  1055. },
  1056. // 5.开始预览
  1057. clickStartRealPlay(szIP, szPort, iStreamType, iWndIndex, iChannelID) {
  1058. var that=this;
  1059. var oWndInfo = WebVideoCtrl.I_GetWindowStatus(this.g_iWndIndex),
  1060. szDeviceIdentify = szIP + "_" + szPort, //ip
  1061. iChannelID = iChannelID,
  1062. bZeroChannel = false,
  1063. iPort = this.iRtspPort,
  1064. szInfo = "";
  1065. iStreamType = iStreamType;
  1066. if (null == szDeviceIdentify) {
  1067. return null;
  1068. }
  1069. this.szDeviceIdentify = szDeviceIdentify;
  1070. var startRealPlay = function() {
  1071. WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, {
  1072. iStreamType: iStreamType,
  1073. iChannelID: iChannelID,
  1074. bZeroChannel: bZeroChannel,
  1075. iWndIndex: iWndIndex, //要播放的窗口
  1076. iPort: iPort, //如果多个摄像头需要必填 (RTSP 端口号)
  1077. success: function() {
  1078. szInfo = "开始预览窗口" + iWndIndex + "成功!";
  1079. console.log(szDeviceIdentify + " " + szInfo);
  1080. },
  1081. error: function(oError) {
  1082. console.log(szDeviceIdentify + " 开始预览窗口" + iWndIndex + "失败!", oError
  1083. .errorCode, oError.errorMsg);
  1084. }
  1085. });
  1086. };
  1087. if (oWndInfo != null) { // 已经在播放了,先停止
  1088. WebVideoCtrl.I_Stop({
  1089. success: function() {
  1090. startRealPlay();
  1091. }
  1092. });
  1093. } else {
  1094. startRealPlay();
  1095. }
  1096. },
  1097. xiazag(){
  1098. var loadUrl = 'http://172.28.195.154:15010/prod-api/profile/HCWebSDKPluginsUserSetup.exe'
  1099. window.open(loadUrl, );
  1100. }
  1101. }
  1102. };
  1103. </script>
  1104. <style lang="scss">
  1105. .isjses{
  1106. .el-tabs--left .el-tabs__nav-wrap.is-left::after{
  1107. width:6px;
  1108. }
  1109. .el-tabs--left .el-tabs__active-bar.is-left,{
  1110. width:6px;
  1111. }
  1112. }
  1113. .ingaqe{
  1114. .el-input--medium{
  1115. width:100%;
  1116. }
  1117. }
  1118. .nhgrls{
  1119. .el-dialog__body{
  1120. padding: 0;
  1121. }
  1122. }
  1123. .hyr{
  1124. span{
  1125. text-decoration:underline;
  1126. }
  1127. }
  1128. </style>
  1129. <style scoped lang="scss">
  1130. .nghwgq{
  1131. display: flex;
  1132. flex-direction: column;
  1133. justify-content: center;
  1134. align-items: center;
  1135. margin-top: 90px;
  1136. div{
  1137. color:#aaa;
  1138. }
  1139. }
  1140. .ihgswq{
  1141. // width:100%;
  1142. // overflow-x: hidden;
  1143. // margin-top: 30px;
  1144. }
  1145. .fijge{
  1146. // width: 110%;
  1147. display: flex;
  1148. display: -webkit-flex;
  1149. justify-content: space-between;
  1150. .shotw{
  1151. position: relative;
  1152. // width:32%;
  1153. width: 238px;
  1154. height: 140px;
  1155. margin-left: 0;
  1156. margin-right: 20px;
  1157. margin-bottom: 15px;
  1158. img{
  1159. height: 100%;
  1160. cursor:pointer;
  1161. }
  1162. p{
  1163. // bottom:-10px;
  1164. margin: 0;
  1165. font-weight: bold;
  1166. font-size: 16px;
  1167. padding: 5px 10px;
  1168. cursor:pointer;
  1169. }
  1170. .iges{
  1171. position: absolute;
  1172. top:50%;
  1173. left:50%;
  1174. width:30px;
  1175. height: 30px;
  1176. transform: translate(-50%,-50%);
  1177. cursor:pointer;
  1178. }
  1179. }
  1180. }
  1181. .nhgwesvq{
  1182. width:1610px !important;
  1183. }
  1184. .shotw{
  1185. position: relative;
  1186. margin-left: -20px;
  1187. margin-right: -20px;
  1188. img{
  1189. width:100%;
  1190. height: 80vh;
  1191. }
  1192. p{
  1193. position: absolute;
  1194. bottom: 0;
  1195. left:0;
  1196. background-color: rgba(0, 0, 0, .5);
  1197. width: 100%;
  1198. padding: 13px 5px;
  1199. color:#fff;
  1200. font-weight: bold;
  1201. font-size: 18px;
  1202. }
  1203. .p{
  1204. top:0px;
  1205. height: 60px;
  1206. margin: 0;
  1207. padding-left: 20px;
  1208. }
  1209. }
  1210. .ksfpo{
  1211. background-color: #3464EB;
  1212. padding: 6px 12px;
  1213. border-radius: 4px ;
  1214. color:#fff;
  1215. cursor:pointer;
  1216. }
  1217. .ksfpok{
  1218. background-color: #FFFFFF;
  1219. padding: 5px 11px;
  1220. border-radius: 4px;
  1221. color:#3464EB;
  1222. border: 1px solid #3464EB;
  1223. margin-left: 10px;
  1224. cursor:pointer;
  1225. }
  1226. .ksfpofg{
  1227. background-color: #75DB75;
  1228. padding: 5px 11px;
  1229. border-radius: 4px;
  1230. color:#FFFFFF;
  1231. border: 1px solid #75DB75;
  1232. margin-left: 10px;
  1233. cursor:pointer;
  1234. }
  1235. .iuer{
  1236. display: flex;
  1237. justify-content: space-between;
  1238. align-items: center;
  1239. .ite{
  1240. display: flex;
  1241. justify-content: space-between;
  1242. align-items: center;
  1243. p{
  1244. cursor:pointer;
  1245. margin: 0;
  1246. font-size: 15px;
  1247. font-family: PingFang SC;
  1248. font-weight: 500;
  1249. color:#666666;
  1250. padding: 4px 12px;
  1251. background: #Fff;
  1252. border-radius: 4px;
  1253. margin-right: 20px;
  1254. position: relative;
  1255. }
  1256. .actt{
  1257. background: #fff;
  1258. // border-bottom: 3px solid #5974E0;
  1259. // border-radius: 0;
  1260. // border-bottom-right-radius: 4px;
  1261. color: #5974E0;
  1262. }
  1263. .actt{
  1264. &::after {
  1265. content: "";
  1266. width: 40%;
  1267. height: 5px;
  1268. border-radius: 3px;
  1269. transform: translate(-50%);
  1270. background-color: #5974E0;
  1271. position: absolute;
  1272. left: 50%;
  1273. bottom:-3px;
  1274. }
  1275. }
  1276. }
  1277. }
  1278. .lqw{
  1279. padding: 0 10px;
  1280. margin: 0;
  1281. margin-bottom: 20px;
  1282. }
  1283. .nhgel{
  1284. height: 170px;
  1285. background-color: #313b61;
  1286. width: 100%;
  1287. position: absolute;
  1288. top:0;
  1289. left:0;
  1290. z-index: 0;
  1291. }
  1292. .app-container{
  1293. background-color: #f3f4f6;
  1294. padding-top: 10px;
  1295. height: 180vh;
  1296. }
  1297. .ntgs{
  1298. position: relative;
  1299. // background-color: #fff;
  1300. padding: 5px;
  1301. // border-radius: 5px;
  1302. padding-top: 10px;
  1303. padding: 10px 20px;
  1304. .pagination-container{
  1305. height: 50px;
  1306. }
  1307. }
  1308. .nghfs{
  1309. position: relative;
  1310. background-color: #fff;
  1311. padding-top: 18px !important;
  1312. padding: 5px;
  1313. // border-radius: 5px;
  1314. // margin-bottom: 20px;
  1315. }
  1316. .ksf{
  1317. img{
  1318. width:100%;
  1319. height: 100%;
  1320. }
  1321. }
  1322. .ingwfaq{
  1323. font-weight: bold;
  1324. font-size: 16px;
  1325. }
  1326. .dflex{display: flex;}
  1327. .dflext{display: flex;align-items: flex-start;}
  1328. .drawings-list{width: 100%;flex: 0 0 auto;padding-left: 10px;line-height:36px ;
  1329. .delimg{width: 15px;height: 15px;margin-left: 5px;}
  1330. .txt{font-size: 12px;padding-left: 5px;flex: 1;}
  1331. .tflex{display: flex;align-items: center;}
  1332. }
  1333. .disbtn{display: flex;align-items: center;flex: 0 0 auto;min-height: 34px;cursor: pointer;
  1334. img{width: 14px;height: 14px;margin-right: 10px;}
  1335. font-weight: 500;
  1336. font-size: 14px;
  1337. color: #444444;
  1338. }
  1339. .anche{
  1340. background: #E7F1EE !important;
  1341. border-radius: 4px !important;
  1342. }
  1343. </style>