info.vue 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716
  1. <template>
  2. <div class="meeting">
  3. <div style="display: flex;flex-direction: row;justify-content: space-between;">
  4. <div class="display-row display-center">
  5. <el-image :src="logo" fit="contain" style="width: 20px;height: 20px;" />
  6. <div class="title">浪潮智屏投控-会议管理</div>
  7. </div>
  8. <div class="display-row display-center" style="margin-right: 15px;" @click="closePage">
  9. <el-image :src="logoExit" fit="contain" class="icon" />
  10. <div class="text-fontsize-14" style="margin-left: 4px;">退出会议</div>
  11. </div>
  12. </div>
  13. <div class="display-row" style="display: flex;align-items: center;margin-top: 27px;">
  14. <div class="text-fontsize-14" style="font-weight: bold;;">{{ form.title }}</div>
  15. <el-image :src="iconAddress" fit="contaion" class="icon" style="margin-left: 15px;" />
  16. <div class="text-fontsize-14" style="margin-left: 4px;">地点:</div>
  17. <div class="text-fontsize-14" style="margin-left: 4px;">{{form.address}}</div>
  18. <el-image :src="iconHost" fit="contaion" class="icon" style="margin-left: 15px;" />
  19. <div class="text-fontsize-14" style="margin-left: 4px;">主持:</div>
  20. <div class="text-fontsize-14" style="margin-left: 4px;">{{form.host}}</div>
  21. <el-image :src="iconOrganization" fit="contaion" class="icon" style="margin-left: 15px;" />
  22. <div class="text-fontsize-14" style="margin-left: 4px;">发起组织:</div>
  23. <div class="text-fontsize-14" style="margin-left: 4px;">{{form.fromOrg}}</div>
  24. <el-image :src="iconTime" fit="contaion" class="icon" style="margin-left: 15px;" />
  25. <div class="text-fontsize-14" style="margin-left: 4px;">时间:</div>
  26. <div class="text-fontsize-14" style="margin-left: 4px;">{{form.beginTime}} - {{form.endTime}}</div>
  27. </div>
  28. <div class="display-row"
  29. style="width: 85%; display: flex;align-items: center;justify-content: space-between; margin-top: 15px;">
  30. <div class="display-row" style="display: flex;align-items: center;">
  31. <div class="text-fontsize-14">请选择会议设备</div>
  32. <el-select v-model="deviceId" placeholder="请选择会议设备" style="margin-left: 8px;" :popper-append-to-body="false" class="elselect">
  33. <el-option v-for="device in deviceList" :label="device.deviceName" :value="device.id" />
  34. </el-select>
  35. </div>
  36. <!-- 开始播放后显示 -->
  37. <div v-if="selectedFileIndex>=0" class="display-row" style="display: flex;align-items: center;">
  38. <div class="text-fontsize-14">党组织建设工作汇报.pptx</div>
  39. <div class="text-fontsize-14" style="margin-left: 15px;">缩放比例</div>
  40. <el-select v-model="scaleId" placeholder="请选择" style="margin-left: 8px;width: 90px;"
  41. :popper-append-to-body="false" @change="scaleChange">
  42. <el-option v-for="scale in scaleList" :label="scale.label" :value="scale.value" />
  43. </el-select>
  44. <div class="text-fontsize-14" style="margin-left: 15px;">移动距离</div>
  45. <el-select v-model="moveId" placeholder="请选择" style="margin-left: 8px;width: 90px;"
  46. :popper-append-to-body="false">
  47. <el-option v-for="move in moveList" :label="move.label" :value="move.value" />
  48. </el-select>
  49. <el-button class="btn no-active" style="margin-left: 18px;" @click="moveUp">上移</el-button>
  50. <el-button class="btn no-active" style="margin-left: 18px;" @click="moveDown">下移</el-button>
  51. <el-button class="btn no-active" style="margin-left: 18px;" @click="lastPage">上一页</el-button>
  52. <el-button class="btn no-active" style="margin-left: 18px;" @click="nextPage">下一页</el-button>
  53. </div>
  54. </div>
  55. <div class="display-row" style="margin-top: 16px;height: 83vh">
  56. <div style="width: 85%;height: 83vh;" class="screen_nocontent display-center">
  57. <div v-if="fileType == 1 && null == pageSrc" class="display-cloumn display-center">
  58. <el-image :src="iconScreen" class="icon-40"></el-image>
  59. <div class="text-fontsize-18" style="margin-top: 8px;">此处展示投屏画面</div>
  60. </div>
  61. <div v-else-if="fileType == 2 && null == material" class="display-cloumn display-center">
  62. <el-image :src="iconScreen" class="icon-40"></el-image>
  63. <div class="text-fontsize-18" style="margin-top: 8px;">此处展示投屏画面</div>
  64. </div>
  65. <div v-else style="height: 83vh;width: 100%;overflow: hidden;" class="display-center">
  66. <iframe v-if="fileType == 2" :src="material" ref="iframe" style="width: 100%; height: 83vh;"></iframe>
  67. <el-image v-else :src="pageSrc.fileUrl" @load="handleImageLoad"
  68. :style="{ height: imageHeight +'%',transform: 'translateY(' + imageOffset + 'px)'}" />
  69. <!-- <div v-else class="image-container" @mousedown="startMove" @mousemove="doMove" @mouseup="endMove"
  70. style="height: 97%;" :style="{ transform: `scale(${scale}) translate(${position.x}px, ${position.y}px)` }">
  71. <el-image :src="pageSrc.fileUrl" />
  72. </div> -->
  73. </div>
  74. </div>
  75. <div style="width: 15%;height: 100%;" class="display-cloumn">
  76. <!-- 会议资料 -->
  77. <div class="display-cloumn" style="height: 38%;padding-bottom: 5px;">
  78. <div class="display-row"
  79. style="display: flex;justify-content: space-between;align-items: center;margin: 0 16px;">
  80. <div class="display-row" style="display: flex;align-items: center;">
  81. <div class="text-fontsize-18">会议资料</div>
  82. <el-image :src="iconFresh" fit="contaion" class="icon" @click="getMeetingInfo()"
  83. style="margin-left: 8px;"></el-image>
  84. </div>
  85. <div class="display-row">
  86. <el-image :src="iconStartPlay" class="icon-40" @click="beginPlay()">开始播放</el-image>
  87. <el-image :src="iconStopPlay" class="icon-40" style="margin-left:10px" @click="endPlay()">结束播放</el-image>
  88. </div>
  89. </div>
  90. <div style="margin-top: 16px;height:240px;overflow-y: auto" class="no-scrollbar">
  91. <div v-for="(item,index) in fileList" @click="selectFileItem(index)">
  92. <div class="fileItem text-fontsize-14 single-line"
  93. :class="{ 'is-selected': selectedFileIndex === index }">{{item.fileName}}</div>
  94. </div>
  95. </div>
  96. </div>
  97. <div class="line" />
  98. <!-- 图片抓拍 -->
  99. <div class="display-cloumn" style="height: 21%;padding: 16px;">
  100. <div class="display-row" style="display: flex;justify-content: space-between;align-items: center;">
  101. <div class="display-row" style="display: flex;align-items: center;">
  102. <div class="text-fontsize-18">图片抓拍</div>
  103. <el-image :src="iconFresh" class="icon" style="margin-left: 8px;" @click="refreshPhoto" />
  104. </div>
  105. <el-button class="more" @click="dialogPhotoVisible = true">更多</el-button>
  106. </div>
  107. <div class="display-cloumn" style="margin-top:10px;height: 75%;">
  108. <div class="display-row" style="display: flex;justify-content: space-between;">
  109. <el-image v-if="firstPhoto !=null" style="width: 157px;height: 90px;" :src="firstPhoto.picPath"
  110. :preview-src-list="firstPhotoList" />
  111. <el-image v-else :src="imgEmpty" style="width: 157px;height: 90px;" />
  112. <div class="display-cloumn" style="display: flex;justify-content: space-between;">
  113. <el-image :src="iconPhoto" class="icon-40" style="margin-left: 8px;" @click="takePhoto" />
  114. <el-image v-if="firstPhoto!=null" :src="iconDelete" class="icon-40" style="margin-left: 8px;"
  115. @click="deletePhoto([0])" />
  116. </div>
  117. </div>
  118. <div v-if="firstPhoto!=null" style="width: 157px;margin-top: 5px;" class="display-center text-fontsize-14">
  119. {{firstPhoto.createTime}}
  120. </div>
  121. <div v-else style="width: 157px;margin-top: 5px;" class="display-center text-fontsize-14">暂无图片</div>
  122. </div>
  123. </div>
  124. <div class="line" />
  125. <!-- 人脸签到 -->
  126. <div class="display-cloumn" style="height: 21%;padding: 16px;">
  127. <div class="display-row" style="display: flex;justify-content: space-between;align-items: center;">
  128. <div class="display-row" style="display: flex;align-items: center;">
  129. <div class="text-fontsize-18">人脸签到</div>
  130. <el-image :src="iconFresh" class="icon" style="margin-left: 8px;" @click="refreshPhotoSign" />
  131. </div>
  132. <el-button class="more" @click="dialogFaceSignVisible = true">更多</el-button>
  133. </div>
  134. <div class="display-cloumn" style="height: 75%;margin-top:10px">
  135. <div class="display-row" style="display: flex;justify-content: space-between;">
  136. <div v-if="faceSignUrl && faceSignUrl.length>0" class="display-cloumn" style="width: 157px;">
  137. <el-image style="width: 157px;height: 90px;" :src="faceSignUrl" :preview-src-list="faceSignList" />
  138. <div style="width: 157px;margin-top: 5px;" class="display-center text-fontsize-14">
  139. {{faceSign.createTime}}
  140. </div>
  141. </div>
  142. <div v-else class="display-cloumn" style="width: 157px;">
  143. <el-image :src="imgEmpty" style="width: 157px;height: 90px;" />
  144. <div style="width: 157px;margin-top: 5px;" class="display-center text-fontsize-14">暂无图片
  145. </div>
  146. </div>
  147. <div class="display-cloumn" style="display: flex;justify-content: space-between;align-items: end;">
  148. <el-image :src="iconPhoto" class="icon-40" style="margin-left: 8px;" @click="photoSign" />
  149. <div v-if="faceSignUrl && faceSignUrl.length>0" class="display-cloumn"
  150. style="display: flex;align-items: end;">
  151. <div class="display-row"
  152. style="margin-bottom:8px ;display: flex;align-items: center;justify-content: center;">
  153. <div class="text-fontsize-14">本次</div>
  154. <div class="text-fontsize-14" style="color: #FFE59E;">+{{faceSign.newAddNum}}</div>
  155. </div>
  156. <progress :value="signedNum" :max="attendanceList.length"></progress>
  157. <div class="display-row display-center" style="margin-top:8px ;">
  158. <div class="text-fontsize-14" style="color: #FFE59E;">{{signedNum}}</div>
  159. <div class="text-fontsize-14">/{{attendanceList.length}} 已签到</div>
  160. </div>
  161. </div>
  162. </div>
  163. </div>
  164. </div>
  165. </div>
  166. <div class="line" />
  167. <!-- 会议纪要 -->
  168. <div class="display-cloumn" style="height: 20%;padding: 16px;">
  169. <div class="display-row" style="display: flex;justify-content: space-between;align-items: center;">
  170. <div class="display-row" style="display: flex;align-items: center;">
  171. <div class="text-fontsize-18">会议纪要</div>
  172. <el-image :src="iconFresh" class="icon" style="margin-left: 8px;" />
  173. </div>
  174. <el-button class="more" @click="dialogMeetVisible = true">更多</el-button>
  175. </div>
  176. <div class="display-row" style="margin-top: 10px;">
  177. <div style="width: 70%;overflow-y: auto;height: 120px;" class="no-scrollbar">
  178. <div v-for="(item, index) in audioList">
  179. <div class="text-fontsize-14 single-line" style="padding:10px 0 ;">{{item.fileName}}</div>
  180. </div>
  181. </div>
  182. <div v-if="timerRunning == false" class="display-cloumn display-center" style="width: 30%;">
  183. <el-image :src="iconStartRecord" class="icon-40" @click="startTimer" />
  184. <div class="text-fontsize-16" style="margin-top:12px ;">录音</div>
  185. </div>
  186. <div v-else class="display-cloumn display-center" style="width: 30%;">
  187. <el-image :src="iconStopRecord" class="icon-40" @click="pauseTimer" />
  188. <div class="text-fontsize-16" style="margin-top:12px ;">{{formatTime}}</div>
  189. </div>
  190. </div>
  191. </div>
  192. </div>
  193. </div>
  194. <!-- 图片抓拍 -更多弹框 -->
  195. <el-dialog title="图片抓拍" :visible.sync="dialogPhotoVisible" center>
  196. <span>
  197. <div class="display-cloumn">
  198. <!-- <div class="line-grey" /> -->
  199. <div style="display: flex;flex-wrap: wrap;overflow: auto;margin-left:5px;">
  200. <div v-for="(item, index) in photoList" :key="index" class="imageDiv">
  201. <div class="display-cloumn" :style="{ backgroundColor: item.isSelected ? '#FFF3F3' : 'white' }">
  202. <div style="margin-left: 10px;">
  203. <input type="checkbox" align="left" :value="index" v-model="selectedItems">
  204. </div>
  205. <el-image style="width: 206px;height: 114px;margin: 5px" :src="item.picPath"
  206. :preview-src-list="photoPreviewList" />
  207. <div class="text-fontsize-14 display-center" style="margin-top:5px;color:#000000;width: 208px;">
  208. {{item.createTime}}
  209. </div>
  210. </div>
  211. </div>
  212. </div>
  213. </div>
  214. </span>
  215. <span slot="footer" class="display-row" style="display: flex;align-items: center;justify-content: space-between;">
  216. <div></div>
  217. <div class="display-row display-center" style="margin-left: 80px;">
  218. <div class="display-cloumn display-center" style="margin-left:24px">
  219. <el-image :src="iconPhotoGrey" class="icon-40" @click="takePhoto" />
  220. <div class="text-fontsize-14" style="margin-top: 5px;color: #545454;">拍照</div>
  221. </div>
  222. <div class="display-cloumn display-center" style="margin-left:24px">
  223. <el-image :src="iconFreshGrey" class="icon-40" @click="refreshPhoto" />
  224. <div class="text-fontsize-14" style="margin-top: 5px;color: #545454;">刷新列表</div>
  225. </div>
  226. </div>
  227. <div>
  228. <el-button @click="dialogPhotoVisible = false">取 消</el-button>
  229. <el-button type="primary" @click="deleteDialogPhoto">删 除</el-button>
  230. </div>
  231. </span>
  232. </el-dialog>
  233. <!-- 人脸签到 - 更多弹框 -->
  234. <el-dialog title="人脸签到" :visible.sync="dialogFaceSignVisible" center>
  235. <div class="display-cloumn">
  236. <div class="line-grey" />
  237. <div class="display-row">
  238. <div class="display-cloumn" style="width: 37%;height: calc(70vh - 51px);padding: 16px 0px 24px 20px;">
  239. <div class="text-fontsize-16" style="color: #545454;margin-left: 4px;">人员列表</div>
  240. <div style="height: 93%;margin-top: 10px;">
  241. <el-table v-loading="loading" class="no-border" :data="attendanceList" height="100%" row-key="id">
  242. <el-table-column label="姓名" align="left" prop="memberName" width="100" />
  243. <el-table-column label="出勤情况" align="left" prop="attendanceStatus" width="100">
  244. <template slot-scope="scope">
  245. <!-- <dict-tag :options="dict.type.sys_attendance_type" :value="scope.row.attendanceStatus" /> -->
  246. <div v-if="scope.row.attendanceStatus == 0" style="color:#F53F3F ;">未签到</div>
  247. <div v-else>已签到</div>
  248. </template>
  249. </el-table-column>
  250. <el-table-column label="签到时间" align="left" prop="signTime" />
  251. </el-table>
  252. </div>
  253. </div>
  254. <div class="line-grey-column" />
  255. <div class="display-cloumn" style="width: 62%;height: calc(70vh - 51px);padding: 16px;">
  256. <div class="text-fontsize-16" style="color: #545454;margin-bottom: 10px;">人脸签到</div>
  257. <el-image v-if="faceSignUrl && faceSignUrl.length>0" style="width: 100%;height:65%" :src="faceSignUrl" />
  258. <el-image v-else style="width: 100%;height:65%" :src="dialogimgEmpty"></el-image>
  259. <div class="display-row display-center" style="margin-top: 32px;">
  260. <div class="display-cloumn display-center">
  261. <el-image :src="iconPhotoGrey" class="icon-40" @click="photoSign" />
  262. <div class="text-fontsize-14" style="margin-top: 5px;color: #545454;">拍照</div>
  263. </div>
  264. <div class="display-cloumn display-center" style="margin-left:24px">
  265. <el-image :src="iconFreshGrey" class="icon-40" @click="refreshPhotoSign" />
  266. <div class="text-fontsize-14" style="margin-top: 5px;color: #545454;">刷新列表</div>
  267. </div>
  268. </div>
  269. <div class="display-row display-center" style="margin-top: 32px;">
  270. <div class="text-fontsize-14" style="color: #545454;">本次</div>
  271. <div v-if="faceSign.newAddNum" class="text-fontsize-14" style="color: #FF5455;">+{{faceSign.newAddNum}}
  272. </div>
  273. <div v-else class="text-fontsize-14" style="color: #FF5455;">+0</div>
  274. <el-progress :stroke-width="8" :percentage="percentage" :color="customColor" :show-text="false"
  275. style="height: 8px;width: 104px;margin-left: 16px;" :define-back-color="customColor2"></el-progress>
  276. <!-- <progress value="14" max="18" style="margin-left: 16px;" class="dialogprogress"></progress> -->
  277. <div class="text-fontsize-14" style="color: #FF5455;margin-left: 16px;">{{signedNum}}</div>
  278. <div class="text-fontsize-14" style="color: #545454;">/{{attendanceList.length}} 已签到</div>
  279. </div>
  280. </div>
  281. </div>
  282. </div>
  283. </el-dialog>
  284. <!-- 会议纪要 - 更多弹框 -->
  285. <el-dialog title="会议纪要" :visible.sync="dialogMeetVisible" center>
  286. <div class="display-cloumn">
  287. <div class="line-grey" />
  288. <div class="display-row">
  289. <div class="display-cloumn" style="width: 43%;height: calc(70vh - 51px);padding: 16px 0px 24px 20px;">
  290. <div class="text-fontsize-16" style="color: #545454;margin-left:4px">会议录音</div>
  291. <div style="height: 93%;margin-top: 10px;" class="display-cloumn">
  292. <el-table v-loading="loading" class="no-border" :data="audioList" height="83%" row-key="id"
  293. @row-click="showAudioTxt" @selection-change="handleSelectionChange">
  294. <el-table-column label="序号" align="left" prop="sort" width="50" />
  295. <el-table-column label="文件名称" align="left" prop="fileName" :show-overflow-tooltip="true" />
  296. <el-table-column label="文本准换" align="left" prop="isTranslate" width="80">
  297. <template slot-scope="scope">
  298. <dict-tag :options="dict.type.sys_asr_status" :value="scope.row.isTranslate" />
  299. </template>
  300. </el-table-column>
  301. <el-table-column label="创建时间" align="left" prop="createTime" width="150" />
  302. </el-table>
  303. <div style="height: 17%;margin-top:10px" class="display-row display-center">
  304. <div class="display-cloumn display-center">
  305. <el-image :src="iconFreshGrey" class="icon-40" @click="refreshAudio" />
  306. <div class="text-fontsize-14" style="color: #545454;margin-top: 5px;">刷新列表</div>
  307. </div>
  308. <div v-if="timerRunning == false" class="display-cloumn display-center" style="margin-left:32px">
  309. <el-image :src="iconStartRecordRed" class="icon-40" @click="startTimer" />
  310. <div class="text-fontsize-14" style="color: #545454;margin-top: 5px;">录音</div>
  311. </div>
  312. <div v-else class="display-cloumn display-center" style="margin-left:32px">
  313. <el-image :src="iconStopRecordRed" class="icon-40" @click="pauseTimer" />
  314. <div class="text-fontsize-14" style="color: #545454;margin-top: 5px;">{{ formatTime }}</div>
  315. </div>
  316. <div class="display-cloumn display-center" style="margin-left:32px">
  317. <el-image :src="iconYjsc" class="icon-40" @click="summaryGenerate" />
  318. <div class="text-fontsize-14" style="color: #545454;margin-top: 5px;">生成会议纪要</div>
  319. </div>
  320. </div>
  321. </div>
  322. </div>
  323. <div class="line-grey-column" />
  324. <div class="display-cloumn" style="width: 57%;height: calc(70vh - 51px);padding: 16px;">
  325. <div class="text-fontsize-16" style="color: #545454;margin-bottom: 10px;">录音内容</div>
  326. <el-input resize="none" v-model="audioTxt" style="margin-left: 10px" type="textarea"
  327. :readonly="audioReadOnly" :rows="21" placeholder="请输入内容" />
  328. <div style="margin-top: 35px;display: flex;justify-content: center;align-items: center;">
  329. <el-button type="primary" @click="audioTxtEdit">文本编辑</el-button>
  330. <el-button type="primary" @click="audioTxtSave">文本保存</el-button>
  331. </div>
  332. </div>
  333. </div>
  334. </div>
  335. </el-dialog>
  336. </div>
  337. <!-- <div class="appNew-container">
  338. <el-card shadow="never" class="" style="">
  339. <div style="overflow: hidden">
  340. <div style="font-weight: bolder;float: left">
  341. {{ form.title }}
  342. </div>
  343. <div style="float: right">
  344. 请选择会议设备:
  345. <el-select v-model="deviceId" placeholder="请选择会议设备" style="">
  346. <el-option v-for="device in deviceList" :key="device.id" :label="device.deviceName"
  347. :value="device.id" />
  348. </el-select>
  349. </div>
  350. </div>
  351. </el-card>
  352. <el-card shadow="never" class="" style="">
  353. <el-tabs type="border-card" style="height: calc(100vh - 150px)">
  354. <el-tab-pane label="会议文件">
  355. <div style="display: flex;justify-content: center">
  356. <div style="width: 30%;">
  357. <el-table v-loading="loading" :data="fileList" height="calc(100vh - 220px)" @selection-change="handleSelectionChange">
  358. <el-table-column type="selection" width="55" align="center" />
  359. <el-table-column prop="fileName" label="文件名" :show-overflow-tooltip="true"/>
  360. </el-table>
  361. </div>
  362. <div style="width: 70%;border-left: 1px solid #e6e6e6;">
  363. <div v-if="null == pageSrc" style="height: calc(100vh - 300px);">
  364. <el-empty description=""></el-empty>
  365. </div>
  366. <div v-else style="height: calc(100vh - 300px);display: flex;justify-content: center;align-items: center;" >
  367. <el-image :src="pageSrc.fileUrl" style="height: 100%"/>
  368. </div>
  369. <div style="height: 10%;display: flex;justify-content: center;align-items: center;">
  370. <el-button type="primary" :disabled="single" @click="showFile">立即播放</el-button>
  371. <el-button type="primary" @click="lastPage">上一页</el-button>
  372. <el-button type="primary" @click="nextPage">下一页</el-button>
  373. <el-button type="warning" :disabled="single" @click="endShowFile">结束播放</el-button>
  374. </div>
  375. </div>
  376. </div>
  377. </el-tab-pane>
  378. <el-tab-pane label="资料链接">
  379. <div style="display: flex;justify-content: center">
  380. <div style="width: 30%;height: calc(100vh - 220px)">
  381. <div v-for="(item,index) in materialOptions">
  382. <div style="display: flex;flex-direction: column;justify-content: center;">
  383. <span>
  384. <span style="font-weight: bolder;">链接地址:</span>
  385. <span style="word-break: break-all;word-wrap: break-word">{{ item }}</span>
  386. </span>
  387. <span style="margin-right: 10px;margin-top: 10px;margin-bottom: 10px">
  388. <el-button type="primary" @click="showUrl(item)">开始播放</el-button>
  389. <el-button type="warning" @click="endShowUrl(item)">结束播放</el-button>
  390. </span>
  391. </div>
  392. </div>
  393. </div>
  394. <div v-if="material == null" style="width: 70%;border-left: 1px solid #e6e6e6;">
  395. <el-empty description=""></el-empty>
  396. </div>
  397. <div v-else style="width: 70%;border-left: 1px solid #e6e6e6;">
  398. <iframe :src="material" style="width: 100%;height: calc(100vh - 220px);border: 0;"></iframe>
  399. </div>
  400. </div>
  401. </el-tab-pane>
  402. <el-tab-pane label="图片抓拍">
  403. <div style="height: calc(100vh - 260px);display: flex;flex-wrap: wrap;overflow: auto">
  404. <div v-for="(item, index) in this.photoList" :key="index" class="imageDiv">
  405. <div>
  406. <el-image style="width: 320px;height: 180px;margin: 5px" :src="item"/>
  407. </div>
  408. <div style="margin: 5px;display: flex;justify-content: center;align-items: center;">
  409. <el-button type="warning" @click="deletePhoto(index)">删除图片</el-button>
  410. </div>
  411. </div>
  412. </div>
  413. <div style="margin-top: 5px;display: flex;justify-content: center;align-items: center;">
  414. <el-button @click="refreshPhoto" type="primary" >刷新</el-button>
  415. <el-button @click="takePhoto" type="primary" >拍照</el-button>
  416. <el-button @click="savePhoto" type="primary" >保存</el-button>
  417. </div>
  418. </el-tab-pane>
  419. <el-tab-pane label="人脸签到">
  420. <div style="display: flex;justify-content: center">
  421. <div style="width: 30%;height: calc(100vh - 220px)">
  422. <div style="font-size: medium;margin-bottom: 10px">人员列表</div>
  423. <div style="height: 85%;">
  424. <el-table v-loading="loading" :data="attendanceList" height="calc(100vh - 250px)" row-key="id">
  425. <el-table-column label="姓名" align="left" prop="memberName" />
  426. <el-table-column label="出勤情况" align="left" prop="attendanceStatus">
  427. <template slot-scope="scope">
  428. <dict-tag :options="dict.type.sys_attendance_type" :value="scope.row.attendanceStatus"/>
  429. </template>
  430. </el-table-column>
  431. <el-table-column label="签到时间" align="left" prop="signTime" />
  432. </el-table>
  433. </div>
  434. </div>
  435. <div style="width: 70%;border-left: 1px solid #e6e6e6;">
  436. <div style="font-size: medium;margin-bottom: 10px;margin-left: 20px">人脸签到</div>
  437. <div v-if="null == faceSignUrl" style="height: calc(100vh - 350px);">
  438. <el-empty description=""></el-empty>
  439. </div>
  440. <div v-else style="height: calc(100vh - 350px);display: flex;justify-content: center;align-items: center;" >
  441. <div style="width: 100%; height: calc(100vh - 350px)">
  442. <el-image style="width: 100%;height: 100%;margin: 5px" :src="faceSignUrl"/>
  443. </div>
  444. </div>
  445. <div style="height: 10%;display: flex;justify-content: center;align-items: center;">
  446. <el-button type="primary" @click="photoSign">拍照</el-button>
  447. <el-button type="primary" @click="refreshPhotoSign">刷新</el-button>
  448. </div>
  449. </div>
  450. </div>
  451. </el-tab-pane>
  452. <el-tab-pane label="会议纪要">
  453. <div style="display: flex;justify-content: center">
  454. <div style="width: 30%;height: calc(100vh - 220px)">
  455. <div style="font-size: medium;margin-bottom: 10px">会议录音</div>
  456. <div style="height: 85%;">
  457. <el-table v-loading="loading" :data="audioList" height="100%" row-key="id" @row-click="showAudioTxt" @selection-change="handleSelectionChange">
  458. <el-table-column label="序号" align="center" prop="sort" width="50" />
  459. <el-table-column label="文件名称" align="left" prop="fileName" :show-overflow-tooltip="true" />
  460. <el-table-column label="文本准换" align="center" prop="isTranslate" width="80" >
  461. <template slot-scope="scope">
  462. <dict-tag :options="dict.type.sys_asr_status" :value="scope.row.isTranslate"/>
  463. </template>
  464. </el-table-column>
  465. <el-table-column label="创建时间" align="left" prop="createTime" width="150" />
  466. </el-table>
  467. </div>
  468. <div style="height: 5%;display: flex;justify-content: center;align-items: center;font-weight: bolder;font-size: large">
  469. {{ formatTime }}
  470. </div>
  471. <div style="margin-top: 5px;display: flex;justify-content: center;align-items: center;">
  472. <el-button @click="startTimer" type="primary" :disabled="timerRunning">开始录音</el-button>
  473. <el-button @click="pauseTimer" type="warning" :disabled="!timerRunning">暂停录音</el-button>
  474. <el-button @click="refreshAudio" type="primary" >刷新列表</el-button>
  475. <el-button @click="summaryGenerate" type="primary" >一键生成</el-button>
  476. </div>
  477. </div>
  478. <div v-if="audioTxt == null" style="width: 70%;border-left: 1px solid #e6e6e6;">
  479. <div style="font-size: medium;margin-bottom: 10px;margin-left: 20px">录音内容</div>
  480. <el-empty description=""></el-empty>
  481. </div>
  482. <div v-else style="width: 70%;border-left: 1px solid #e6e6e6;">
  483. <div style="font-size: medium;margin-bottom: 10px;margin-left: 20px">录音内容</div>
  484. <el-input resize="none" v-model="audioTxt" style="margin-left: 10px" type="textarea" :readonly="audioReadOnly" :rows = "29" placeholder="请输入内容" />
  485. <div style="margin-top: 35px;display: flex;justify-content: center;align-items: center;">
  486. <el-button type="primary" @click="audioTxtEdit">文本编辑</el-button>
  487. <el-button type="primary" @click="audioTxtSave">文本保存</el-button>
  488. </div>
  489. </div>
  490. </div>
  491. </el-tab-pane>
  492. <el-tab-pane label="AI问答">
  493. <div style="display: flex;flex-direction: column; height: calc(100vh - 150px)">
  494. <el-input v-model="sourceWord" resize="none" type="textarea" :rows = "12" placeholder="请输入内容" />
  495. <div style="margin-top: 20px;display: flex;justify-content: center;align-items: center;">
  496. <el-button type="primary" @click="rsWord">提交问题</el-button>
  497. <el-button type="waring" @click="resetWord">文本重置</el-button>
  498. </div>
  499. <el-divider style="margin-top: 10px;margin-bottom: 10px"></el-divider>
  500. <el-input id="targetWord" resize="none" v-model="targetWord" type="textarea" :readonly="true" :rows = "14" placeholder="请输入内容" />
  501. <div style="margin-top: 20px;display: flex;flex-direction: column;justify-content: center;align-items: center;">
  502. <el-button type="primary" @click="copyWord">文本复制</el-button>
  503. </div>
  504. </div>
  505. </el-tab-pane>
  506. </el-tabs>
  507. </el-card>
  508. </div> -->
  509. </template>
  510. <script>
  511. import {
  512. getMeeting,
  513. getMeetingFileImage,
  514. updateMeeting
  515. } from "@/api/partywork/meeting";
  516. import {
  517. endAudio,
  518. endFilePlay,
  519. filePlay,
  520. startAudio,
  521. takePhoto,
  522. takePhotoSign,
  523. urlControl,
  524. imageMove,
  525. imageScale
  526. } from "@/api/partywork/remoteControl";
  527. import {
  528. getToken
  529. } from "@/utils/auth";
  530. import {
  531. getAudio,
  532. listAudio,
  533. summaryMeeting,
  534. updateAudioTxt
  535. } from "@/api/partywork/meeting_audio";
  536. import {
  537. listDevice
  538. } from "@/api/pc/device";
  539. import {
  540. listAttendance
  541. } from "@/api/partywork/attendance";
  542. import {
  543. photoSignRecord
  544. } from "@/api/partywork/face";
  545. import logoImg from '@/assets/logo/party.png'
  546. import logoExitImg from '@/assets/logo/icon_exit.png'
  547. import iconAddressImg from '@/assets/icons/icon_address.png'
  548. import iconHostImg from '@/assets/icons/icon_host.png'
  549. import iconOrganizationImg from '@/assets/icons/icon_organization.png'
  550. import iconTimeImg from '@/assets/icons/icon_time.png'
  551. import iconScreenImg from '@/assets/icons/icon_screen.png'
  552. import iconFreshImg from '@/assets/icons/icon_fresh.png'
  553. import iconFreshGreyImg from '@/assets/icons/icon_fresh_grey.png'
  554. import iconYjscImg from '@/assets/icons/icon_yjsc.png'
  555. import iconPhotoImg from '@/assets/icons/icon_photo.png'
  556. import iconPhotoGreyImg from '@/assets/icons/icon_photo_grey.png'
  557. import iconDeleteImg from '@/assets/icons/icon_delete.png'
  558. import iconStartRecordImg from '@/assets/icons/icon_startrecord.png'
  559. import iconStartRecordRedImg from '@/assets/icons/icon_startrecord_red.png'
  560. import iconStopRecordImg from '@/assets/icons/icon_stoprecord.png'
  561. import iconStopRecordRedImg from '@/assets/icons/icon_stoprecord_red.png'
  562. import imgEmptyImg from '@/assets/images/img_empty.png'
  563. import dialogimgEmptyImg from '@/assets/images/dialog_img_empty.png'
  564. import iconStartPlayImg from '@/assets/icons/btn_startplay.png'
  565. import iconStopPlayImg from '@/assets/icons/btn_stopplay.png'
  566. export default {
  567. dicts: ['sys_asr_status', 'sys_attendance_type'],
  568. data() {
  569. return {
  570. logo: logoImg,
  571. logoExit: logoExitImg,
  572. iconAddress: iconAddressImg,
  573. iconHost: iconHostImg,
  574. iconOrganization: iconOrganizationImg,
  575. iconTime: iconTimeImg,
  576. iconScreen: iconScreenImg,
  577. iconFresh: iconFreshImg,
  578. iconFreshGrey: iconFreshGreyImg,
  579. iconYjsc: iconYjscImg,
  580. iconPhoto: iconPhotoImg,
  581. iconPhotoGrey: iconPhotoGreyImg,
  582. iconDelete: iconDeleteImg,
  583. iconStartRecord: iconStartRecordImg,
  584. iconStopRecord: iconStopRecordImg,
  585. iconStartRecordRed: iconStartRecordRedImg,
  586. iconStopRecordRed: iconStopRecordRedImg,
  587. imgEmpty: imgEmptyImg,
  588. dialogimgEmpty: dialogimgEmptyImg,
  589. iconStartPlay: iconStartPlayImg,
  590. iconStopPlay: iconStopPlayImg,
  591. meetingId: null,
  592. form: {},
  593. fileList: [],
  594. imageList: [],
  595. // 遮罩层
  596. loading: true,
  597. ids: [],
  598. // 非单个禁用
  599. single: true,
  600. // 非多个禁用
  601. multiple: true,
  602. totalPage: null,
  603. currentPage: 1,
  604. pageSrc: null,
  605. // 学习资料网站
  606. materialOptions: [],
  607. sourceWord: null,
  608. targetWord: null,
  609. websocket: null,
  610. material: null,
  611. timer: null, // 记录经过的时间秒数
  612. intervalId: null, // 定时器的ID
  613. timerRunning: false, // 状态标示,是否正在计时
  614. elapsed: 0, // 经过时间(毫秒)
  615. audioList: [],
  616. audioTxt: null,
  617. photoList: [],
  618. deviceList: [],
  619. deviceId: null,
  620. scaleId: null,
  621. moveId: null,
  622. audioReadOnly: true,
  623. audioId: null,
  624. attendanceList: [],
  625. signedNum: 0,
  626. faceSignUrl: null,
  627. faceSignList: [],
  628. scaleList: [{
  629. value: '25',
  630. label: '25%'
  631. }, {
  632. value: '50',
  633. label: '50%'
  634. }, {
  635. value: '75',
  636. label: '75%'
  637. }, {
  638. value: '100',
  639. label: '100%'
  640. }, {
  641. value: '125',
  642. label: '125%'
  643. }, {
  644. value: '150',
  645. label: '150%'
  646. }, {
  647. value: '175',
  648. label: '175%'
  649. }, {
  650. value: '200',
  651. label: '200%'
  652. }],
  653. moveList: [{
  654. value: '10',
  655. label: '10%'
  656. }, {
  657. value: '20',
  658. label: '20%'
  659. }, {
  660. value: '30',
  661. label: '30%'
  662. }, {
  663. value: '40',
  664. label: '40%'
  665. }, {
  666. value: '50',
  667. label: '50%'
  668. }, {
  669. value: '60',
  670. label: '60%'
  671. }, {
  672. value: '70',
  673. label: '70%'
  674. }, {
  675. value: '80',
  676. label: '80%'
  677. }, {
  678. value: '90',
  679. label: '90%'
  680. }, {
  681. value: '100',
  682. label: '100%'
  683. }],
  684. firstPhoto: null,
  685. firstPhotoList: [],
  686. selectedFileIndex: -1,
  687. fileType: 1,
  688. dialogPhotoVisible: false,
  689. selectedItems: [],
  690. dialogFaceSignVisible: false,
  691. customColor: '#FF5455',
  692. customColor2: 'rgba(0, 0, 0, 0.3)',
  693. percentage: 20,
  694. faceSign: {},
  695. dialogMeetVisible: false,
  696. isMeetPlay: false,
  697. imageHeight: 100,
  698. imageOffset: 0,
  699. imageHeightPx: 0,
  700. imageHeightPxChange: 0,
  701. }
  702. },
  703. watch: {
  704. selectedItems(newValue, oldValue) {
  705. // 当message变化时,会执行这里的代码
  706. console.log(`message changed from ${oldValue} to ${newValue}`);
  707. for (let j = 0; j < this.photoList.length; j++) {
  708. this.photoList[j].isSelected = false;
  709. }
  710. for (let i = 0; i < newValue.length; i++) {
  711. this.photoList[newValue[i]].isSelected = true;
  712. }
  713. }
  714. },
  715. // mounted:{
  716. // let checkboxes = document.getElementsByName("myCheckbox");
  717. // for (let i = 0; i < checkboxes.length; i++) {
  718. // console.log(checkboxes[i].checked); // 输出 true 或 false
  719. // }
  720. // },
  721. computed: {
  722. formatTime() {
  723. let remaining = this.elapsed;
  724. let milliseconds = remaining % 1000;
  725. remaining = Math.floor(remaining / 1000);
  726. let seconds = remaining % 60;
  727. remaining = Math.floor(remaining / 60);
  728. let minutes = remaining % 60;
  729. let hours = Math.floor(remaining / 60);
  730. return `${hours.toString().padStart(2, '0')}:${minutes
  731. .toString()
  732. .padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(3, '0')}`;
  733. },
  734. },
  735. created() {
  736. this.getRouterParam();
  737. this.getMeetingInfo();
  738. this.socketConnect();
  739. this.refreshAudio();
  740. this.getDeviceList();
  741. this.getAttendanceList();
  742. },
  743. destroyed() {
  744. this.websocket.close();
  745. if (this.timerRunning) {
  746. this.pauseTimer();
  747. clearInterval(this.timer);
  748. }
  749. },
  750. methods: {
  751. closePage() {
  752. this.$router.back();
  753. },
  754. refreshPhotoSign() {
  755. let param = {
  756. meetingId: this.meetingId,
  757. }
  758. photoSignRecord(param).then(response => {
  759. let reqParam = JSON.parse(response.data.reqParam);
  760. console.log('reqParam:', response.data);
  761. this.faceSign = response.data;
  762. if (response.data.rspCode === "200") {
  763. this.faceSignUrl = reqParam.url + ".1.png";
  764. } else {
  765. this.faceSignUrl = reqParam.url;
  766. }
  767. this.faceSignList = [];
  768. this.faceSignList.push(this.faceSignUrl);
  769. this.getAttendanceList();
  770. });
  771. },
  772. photoSign() {
  773. if (!this.validDeviceId()) {
  774. return;
  775. }
  776. let param = {
  777. meetingId: this.meetingId,
  778. deviceId: this.deviceId
  779. }
  780. takePhotoSign(param).then(response => {
  781. this.$modal.msgSuccess("下发拍照成功,请刷新!");
  782. });
  783. },
  784. getAttendanceList() {
  785. this.loading = true;
  786. let param = {
  787. meetingId: this.meetingId,
  788. pageNum: 1,
  789. pageSize: 200,
  790. type: 1
  791. }
  792. listAttendance(param).then(response => {
  793. this.attendanceList = response.rows;
  794. this.loading = false;
  795. console.log('attendanceList:', this.attendanceList);
  796. this.signedNum = 0;
  797. if (this.attendanceList != null && this.attendanceList.length > 0) {
  798. for (let i = 0; i < this.attendanceList.length; i++) {
  799. if (this.attendanceList[i].attendanceStatus == 1) {
  800. this.signedNum++;
  801. }
  802. }
  803. this.percentage = (this.signedNum / this.attendanceList.length) * 100;
  804. console.log('percentage:', this.percentage);
  805. }
  806. });
  807. },
  808. audioTxtEdit() {
  809. this.audioReadOnly = false;
  810. this.$message({
  811. message: '您现在可以对录音内容进行编辑',
  812. type: 'success'
  813. });
  814. },
  815. validDeviceId() {
  816. if (this.deviceId == null || this.deviceId === '') {
  817. this.$message({
  818. message: '请先选择会议设备',
  819. type: 'error'
  820. });
  821. return false;
  822. }
  823. return true;
  824. },
  825. getDeviceList() {
  826. let param = {
  827. pageSize: 100
  828. }
  829. listDevice(param).then(response => {
  830. this.deviceList = response.rows;
  831. this.deviceList.forEach(item => {
  832. let online = item.onlineStatus == "1" ? "在线" : "离线";
  833. item.deviceName = item.deviceName + "(" + online + ")";
  834. });
  835. })
  836. },
  837. summaryGenerate() {
  838. if (this.timerRunning) {
  839. this.$message({
  840. message: '请先暂停录音',
  841. type: 'warning'
  842. });
  843. } else {
  844. summaryMeeting(this.meetingId).then(response => {
  845. this.$message({
  846. message: response.msg,
  847. type: 'success'
  848. });
  849. });
  850. /*this.$modal.confirm('确认通过AI一键生成会议纪要?').then(function() {
  851. return summaryMeeting(this.meetingId);
  852. }).then(() => {
  853. this.$modal.msgSuccess("任务提交成功,请稍后刷新列表!");
  854. }).catch(() => {});*/
  855. }
  856. },
  857. savePhoto() {
  858. this.form.picsPath = this.photoList.join(",");
  859. console.log('保存后的photoList:', this.photoList);
  860. // this.form.imageList = this.photoList;
  861. // console.log('保存后的imageList:', this.form.imageList);
  862. updateMeeting(this.form).then(response => {
  863. if (this.photoList && this.photoList.length > 0) {
  864. this.firstPhoto = this.photoList[0];
  865. this.firstPhotoList = [];
  866. this.firstPhotoList.push(this.firstPhoto.picPath);
  867. this.photoPreviewList = [];
  868. for (let i = 0; i < this.photoList.length; i++) {
  869. this.photoPreviewList.push(this.photoList[i].picPath);
  870. }
  871. } else {
  872. this.firstPhoto = null;
  873. this.firstPhotoList = [];
  874. this.photoPreviewList = [];
  875. }
  876. this.selectedItems = [];
  877. this.$message({
  878. message: '删除成功',
  879. type: 'success'
  880. });
  881. });
  882. },
  883. refreshPhoto() {
  884. const id = this.meetingId;
  885. getMeeting(id).then(response => {
  886. // 会议照片集合
  887. this.selectedItems = [];
  888. if (response.data.imageList != null && response.data.imageList.length > 0) {
  889. this.photoList = response.data.imageList;
  890. console.log('photoList', this.photoList)
  891. if (this.photoList != null && this.photoList.length > 0) {
  892. this.firstPhoto = this.photoList[0];
  893. this.firstPhotoList = [];
  894. this.firstPhotoList.push(this.firstPhoto.picPath);
  895. this.photoPreviewList = [];
  896. for (let i = 0; i < this.photoList.length; i++) {
  897. this.photoPreviewList.push(this.photoList[i].picPath);
  898. }
  899. } else {
  900. this.firstPhoto = null;
  901. this.firstPhotoList = [];
  902. this.photoPreviewList = [];
  903. }
  904. }
  905. });
  906. },
  907. deletePhoto(index) {
  908. this.$modal.confirm('是否确认删除图片?').then(() => {
  909. // 用户点击确认后执行的代码
  910. for (let i = 0; i < index.length; i++) {
  911. this.photoList.splice(index[i], 1);
  912. }
  913. console.log('新photoList:', this.photoList);
  914. this.savePhoto();
  915. // this.$modal.msgSuccess("删除成功");
  916. }).catch(() => {
  917. // 用户点击取消后执行的代码
  918. });
  919. },
  920. takePhoto() {
  921. if (!this.validDeviceId()) {
  922. return;
  923. }
  924. let id = this.meetingId;
  925. takePhoto(id, this.deviceId).then(response => {
  926. this.$message({
  927. message: '发送拍照指令成功',
  928. type: 'success'
  929. });
  930. });
  931. },
  932. showAudioTxt(row) {
  933. if (row.isTranslate == 0 || row.isTranslate == 2 || row.isTranslate == 3) {
  934. this.$message({
  935. message: '当前无文本内容可供查看,请稍后!',
  936. type: 'warning'
  937. });
  938. return;
  939. }
  940. let id = row.id;
  941. this.audioId = id;
  942. getAudio(id).then(response => {
  943. this.audioTxt = response.data.audioTxt;
  944. });
  945. },
  946. audioTxtSave() {
  947. this.audioReadOnly = true;
  948. let id = this.audioId;
  949. let audioTxt = this.audioTxt;
  950. let param = {
  951. id: id,
  952. audioTxt: audioTxt
  953. }
  954. updateAudioTxt(param).then(response => {
  955. this.$message({
  956. message: '文本内容保存成功!',
  957. type: 'success'
  958. });
  959. this.showAudioTxt(param);
  960. });
  961. },
  962. refreshAudio() {
  963. let queryParam = {
  964. meetingId: this.meetingId,
  965. pageNum: 1,
  966. pageSize: 100
  967. };
  968. this.loading = true;
  969. listAudio(queryParam).then(response => {
  970. this.audioList = response.rows;
  971. console.log('audioList', this.audioList);
  972. this.loading = false;
  973. });
  974. },
  975. // 开始计时
  976. startTimer() {
  977. if (!this.validDeviceId()) {
  978. return;
  979. }
  980. if (!this.timer) {
  981. this.timerRunning = true;
  982. this.timer = setInterval(() => {
  983. this.elapsed += 10; // 我们每10毫秒更新一次时钟
  984. }, 10);
  985. startAudio(this.meetingId, this.deviceId).then(response => {
  986. this.$message({
  987. message: '开始录制成功',
  988. type: 'success'
  989. });
  990. });
  991. }
  992. },
  993. // 暂停计时
  994. pauseTimer() {
  995. if (!this.validDeviceId()) {
  996. return;
  997. }
  998. this.timerRunning = false;
  999. clearInterval(this.timer);
  1000. this.timer = null;
  1001. endAudio(this.meetingId, this.deviceId).then(response => {
  1002. this.$message({
  1003. message: '暂停录制成功',
  1004. type: 'success'
  1005. });
  1006. });
  1007. },
  1008. showUrl(url) {
  1009. // if (!this.validDeviceId()) {
  1010. // return;
  1011. // }
  1012. this.material = url;
  1013. let param = {
  1014. material: url,
  1015. type: 1,
  1016. deviceId: this.deviceId,
  1017. meetingId: this.meetingId
  1018. };
  1019. urlControl(param).then(response => {
  1020. this.$message({
  1021. message: '播放成功',
  1022. type: 'success'
  1023. });
  1024. });
  1025. },
  1026. endShowUrl(url) {
  1027. if (!this.validDeviceId()) {
  1028. return;
  1029. }
  1030. this.material = null;
  1031. let param = {
  1032. material: url,
  1033. type: 2,
  1034. deviceId: this.deviceId
  1035. };
  1036. urlControl(param).then(response => {
  1037. this.$message({
  1038. message: '结束成功',
  1039. type: 'success'
  1040. });
  1041. });
  1042. },
  1043. copyWord() {
  1044. let textToCopy = document.getElementById("targetWord").value;
  1045. navigator.clipboard.writeText(textToCopy).then(function() {
  1046. }, function(err) {
  1047. console.error('无法复制文本:', err);
  1048. });
  1049. this.$message({
  1050. message: '文本复制成功',
  1051. type: 'success'
  1052. });
  1053. },
  1054. resetWord() {
  1055. this.sourceWord = "";
  1056. let inputElement = document.getElementById("targetWord");
  1057. inputElement.value = "";
  1058. },
  1059. getRouterParam() {
  1060. this.meetingId = this.$route.query.meetingId;
  1061. console.log(this.meetingId);
  1062. },
  1063. getMeetingInfo() {
  1064. const id = this.meetingId;
  1065. this.loading = true;
  1066. getMeeting(id).then(response => {
  1067. this.form = response.data;
  1068. console.log(this.form);
  1069. this.fileList = this.form.followList;
  1070. this.materialOptions = this.form.materialOptions;
  1071. console.log('fileList:', this.fileList);
  1072. this.loading = false;
  1073. // 会议照片集合
  1074. if (this.form.imageList != null && this.form.imageList.length > 0) {
  1075. this.photoList = this.form.imageList;
  1076. console.log('phtotList', this.photoList);
  1077. if (this.photoList != null && this.photoList.length > 0) {
  1078. this.firstPhoto = this.photoList[0];
  1079. this.firstPhotoList = [];
  1080. this.firstPhotoList.push(this.firstPhoto.picPath);
  1081. this.photoPreviewList = [];
  1082. for (let i = 0; i < this.photoList.length; i++) {
  1083. this.photoPreviewList.push(this.photoList[i].picPath);
  1084. }
  1085. } else {
  1086. this.firstPhoto = null;
  1087. this.firstPhotoList = [];
  1088. this.photoPreviewList = [];
  1089. }
  1090. console.log('firstPhoto', this.firstPhoto);
  1091. }
  1092. });
  1093. },
  1094. // 多选框选中数据
  1095. handleSelectionChange(selection) {
  1096. this.ids = selection.map(item => item.id)
  1097. this.single = selection.length !== 1
  1098. this.multiple = !selection.length
  1099. },
  1100. // 开始播放会议文件
  1101. showFile() {
  1102. const id = this.fileList[this.selectedFileIndex].id;
  1103. this.currentPage = 1;
  1104. getMeetingFileImage(id).then(response => {
  1105. this.imageList = response.data;
  1106. this.totalPage = this.imageList.length;
  1107. this.getPageSrc();
  1108. });
  1109. this.controlFilePlay();
  1110. },
  1111. getPageSrc() {
  1112. this.imageList.forEach((item, index) => {
  1113. if (index === this.currentPage - 1) {
  1114. this.pageSrc = item;
  1115. }
  1116. })
  1117. },
  1118. //缩放
  1119. scaleChange() {
  1120. if (!this.validDeviceId()) {
  1121. this.scaleId = null;
  1122. return;
  1123. }
  1124. if (this.totalPage == null) {
  1125. this.$message({
  1126. message: '请先选择文件开始文件播放',
  1127. type: 'warning'
  1128. });
  1129. this.scaleId = null;
  1130. return;
  1131. }
  1132. let param = {
  1133. meetingId: this.meetingId,
  1134. scale: this.scaleId,
  1135. deviceId: this.deviceId,
  1136. imageIndex: this.currentPage
  1137. }
  1138. imageScale(param).then(response => {
  1139. console.log('缩放:', response);
  1140. this.imageHeight = 100 * (this.scaleId / 100);
  1141. this.this.imageHeightPxChange = this.imageHeightPx * (this.scaleId / 100);
  1142. this.$message({
  1143. message: "缩放成功",
  1144. type: 'success'
  1145. });
  1146. });
  1147. },
  1148. //上移
  1149. moveUp() {
  1150. console.log('moveId', this.moveId);
  1151. if (!this.validDeviceId()) {
  1152. return;
  1153. }
  1154. if (this.fileType == 1) {
  1155. if (this.totalPage == null) {
  1156. this.$message({
  1157. message: '请先选择文件开始文件播放',
  1158. type: 'warning'
  1159. });
  1160. return;
  1161. }
  1162. }
  1163. if (this.moveId == null) {
  1164. this.$message({
  1165. message: '请先选择移动距离',
  1166. type: 'warning'
  1167. });
  1168. return;
  1169. }
  1170. let param = {
  1171. direction: 1,
  1172. meetingId: this.meetingId,
  1173. distance: this.moveId,
  1174. deviceId: this.deviceId,
  1175. imageIndex: this.currentPage
  1176. }
  1177. imageMove(param).then(response => {
  1178. console.log('上移:', response);
  1179. this.imageOffset = this.imageOffset - ((this.moveId / 100) * this.imageHeightPxChange);
  1180. this.$message({
  1181. message: '上移成功',
  1182. type: 'success'
  1183. });
  1184. });
  1185. },
  1186. //下移
  1187. moveDown() {
  1188. if (!this.validDeviceId()) {
  1189. return;
  1190. }
  1191. if (this.fileType == 1) {
  1192. if (this.totalPage == null) {
  1193. this.$message({
  1194. message: '请先选择文件开始文件播放',
  1195. type: 'warning'
  1196. });
  1197. return;
  1198. }
  1199. }
  1200. if (this.moveId == null) {
  1201. this.$message({
  1202. message: '请先选择移动距离',
  1203. type: 'warning'
  1204. });
  1205. return;
  1206. }
  1207. let param = {
  1208. direction: 2,
  1209. meetingId: this.meetingId,
  1210. distance: this.moveId,
  1211. deviceId: this.deviceId,
  1212. imageIndex: this.currentPage
  1213. }
  1214. imageMove(param).then(response => {
  1215. console.log('下移:', response);
  1216. this.imageOffset = this.imageOffset + (this.moveId / 100) * this.imageHeightPxChange;
  1217. this.$message({
  1218. message: '下移成功',
  1219. type: 'success'
  1220. });
  1221. });
  1222. },
  1223. // 上一页
  1224. lastPage() {
  1225. if (!this.validDeviceId()) {
  1226. return;
  1227. }
  1228. if (this.currentPage === 1) {
  1229. this.$message({
  1230. message: '已经是第一页',
  1231. type: 'warning'
  1232. });
  1233. } else {
  1234. this.currentPage--;
  1235. this.getPageSrc();
  1236. this.controlFilePlay();
  1237. }
  1238. },
  1239. controlFilePlay() {
  1240. const id = this.fileList[this.selectedFileIndex].id;
  1241. filePlay(id, this.currentPage, this.deviceId).then(response => {
  1242. this.$message({
  1243. message: response.msg,
  1244. type: 'success'
  1245. });
  1246. });
  1247. },
  1248. endFilePlay() {
  1249. const id = this.ids[0];
  1250. endFilePlay(id, this.deviceId).then(response => {
  1251. this.$message({
  1252. message: response.msg,
  1253. type: 'success'
  1254. });
  1255. });
  1256. },
  1257. // 下一页
  1258. nextPage() {
  1259. if (!this.validDeviceId()) {
  1260. return;
  1261. }
  1262. if (this.totalPage == null) {
  1263. this.$message({
  1264. message: '请先选择文件开始文件播放',
  1265. type: 'warning'
  1266. });
  1267. return;
  1268. }
  1269. if (this.currentPage === this.totalPage) {
  1270. this.$message({
  1271. message: '已经是最后一页',
  1272. type: 'warning'
  1273. });
  1274. } else {
  1275. this.currentPage++;
  1276. this.getPageSrc();
  1277. this.controlFilePlay();
  1278. }
  1279. },
  1280. // 结束播放
  1281. endShowFile() {
  1282. if (!this.validDeviceId()) {
  1283. return;
  1284. }
  1285. this.endFilePlay();
  1286. this.currentPage = null;
  1287. this.pageSrc = null;
  1288. this.imageList = [];
  1289. // this.fileList = [];
  1290. this.totalPage = null;
  1291. this.currentPage = 1;
  1292. },
  1293. rsWord() {
  1294. if (this.sourceWord === null || this.sourceWord === '') {
  1295. this.$message({
  1296. message: '文本内容不能为空',
  1297. type: 'warning'
  1298. });
  1299. } else {
  1300. // 调用接口
  1301. /*let word = {
  1302. message : this.sourceWord
  1303. };
  1304. rsWord(word).then(response => {
  1305. this.targetWord = response.data.result;
  1306. });*/
  1307. let inputElement = document.getElementById("targetWord");
  1308. inputElement.value = "";
  1309. this.socketSend()
  1310. }
  1311. },
  1312. socketSend() {
  1313. let message = this.sourceWord;
  1314. this.websocket.send(message);
  1315. },
  1316. socketConnect() {
  1317. let socketUrl = "ws://117.73.13.40:8080/party-admin/ws/server/" + getToken();
  1318. this.websocket = new WebSocket(socketUrl);
  1319. this.websocket.onopen = function(event) {
  1320. console.log("连接成功");
  1321. };
  1322. this.websocket.onmessage = function(event) {
  1323. let message = event.data;
  1324. let decodedMessage = decodeURIComponent(message); // 将消息转换为UTF-8编码
  1325. let inputElement = document.getElementById("targetWord");
  1326. inputElement.value = inputElement.value + decodedMessage;
  1327. };
  1328. this.websocket.onclose = function(event) {
  1329. console.log("连接关闭");
  1330. };
  1331. this.websocket.onerror = function(event) {
  1332. console.log("链接错误");
  1333. };
  1334. },
  1335. //点击会议资料
  1336. selectFileItem(index) {
  1337. this.selectedFileIndex = index;
  1338. },
  1339. //开始播放
  1340. beginPlay() {
  1341. if (!this.validDeviceId()) {
  1342. return;
  1343. }
  1344. if (this.selectedFileIndex < 0) {
  1345. this.$message({
  1346. message: '请先选择会议资料',
  1347. type: 'warning'
  1348. });
  1349. return;
  1350. }
  1351. if (this.fileList[this.selectedFileIndex].fileType == 1) {
  1352. this.fileType = 1;
  1353. this.showFile();
  1354. } else if (this.fileList[this.selectedFileIndex].fileType == 2) {
  1355. this.fileType = 2;
  1356. this.showUrl(this.fileList[this.selectedFileIndex].fileUrl);
  1357. }
  1358. this.isMeetPlay = true;
  1359. },
  1360. endPlay() {
  1361. if (this.fileList[this.selectedFileIndex].fileType == 1) {
  1362. this.fileType = 1;
  1363. this.endShowFile();
  1364. } else if (this.fileList[this.selectedFileIndex].fileType == 2) {
  1365. this.fileType = 2;
  1366. this.endShowUrl(this.fileList[this.selectedFileIndex].fileUrl);
  1367. }
  1368. this.isMeetPlay = false;
  1369. this.imageOffset = 0;
  1370. this.imageHeight = 100;
  1371. this.imageHeightPxChange = this.imageHeightPx;
  1372. this.scaleId = null;
  1373. this.moveId = null;
  1374. },
  1375. deleteDialogPhoto() {
  1376. console.log('selectedItems:', this.selectedItems);
  1377. if (this.selectedItems != null && this.selectedItems.length > 0) {
  1378. this.deletePhoto(this.selectedItems);
  1379. } else {
  1380. this.$message({
  1381. message: '请先选择需要删除的图片',
  1382. type: 'warning'
  1383. });
  1384. }
  1385. },
  1386. handleImageLoad(event) {
  1387. this.imageHeightPx = event.target.offsetHeight;
  1388. this.imageHeightPxChange = this.imageHeightPx;
  1389. console.log('Image height:', this.imageHeightPx);
  1390. }
  1391. }
  1392. }
  1393. </script>
  1394. <style>
  1395. .imageDiv {
  1396. /* margin-left: 40px;
  1397. margin-right: 30px;
  1398. margin-bottom: 10px; */
  1399. margin-left: 5px;
  1400. margin-rignt: 5px;
  1401. display: flex;
  1402. align-items: center;
  1403. margin-bottom: 10px;
  1404. }
  1405. .meeting {
  1406. width: 100%;
  1407. height: 100%;
  1408. background-image: url("../../../assets/images/bg_metting.png");
  1409. display: flex;
  1410. flex-direction: column;
  1411. padding-left: 15px;
  1412. padding-top: 15px;
  1413. padding-bottom: 15px;
  1414. }
  1415. .title {
  1416. font-family: Microsoft YaHei;
  1417. font-size: 18px;
  1418. font-weight: bold;
  1419. line-height: 18px;
  1420. letter-spacing: -1px;
  1421. color: #FFFFFF;
  1422. margin-left: 8px;
  1423. }
  1424. .display-row {
  1425. display: flex;
  1426. flex-direction: row;
  1427. }
  1428. .display-cloumn {
  1429. display: flex;
  1430. flex-direction: column;
  1431. }
  1432. .display-center {
  1433. display: flex;
  1434. justify-content: center;
  1435. align-items: center;
  1436. }
  1437. .text-fontsize-14 {
  1438. font-size: 14px;
  1439. font-weight: normal;
  1440. letter-spacing: 0.01em;
  1441. color: #FFFFFF;
  1442. }
  1443. .text-fontsize-16 {
  1444. font-size: 16px;
  1445. font-weight: normal;
  1446. letter-spacing: 0.01em;
  1447. color: #FFFFFF;
  1448. }
  1449. .text-fontsize-18 {
  1450. font-size: 18px;
  1451. font-weight: normal;
  1452. letter-spacing: 0.01em;
  1453. color: #FFFFFF;
  1454. }
  1455. .icon {
  1456. width: 18px;
  1457. height: 18px;
  1458. }
  1459. .icon-40 {
  1460. width: 40px;
  1461. height: 40px;
  1462. }
  1463. /* 如果你想要更改下拉菜单的背景色 */
  1464. .el-select .el-input__inner {
  1465. background-color: rgba(0, 0, 0, 0);
  1466. /* 你想要的背景色 */
  1467. border: 1px solid rgba(255, 255, 255, 0.85);
  1468. font-size: 14px;
  1469. font-weight: normal;
  1470. letter-spacing: 0px;
  1471. color: #FFFFFF;
  1472. }
  1473. .el-select .el-input__inner:focus {
  1474. border-color: rgba(255, 255, 255, 0.85) !important;
  1475. }
  1476. /* 下拉框*/
  1477. .el-select-dropdown {}
  1478. /* 修改el-select下拉菜单选项的文字颜色 */
  1479. .el-select-dropdown__item {
  1480. color: #000000;
  1481. /* 将#your-color-here替换为你想要的颜色代码 */
  1482. font-weight: normal;
  1483. font-size: 14px;
  1484. }
  1485. .el-select-dropdown__item.selected {
  1486. color: #CA0001;
  1487. font-weight: normal;
  1488. font-size: 14px;
  1489. }
  1490. .is-selected {
  1491. background: rgba(255, 255, 255, 0.15);
  1492. }
  1493. .btn {
  1494. background-color: transparent;
  1495. border-color: #FFFFFF;
  1496. color: #FFFFFF;
  1497. }
  1498. .screen_nocontent {
  1499. border: 1px dashed #FFFFFF;
  1500. }
  1501. .fileItem {
  1502. padding: 10px 20px;
  1503. }
  1504. .single-line {
  1505. white-space: nowrap;
  1506. /* 保证文本不会换行 */
  1507. overflow: hidden;
  1508. /* 隐藏溢出的内容 */
  1509. text-overflow: ellipsis;
  1510. /* 添加省略号表示文本被截断 */
  1511. }
  1512. .line {
  1513. height: 1px;
  1514. width: 100%;
  1515. background-color: #FFFFFF;
  1516. }
  1517. .line-grey {
  1518. height: 1px;
  1519. width: 100%;
  1520. background-color: #E5E6EB;
  1521. }
  1522. .line-grey-column {
  1523. width: 1px;
  1524. height: calc(70vh - 51px);
  1525. background-color: #E5E6EB;
  1526. }
  1527. progress {
  1528. width: 82px;
  1529. height: 8px;
  1530. border-radius: 10px;
  1531. background-color: rgba(0, 0, 0, 0.3);
  1532. }
  1533. /* 已完成部分的样式 */
  1534. progress::-webkit-progress-value {
  1535. border-radius: 10px;
  1536. background: #FFE59E;
  1537. }
  1538. /* 未完成部分的样式 */
  1539. progress::-webkit-progress-bar {
  1540. border-radius: 10px;
  1541. background-color: rgba(0, 0, 0, 0.3);
  1542. }
  1543. .no-scrollbar::-webkit-scrollbar {
  1544. display: none;
  1545. /* 对于WebKit浏览器,如Chrome,Safari */
  1546. }
  1547. .no-scrollbar {
  1548. -ms-overflow-style: none;
  1549. /* 对于IE和Edge */
  1550. scrollbar-width: none;
  1551. /* 对于Firefox */
  1552. }
  1553. .el-dialog {
  1554. display: flex;
  1555. flex-direction: column;
  1556. margin: 0 !important;
  1557. position: absolute;
  1558. top: 50%;
  1559. left: 50%;
  1560. transform: translate(-50%, -50%);
  1561. height: 70vh;
  1562. width: 60vw;
  1563. max-height: calc(100% - 200px);
  1564. max-width: calc(100% - 30px);
  1565. }
  1566. .el-dialog__header {
  1567. height: 50px;
  1568. /* 设置你想要的高度 */
  1569. }
  1570. .el-dialog .el-dialog__body {
  1571. flex: 1;
  1572. overflow: auto;
  1573. padding: 0px;
  1574. }
  1575. /* table th,
  1576. table td {
  1577. border-bottom: none !important;
  1578. } */
  1579. .no-border th,
  1580. .no-border td {
  1581. border-bottom: none !important;
  1582. }
  1583. .custom-text-color {
  1584. color: red;
  1585. }
  1586. .no-active.el-button:focus,
  1587. .no-active.el-button:hover,
  1588. .no-active.el-button:active {
  1589. background-color: transparent !important;
  1590. border-color: #FFFFFF !important;
  1591. color: #FFFFFF !important;
  1592. }
  1593. .playBtn.el-button:focus,
  1594. .playBtn.el-button:hover,
  1595. .playBtn.el-button:active {
  1596. background-color: #FFE59E !important;
  1597. color: #CA0001 !important;
  1598. }
  1599. .playBtn {
  1600. background: #FFE59E;
  1601. color: #CA0001;
  1602. padding: 5px;
  1603. }
  1604. .more {
  1605. color: #FFE59E;
  1606. background: transparent;
  1607. border-color: transparent;
  1608. padding: 0;
  1609. font-size: 14px;
  1610. }
  1611. .more.el-button:focus,
  1612. .more.el-button:hover,
  1613. .more.el-button:active {
  1614. background-color: transparent !important;
  1615. color: #FFE59E !important;
  1616. border-color: transparent !important;
  1617. }
  1618. .el-select .el-input__inner::placeholder{
  1619. color: #FFFFFF;
  1620. }
  1621. </style>