index.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <template>
  2. <a-card
  3. title="存储列表"
  4. >
  5. <a-row justify="space-between" >
  6. <a-col>
  7. <a-select v-model:value="recordState.type" style="width: 170px;" >
  8. <a-select-option
  9. v-for="item in typeList"
  10. :key="item"
  11. :value="item"
  12. >
  13. {{item}}
  14. </a-select-option>
  15. </a-select>
  16. </a-col>
  17. <a-col>
  18. <a-button type="primary" @click="openRecordModal">开始存储</a-button>
  19. </a-col>
  20. </a-row>
  21. <a-table
  22. style="margin-top: 20px;"
  23. :columns="recordColumns"
  24. :data-source="state.recordDataSource"
  25. :loading="state.loading"
  26. :pagination="false"
  27. >
  28. <template #bodyCell="{column, record}" >
  29. <template v-if="column.key === 'action'" >
  30. <a-space>
  31. <!-- <a @click="openModal(record)" >详情</a> -->
  32. <a @click="recordPlay(record)" >录制播放</a>
  33. </a-space>
  34. </template>
  35. </template>
  36. </a-table>
  37. </a-card>
  38. <a-card
  39. title="正在存储的视频流"
  40. style="margin-top: 20px;"
  41. >
  42. <a-table
  43. :columns="columns"
  44. :data-source="state.recordingDataSource"
  45. :loading="state.loading"
  46. :pagination="false"
  47. >
  48. <template #bodyCell="{column, record}" >
  49. <template v-if="column.key === 'action'" >
  50. <a-space>
  51. <a @click="stopRcord(record)" >停止录制</a>
  52. </a-space>
  53. </template>
  54. </template>
  55. </a-table>
  56. </a-card>
  57. <modal-pro
  58. style="width: 700px;"
  59. label="视频流详情"
  60. :visible="state.visible"
  61. @cancel="state.visible = false"
  62. @ok="state.visible = false"
  63. destroyOnClose
  64. >
  65. <video-player-tsx :video-url="`/rts-api/record/${state.recordDetail.Path}`" />
  66. </modal-pro>
  67. <modal-pro
  68. label="录制视频"
  69. :visible="state.recordVisible"
  70. @cancel="state.recordVisible = false"
  71. @ok="recordVideo"
  72. >
  73. <a-form :label-col="{span: 4}" >
  74. <a-form-item label="类型" >
  75. <a-select v-model:value="recordState.type" >
  76. <a-select-option
  77. v-for="item in typeList"
  78. :key="item"
  79. :value="item"
  80. >
  81. {{item}}
  82. </a-select-option>
  83. </a-select>
  84. </a-form-item>
  85. <a-form-item label="视频流标识" >
  86. <a-select v-model:value="recordState.streamPath" >
  87. <a-select-option
  88. v-for="item in state.streams"
  89. :key="item.Path"
  90. :value="item.Path"
  91. >
  92. {{item.Path}}
  93. </a-select-option>
  94. </a-select>
  95. </a-form-item>
  96. </a-form>
  97. </modal-pro>
  98. </template>
  99. <script lang="ts" setup >
  100. import { RtsController } from '@/controller/rts'
  101. import { onMounted, reactive } from 'vue'
  102. import { Form, message } from 'ant-design-vue'
  103. import { VideoPlayerTsx } from '@/components/VideoPlayer/index'
  104. import { getRecording } from '@/api/rts/stream'
  105. const useForm = Form.useForm
  106. const recordColumns = [
  107. {
  108. title: '存储地址',
  109. dataIndex: 'Path'
  110. },
  111. {
  112. title: '文件大小',
  113. dataIndex: 'Size'
  114. },
  115. {
  116. title: '时长',
  117. dataIndex: 'Duration'
  118. },
  119. {
  120. title: '操作',
  121. dataIndex: 'action',
  122. key: 'action'
  123. }
  124. ]
  125. const columns = [
  126. {
  127. title: 'id',
  128. dataIndex: 'ID'
  129. },
  130. {
  131. title: '录制类型',
  132. dataIndex: 'Type'
  133. },
  134. {
  135. title: '录制开始时间',
  136. dataIndex: 'StartTime'
  137. },
  138. {
  139. title: '录制参数',
  140. dataIndex: 'Config'
  141. },
  142. {
  143. title: '操作',
  144. dataIndex: 'action',
  145. key: 'action'
  146. }
  147. ]
  148. const typeList = ['mp4', 'ts', 'flv']
  149. const recordState = reactive({
  150. type: 'flv',
  151. streamPath: 'app/name'
  152. })
  153. const state = reactive({
  154. loading: false,
  155. visible: false,
  156. recordVisible: false,
  157. recordingDataSource: [],
  158. recordDataSource: [],
  159. recordDetail: {},
  160. detail: {},
  161. streams: [],
  162. type: 'flv',
  163. videoUrl: ''
  164. })
  165. const stopRcord = async (record) => {
  166. await RtsController.stopRecord(record.id)
  167. getRecording()
  168. }
  169. const recordVideo = async () => {
  170. if (!recordState.streamPath) {
  171. message.warn('请填写标识流地址')
  172. return
  173. }
  174. await RtsController.recordVideo(recordState)
  175. state.recordVisible = false
  176. }
  177. const recordPlay = async (record) => {
  178. await RtsController.playRecord(record.Path, 'flv')
  179. getRecordingList()
  180. }
  181. const openRecordModal = () => {
  182. state.recordVisible = true
  183. }
  184. const openModal = (record: RTS.STREAM.Detail) => {
  185. state.detail = record
  186. state.visible = false
  187. }
  188. const getStreamList = async () => {
  189. const { data } = await RtsController.getStreams()
  190. state.streams = data
  191. }
  192. const getRecordList = async () => {
  193. const { data } = await RtsController.listRecord(state.type)
  194. state.recordDataSource = data
  195. }
  196. const getRecordingList = async () => {
  197. const { data } = await RtsController.listRecording()
  198. state.recordingDataSource = data
  199. }
  200. onMounted(() => {
  201. getRecordingList()
  202. getStreamList()
  203. getRecordList()
  204. })
  205. </script>
  206. <style></style>