index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <template>
  2. <div>
  3. <div style="display: flex">
  4. <div style="width: 300px">
  5. <el-card>
  6. <dic-tree
  7. v-model="listQuery.params.catId"
  8. dic-code="course_file_catalog"
  9. />
  10. </el-card>
  11. </div>
  12. <div style="flex-grow: 1; padding-left: 20px">
  13. <data-table
  14. ref="pagingTable"
  15. :options="options"
  16. :list-query="listQuery"
  17. @add="handleAdd"
  18. @edit="handleEdit"
  19. >
  20. <template slot="filter-content">
  21. <dic-list-select
  22. v-model="listQuery.params.fileType"
  23. dic-code="course_file_type"
  24. title="课件类型"
  25. class="filter-item"
  26. />
  27. <el-input
  28. v-model="listQuery.params.title"
  29. placeholder="搜索课件名称"
  30. style="width: 200px"
  31. class="filter-item"
  32. />
  33. </template>
  34. <template slot="data-columns">
  35. <el-table-column
  36. label="课件名称"
  37. prop="title"
  38. show-overflow-tooltip
  39. >
  40. <template slot-scope="scope">
  41. <detail-link
  42. :id="scope.row.id"
  43. :title="scope.row.title"
  44. permission="course:file:update"
  45. @click="handleEdit"
  46. />
  47. </template>
  48. </el-table-column>
  49. <el-table-column
  50. label="课件类型"
  51. prop="fileType_dictText"
  52. align="center"
  53. width="150px"
  54. />
  55. <el-table-column
  56. label="课程类目"
  57. prop="catId_dictText"
  58. align="center"
  59. />
  60. <el-table-column
  61. label="文件大小"
  62. prop="fileSize"
  63. align="center"
  64. width="120px"
  65. />
  66. <el-table-column
  67. label="课件时长"
  68. align="center"
  69. width="120px"
  70. show-overflow-tooltip
  71. >
  72. <template v-slot="scope">
  73. <span v-if="scope.row.duration === 0">无</span>
  74. <span v-else>
  75. <sec-format :value="scope.row.duration" />
  76. </span>
  77. </template>
  78. </el-table-column>
  79. <el-table-column
  80. label="创建人"
  81. align="center"
  82. prop="createBy_dictText"
  83. width="120px"
  84. />
  85. <el-table-column
  86. label="创建时间"
  87. align="center"
  88. prop="createTime"
  89. width="180px"
  90. />
  91. <el-table-column label="操作" align="center" width="150px">
  92. <template slot-scope="scope">
  93. <el-link
  94. type="primary"
  95. icon="el-icon-view"
  96. style="margin-left: 10px"
  97. @click="handlePreview(scope.row)"
  98. >在线预览</el-link
  99. >
  100. </template>
  101. </el-table-column>
  102. </template>
  103. </data-table>
  104. </div>
  105. </div>
  106. <el-dialog
  107. :close-on-click-modal="false"
  108. :visible.sync="dialogVisible"
  109. title="课件管理"
  110. width="50%"
  111. >
  112. <el-form
  113. ref="postForm"
  114. :model="postForm"
  115. :rules="rules"
  116. label-position="left"
  117. label-width="120px"
  118. >
  119. <el-form-item label="课件类型" prop="fileType">
  120. <dic-list-select
  121. v-model="postForm.fileType"
  122. :disabled="isEdit"
  123. dic-code="course_file_type"
  124. />
  125. </el-form-item>
  126. <el-form-item label="课件名称" prop="title">
  127. <el-input v-model="postForm.title" />
  128. </el-form-item>
  129. <el-form-item label="课件分类">
  130. <dic-catalog-tree
  131. v-model="postForm.catId"
  132. dic-code="course_file_catalog"
  133. />
  134. </el-form-item>
  135. <el-form-item v-if="postForm.fileType" label="上传文件" prop="fileUrl">
  136. <file-upload
  137. v-model="postForm.fileUrl"
  138. :limit="1"
  139. :tips="tips"
  140. :accept="accept"
  141. list-type="file"
  142. />
  143. </el-form-item>
  144. <el-form-item
  145. v-if="postForm.fileType === '33' && postForm.fileUrl"
  146. label="视频时长"
  147. >
  148. <el-input-number v-model="postForm.duration" /> 单位:秒
  149. <div style="color: #ff4949">
  150. <small
  151. >MP4视频可以直接读取视频时长,其他格式视频将在提交后异步读取.</small
  152. >
  153. </div>
  154. </el-form-item>
  155. </el-form>
  156. <div slot="footer" class="dialog-footer">
  157. <el-alert type="success" style="margin-bottom: 20px">
  158. 课件保存后,您可以从列表来预览它!
  159. </el-alert>
  160. <el-button @click="dialogVisible = false">取 消</el-button>
  161. <el-button :loading="loading" type="primary" @click="handleSave"
  162. >确 定</el-button
  163. >
  164. </div>
  165. </el-dialog>
  166. <el-dialog
  167. :close-on-click-modal="false"
  168. :visible.sync="previewVisible"
  169. title="文件预览"
  170. width="60%"
  171. @close="closePreview"
  172. >
  173. <div style="max-height: 650px; overflow-x: hidden; overflow-y: auto">
  174. <div v-if="previewData.fileType === '33'">
  175. <video-player
  176. v-model="previewData.viewUrl"
  177. :ref-id="previewData.id"
  178. />
  179. </div>
  180. <pdf-reader
  181. v-if="previewData.fileType === '11'"
  182. :src="previewData.viewUrl"
  183. />
  184. <pdf-reader
  185. v-if="previewData.fileType === '22'"
  186. :src="previewData.fileUrl"
  187. />
  188. </div>
  189. </el-dialog>
  190. <div
  191. v-if="postForm.fileType === '33' && postForm.fileUrl"
  192. style="display: none"
  193. >
  194. <video-player v-model="postForm.fileUrl" @loaded="videoLoaded" />
  195. </div>
  196. </div>
  197. </template>
  198. <script>
  199. import DataTable from "@/components/DataTable";
  200. import DicListSelect from "@/components/DicListSelect";
  201. import { saveData, fetchDetail } from "@/api/course/file";
  202. import FileUpload from "@/components/FileUpload";
  203. import DicCatalogTree from "@/components/DicTreeSelect";
  204. import { fetchTree } from "@/api/sys/dict/value";
  205. import DicTree from "@/components/DicTree/index";
  206. import DetailLink from "@/components/DetailLink";
  207. import VideoPlayer from "@/components/VideoPlayer";
  208. import PdfReader from "@/components/PdfReader";
  209. import SecFormat from "@/components/SecFormat";
  210. export default {
  211. name: "CourseFileList",
  212. components: {
  213. SecFormat,
  214. PdfReader,
  215. VideoPlayer,
  216. DetailLink,
  217. DicTree,
  218. DicCatalogTree,
  219. FileUpload,
  220. DicListSelect,
  221. DataTable,
  222. },
  223. data() {
  224. return {
  225. dialogVisible: false,
  226. fileList: [],
  227. isEdit: false,
  228. tips: "",
  229. accept: "",
  230. data: {},
  231. loading: false,
  232. postForm: {
  233. fileType: "",
  234. fileUrl: "",
  235. needLearn: 0,
  236. },
  237. rules: {
  238. title: [{ required: true, message: "课件名称不能为空!" }],
  239. fileType: [{ required: true, message: "课件类型不能为空!" }],
  240. fileUrl: [{ required: true, message: "课件文件必须上传!" }],
  241. },
  242. listQuery: {
  243. current: 1,
  244. size: 10,
  245. params: {
  246. courseId: this.courseId,
  247. catId: null,
  248. },
  249. },
  250. options: {
  251. // 可批量操作
  252. multi: true,
  253. add: {
  254. enable: true,
  255. permission: "course:file:add",
  256. },
  257. edit: {
  258. enable: true,
  259. permission: "course:file:update",
  260. },
  261. delete: {
  262. enable: true,
  263. permission: "course:file:delete",
  264. url: "/api/course/file/delete",
  265. },
  266. // 列表请求URL
  267. listUrl: "/api/course/file/paging",
  268. },
  269. previewVisible: false,
  270. previewData: {},
  271. treeData: [],
  272. defaultProps: {
  273. children: "children",
  274. label: "title",
  275. },
  276. };
  277. },
  278. watch: {
  279. "postForm.fileType": {
  280. handler(val) {
  281. if (val === "11") {
  282. this.tips = "包含doc,docx,xls,xlsx,ppt,pptx等Office类型文件";
  283. this.accept = ".doc, .docx, .xls, .xlsx, .ppt, .pptx";
  284. this.data = {};
  285. this.previewData.fileType = "11";
  286. }
  287. if (val === "22") {
  288. this.tips = "PDF文件可以直接在线预览";
  289. this.accept = ".pdf";
  290. this.data = {};
  291. this.previewData.fileType = "22";
  292. }
  293. if (val === "33") {
  294. this.tips =
  295. "视频文件,尽可能使用mp4格式兼容性较好,也支持flv,mkv,rm,rmvb等格式";
  296. this.accept = ".mp4, .mov, .flv, .mkv, .rm, .rmvb, .webm, .ogv, .avi";
  297. this.data = {};
  298. this.previewData.fileType = "33";
  299. }
  300. },
  301. },
  302. },
  303. created() {
  304. const id = this.$route.params.courseId;
  305. if (id !== undefined) {
  306. this.listQuery.params.courseId = id;
  307. }
  308. fetchTree({ dicCode: "course_file_catalog" }).then((res) => {
  309. this.treeData = res.data;
  310. });
  311. },
  312. methods: {
  313. handleAdd() {
  314. this.postForm = { courseId: this.listQuery.params.courseId };
  315. this.dialogVisible = true;
  316. this.isEdit = false;
  317. },
  318. handleEdit(id) {
  319. // 先清理表单
  320. this.postForm = {};
  321. this.isEdit = true;
  322. this.dialogVisible = true;
  323. fetchDetail(id).then((res) => {
  324. this.postForm = res.data;
  325. });
  326. },
  327. handleSave() {
  328. this.$refs.postForm.validate((valid) => {
  329. if (!valid) {
  330. return;
  331. }
  332. this.loading = true;
  333. saveData(this.postForm)
  334. .then(() => {
  335. this.$message({
  336. type: "success",
  337. message: "课件保存成功!",
  338. });
  339. this.dialogVisible = false;
  340. this.$refs.pagingTable.getList();
  341. this.loading = false;
  342. })
  343. .catch((err) => {
  344. console.log(err);
  345. this.loading = false;
  346. });
  347. });
  348. },
  349. catalogSelected(node) {
  350. console.log("node", node);
  351. this.listQuery.params.catId = node.id;
  352. },
  353. handlePreview(data) {
  354. this.previewVisible = true;
  355. this.previewData.fileType = data.fileType;
  356. this.previewData.viewUrl = data.viewUrl;
  357. this.previewData.fileUrl = data.fileUrl;
  358. },
  359. closePreview() {
  360. this.previewData = {};
  361. },
  362. // 读取视频长度
  363. videoLoaded(d) {
  364. console.log("++++++视频长度" + d);
  365. this.postForm["duration"] = parseInt(d);
  366. },
  367. },
  368. };
  369. </script>