Commit bf5dcdd582fde3080605fda8475596781c88f661

Authored by YunaiV
1 parent 5a1d02df

mp:素材管理,增加【语音】【视频】

yudao-ui-admin/src/views/mp/components/wx-voice-play/main.vue
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <template> 12 <template>
13 <div class="wx-voice-div" @click="playVoice"> 13 <div class="wx-voice-div" @click="playVoice">
14 <i :class="playing !== true ? 'el-icon-video-play': 'el-icon-video-pause'"> 14 <i :class="playing !== true ? 'el-icon-video-play': 'el-icon-video-pause'">
15 - <span class="amr-duration" v-if="duration">{{ duration }}</span> 15 + <span class="amr-duration" v-if="duration">{{ duration }} 秒</span>
16 </i> 16 </i>
17 <div v-if="content"> 17 <div v-if="content">
18 <el-tag type="success" size="mini">语音识别</el-tag> 18 <el-tag type="success" size="mini">语音识别</el-tag>
yudao-ui-admin/src/views/mp/material/index.vue
@@ -20,6 +20,10 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER @@ -20,6 +20,10 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE. 22 SOFTWARE.
  23 + 芋道源码:
  24 + ① 清理冗余 css 内容,清理冗余 data 变量
  25 + ② 美化样式,支持播放,提升使用体验
  26 + ③ 优化代码,特别是方法名和变量,提升可读性
23 --> 27 -->
24 <template> 28 <template>
25 <div class="app-container"> 29 <div class="app-container">
@@ -63,152 +67,102 @@ SOFTWARE. @@ -63,152 +67,102 @@ SOFTWARE.
63 <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" 67 <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
64 @pagination="getList"/> 68 @pagination="getList"/>
65 </el-tab-pane> 69 </el-tab-pane>
  70 +
  71 + <!-- tab 2:语音 -->
66 <el-tab-pane name="voice"> 72 <el-tab-pane name="voice">
67 <span slot="label"><i class="el-icon-microphone"></i> 语音</span> 73 <span slot="label"><i class="el-icon-microphone"></i> 语音</span>
68 - <div class="add_but">  
69 - <el-upload  
70 - :action="actionUrl"  
71 - :headers="headers"  
72 - multiple  
73 - :limit="1"  
74 - :on-success="handleUploadSuccess"  
75 - :file-list="fileList"  
76 - :before-upload="beforeVoiceUpload"  
77 - :data="uploadData"> 74 + <div class="add_but" v-hasPermi="['mp:material:upload-permanent']">
  75 + <el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
  76 + :on-success="handleUploadSuccess" :before-upload="beforeVoiceUpload">
78 <el-button size="mini" type="primary">点击上传</el-button> 77 <el-button size="mini" type="primary">点击上传</el-button>
79 - <div slot="tip" class="el-upload__tip">  
80 - 格式支持mp3/wma/wav/amr,文件大小不超过2M,播放长度不超过60s  
81 - </div> 78 + <span slot="tip" class="el-upload__tip" style="margin-left: 5px">格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s</span>
82 </el-upload> 79 </el-upload>
83 </div> 80 </div>
84 - <el-table  
85 - :data="list"  
86 - stripe  
87 - border  
88 - v-loading="loading">  
89 - <el-table-column  
90 - prop="mediaId"  
91 - label="media_id">  
92 - </el-table-column>  
93 - <el-table-column  
94 - prop="name"  
95 - label="名称"> 81 + <el-table :data="list" stripe border v-loading="loading" style="margin-top: 10px;">
  82 + <el-table-column label="编号" align="center" prop="mediaId" />
  83 + <el-table-column label="文件名" align="center" prop="name" />
  84 + <el-table-column label="语音" align="center">
  85 + <template v-slot="scope">
  86 + <wx-voice-player :url="scope.row.url" />
  87 + </template>
96 </el-table-column> 88 </el-table-column>
97 - <el-table-column  
98 - prop="updateTime"  
99 - label="更新时间"> 89 + <el-table-column label="上传时间" align="center" prop="createTime" width="180">
  90 + <template v-slot="scope">
  91 + <span>{{ parseTime(scope.row.createTime) }}</span>
  92 + </template>
100 </el-table-column> 93 </el-table-column>
101 - <el-table-column  
102 - fixed="right"  
103 - label="操作"> 94 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
104 <template slot-scope="scope"> 95 <template slot-scope="scope">
105 - <el-button type="text"  
106 - icon="el-icon-download"  
107 - size="small"  
108 - plain  
109 - @click="handleDown(scope.row)">下载</el-button>  
110 - <el-button type="text"  
111 - icon="el-icon-delete"  
112 - size="small"  
113 - plain  
114 - @click="handleDelete(scope.row)">删除</el-button> 96 + <el-button type="text" icon="el-icon-download" size="small" plain @click="handleDownload(scope.row)">下载</el-button>
  97 + <el-button type="text" icon="el-icon-delete" size="small" plain @click="handleDelete(scope.row)"
  98 + v-hasPermi="['mp:material:delete']">删除</el-button>
115 </template> 99 </template>
116 </el-table-column> 100 </el-table-column>
117 </el-table> 101 </el-table>
118 - <el-pagination  
119 - @size-change="sizeChange"  
120 - @current-change="currentChange"  
121 - :current-page.sync="queryParams.currentPage"  
122 - :page-sizes="[10, 20]"  
123 - :page-size="queryParams.pageSize"  
124 - layout="total, sizes, prev, pager, next, jumper"  
125 - :total="queryParams.total"  
126 - class="pagination"  
127 - >  
128 - </el-pagination> 102 + <!-- 分页组件 -->
  103 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  104 + @pagination="getList"/>
129 </el-tab-pane> 105 </el-tab-pane>
  106 +
  107 + <!-- tab 3:视频 -->
130 <el-tab-pane name="video"> 108 <el-tab-pane name="video">
131 <span slot="label"><i class="el-icon-video-play"></i> 视频</span> 109 <span slot="label"><i class="el-icon-video-play"></i> 视频</span>
132 - <div class="add_but">  
133 - <el-button size="mini" type="primary" @click="handleAddVideo">新建</el-button> 110 + <div class="add_but" v-hasPermi="['mp:material:upload-permanent']">
  111 + <el-button size="mini" type="primary" @click="handleAddVideo">新建视频</el-button>
134 </div> 112 </div>
135 - <el-dialog title="新建视频" :visible.sync="dialogVideoVisible" v-loading="addMaterialLoading">  
136 - <el-upload  
137 - ref="uploadVideo"  
138 - :action="actionUrl"  
139 - :headers="headers"  
140 - multiple  
141 - :limit="1"  
142 - :on-success="handleUploadSuccess"  
143 - :file-list="fileList"  
144 - :before-upload="beforeVideoUpload"  
145 - :auto-upload="false"  
146 - :data="uploadData"> 113 + <!-- 新建视频的弹窗 -->
  114 + <el-dialog title="新建视频" :visible.sync="dialogVideoVisible" append-to-body width="600px"
  115 + v-loading="addMaterialLoading">
  116 + <el-upload :action="actionUrl" :headers="headers" multiple :limit="1" :file-list="fileList" :data="uploadData"
  117 + :before-upload="beforeVideoUpload" :on-success="handleUploadSuccess"
  118 + ref="uploadVideo" :auto-upload="false">
147 <el-button slot="trigger" size="mini" type="primary">选择视频</el-button> 119 <el-button slot="trigger" size="mini" type="primary">选择视频</el-button>
148 - <div class="el-upload__tip">  
149 - 格式支持MP4,文件大小不超过10MB  
150 - </div> 120 + <span class="el-upload__tip" style="margin-left: 10px;">格式支持 MP4,文件大小不超过 10MB</span>
151 </el-upload> 121 </el-upload>
152 - <el-form :model="uploadData"  
153 - :rules="uploadRules"  
154 - ref="uploadForm">  
155 - <el-form-item label="标题" prop="title">  
156 - <el-input v-model="uploadData.title" placeholder="标题将展示在相关播放页面,建议填写清晰、准确、生动的标题"></el-input>  
157 - </el-form-item>  
158 - <el-form-item label="描述" prop="introduction">  
159 - <el-input :rows="3" type="textarea" v-model="uploadData.introduction" placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容"></el-input>  
160 - </el-form-item> 122 + <el-form :model="uploadData" :rules="uploadRules" ref="uploadForm" label-width="80px">
  123 + <el-row>
  124 + <el-form-item label="标题" prop="title">
  125 + <el-input v-model="uploadData.title" placeholder="标题将展示在相关播放页面,建议填写清晰、准确、生动的标题" />
  126 + </el-form-item>
  127 + </el-row>
  128 + <el-row>
  129 + <el-form-item label="描述" prop="introduction">
  130 + <el-input :rows="3" type="textarea" v-model="uploadData.introduction"
  131 + placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容" />
  132 + </el-form-item>
  133 + </el-row>
161 </el-form> 134 </el-form>
162 <div slot="footer" class="dialog-footer"> 135 <div slot="footer" class="dialog-footer">
163 - <el-button @click="dialogVideoVisible = false">取 消</el-button>  
164 - <el-button type="primary" @click="subVideo">提 交</el-button> 136 + <el-button @click="cancelVideo">取 消</el-button>
  137 + <el-button type="primary" @click="submitVideo">提 交</el-button>
165 </div> 138 </div>
166 </el-dialog> 139 </el-dialog>
167 - <el-table  
168 - :data="list"  
169 - stripe  
170 - border  
171 - v-loading="loading">  
172 - <el-table-column  
173 - prop="mediaId"  
174 - label="media_id">  
175 - </el-table-column>  
176 - <el-table-column  
177 - prop="name"  
178 - label="名称"> 140 + <el-table :data="list" stripe border v-loading="loading" style="margin-top: 10px;">
  141 + <el-table-column label="编号" align="center" prop="mediaId" />
  142 + <el-table-column label="文件名" align="center" prop="name" />
  143 + <el-table-column label="标题" align="center" prop="title" />
  144 + <el-table-column label="介绍" align="center" prop="introduction" />
  145 + <el-table-column label="视频" align="center">
  146 + <template v-slot="scope">
  147 + <wx-video-player :url="scope.row.url" />
  148 + </template>
179 </el-table-column> 149 </el-table-column>
180 - <el-table-column  
181 - prop="updateTime"  
182 - label="更新时间"> 150 + <el-table-column label="上传时间" align="center" prop="createTime" width="180">
  151 + <template v-slot="scope">
  152 + <span>{{ parseTime(scope.row.createTime) }}</span>
  153 + </template>
183 </el-table-column> 154 </el-table-column>
184 - <el-table-column  
185 - fixed="right"  
186 - label="操作">  
187 - <template slot-scope="scope">  
188 - <el-button type="text"  
189 - icon="el-icon-view"  
190 - size="small"  
191 - plain  
192 - @click="handleInfo(scope.row)">查看</el-button>  
193 - <el-button type="text"  
194 - icon="el-icon-delete"  
195 - size="small"  
196 - plain  
197 - @click="handleDelete(scope.row)">删除</el-button> 155 + <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
  156 + <template v-slot="scope">
  157 + <el-button type="text" icon="el-icon-download" size="small" plain @click="handleDownload(scope.row)">下载</el-button>
  158 + <el-button type="text" icon="el-icon-delete" size="small" plain @click="handleDelete(scope.row)"
  159 + v-hasPermi="['mp:material:delete']">删除</el-button>
198 </template> 160 </template>
199 </el-table-column> 161 </el-table-column>
200 </el-table> 162 </el-table>
201 - <el-pagination  
202 - @size-change="sizeChange"  
203 - @current-change="currentChange"  
204 - :current-page.sync="queryParams.currentPage"  
205 - :page-sizes="[10, 20]"  
206 - :page-size="queryParams.pageSize"  
207 - layout="total, sizes, prev, pager, next, jumper"  
208 - :total="queryParams.total"  
209 - class="pagination"  
210 - >  
211 - </el-pagination> 163 + <!-- 分页组件 -->
  164 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  165 + @pagination="getList"/>
212 </el-tab-pane> 166 </el-tab-pane>
213 </el-tabs> 167 </el-tabs>
214 </div> 168 </div>
@@ -243,26 +197,23 @@ export default { @@ -243,26 +197,23 @@ export default {
243 pageNo: 1, 197 pageNo: 1,
244 pageSize: 10, 198 pageSize: 10,
245 accountId: undefined, 199 accountId: undefined,
  200 + permanent: true,
246 }, 201 },
247 202
248 actionUrl: process.env.VUE_APP_BASE_API + '/admin-api/mp/material/upload-permanent', 203 actionUrl: process.env.VUE_APP_BASE_API + '/admin-api/mp/material/upload-permanent',
249 headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部 204 headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部
250 fileList:[], 205 fileList:[],
251 - dialogVideoVisible:false,  
252 - dialogNewsVisible:false,  
253 - addMaterialLoading:false,  
254 uploadData: { 206 uploadData: {
255 "type": 'image', 207 "type": 'image',
256 "title":'', 208 "title":'',
257 "introduction":'' 209 "introduction":''
258 }, 210 },
259 - uploadRules:{  
260 - title: [  
261 - { required: true, message: '请输入标题', trigger: 'blur' }  
262 - ],  
263 - introduction: [  
264 - { required: true, message: '请输入描述', trigger: 'blur' }  
265 - ], 211 + // === 视频上传,独有变量 ===
  212 + dialogVideoVisible: false,
  213 + addMaterialLoading: false,
  214 + uploadRules: { // 视频上传的校验规则
  215 + title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
  216 + introduction: [{ required: true, message: '请输入描述', trigger: 'blur' }],
266 }, 217 },
267 218
268 // 公众号账号列表 219 // 公众号账号列表
@@ -284,7 +235,6 @@ export default { @@ -284,7 +235,6 @@ export default {
284 // ======================== 列表查询 ======================== 235 // ======================== 列表查询 ========================
285 /** 设置账号编号 */ 236 /** 设置账号编号 */
286 setAccountId(accountId) { 237 setAccountId(accountId) {
287 - console.log('奥特曼!')  
288 this.queryParams.accountId = accountId; 238 this.queryParams.accountId = accountId;
289 this.uploadData.accountId = accountId; 239 this.uploadData.accountId = accountId;
290 }, 240 },
@@ -333,53 +283,6 @@ export default { @@ -333,53 +283,6 @@ export default {
333 }, 283 },
334 284
335 // ======================== 文件上传 ======================== 285 // ======================== 文件上传 ========================
336 -  
337 - handleInfo(row){  
338 - this.loading = true  
339 - getMaterialVideo({  
340 - mediaId:row.mediaId  
341 - }).then((response) => {  
342 - this.loading = false  
343 - if(response.code == 200){  
344 - let downUrl = response.data.downUrl  
345 - window.open(downUrl, '_blank');  
346 - }else{  
347 - this.$message.error('获取微信视频素材出错:' + response.data.msg)  
348 - }  
349 - }).catch(() => {  
350 - this.loading = false  
351 - })  
352 - },  
353 - handleDown(row){  
354 - this.loading = true  
355 - getMaterialOther({  
356 - mediaId:row.mediaId,  
357 - fileName:row.name  
358 - }).then(response => {  
359 - this.loading = false  
360 - let url = window.URL.createObjectURL(new Blob([response.data]))  
361 - let link = document.createElement('a')  
362 - link.style.display = 'none'  
363 - link.href = url  
364 - link.setAttribute('download', row.name)  
365 - document.body.appendChild(link)  
366 - link.click()  
367 - }).catch(() => {  
368 - this.loading = false  
369 - })  
370 - },  
371 - subVideo(){  
372 - this.$refs['uploadForm'].validate((valid) => {  
373 - if (valid) {  
374 - this.$refs.uploadVideo.submit()  
375 - } else {  
376 - return false  
377 - }  
378 - })  
379 - },  
380 - handleAddVideo(){  
381 - this.dialogVideoVisible = true  
382 - },  
383 beforeImageUpload(file) { 286 beforeImageUpload(file) {
384 const isType = file.type === 'image/jpeg' 287 const isType = file.type === 'image/jpeg'
385 || file.type === 'image/png' 288 || file.type === 'image/png'
@@ -388,42 +291,46 @@ export default { @@ -388,42 +291,46 @@ export default {
388 || file.type === 'image/jpg'; 291 || file.type === 'image/jpg';
389 if (!isType) { 292 if (!isType) {
390 this.$message.error('上传图片格式不对!') 293 this.$message.error('上传图片格式不对!')
391 - this.loading = false  
392 return false; 294 return false;
393 } 295 }
394 const isLt = file.size / 1024 / 1024 < 2 296 const isLt = file.size / 1024 / 1024 < 2
395 if (!isLt) { 297 if (!isLt) {
396 this.$message.error('上传图片大小不能超过 2M!') 298 this.$message.error('上传图片大小不能超过 2M!')
397 - this.loading = false  
398 return false; 299 return false;
399 } 300 }
400 this.loading = true 301 this.loading = true
401 return true; 302 return true;
402 }, 303 },
403 beforeVoiceUpload(file){ 304 beforeVoiceUpload(file){
404 - const isType = file.type === 'audio/mp3' || file.type === 'audio/wma' || file.type === 'audio/wav' || file.type === 'audio/amr'; 305 + const isType = file.type === 'audio/mp3'
  306 + || file.type === 'audio/wma'
  307 + || file.type === 'audio/wav'
  308 + || file.type === 'audio/amr';
405 const isLt = file.size / 1024 / 1024 < 2 309 const isLt = file.size / 1024 / 1024 < 2
406 if (!isType) { 310 if (!isType) {
407 this.$message.error('上传语音格式不对!') 311 this.$message.error('上传语音格式不对!')
  312 + return false;
408 } 313 }
409 if (!isLt) { 314 if (!isLt) {
410 - this.$message.error('上传语音大小不能超过2M!') 315 + this.$message.error('上传语音大小不能超过 2M!')
  316 + return false;
411 } 317 }
412 - this.loading = false  
413 - return isType && isLt; 318 + this.loading = true
  319 + return true;
414 }, 320 },
415 beforeVideoUpload(file){ 321 beforeVideoUpload(file){
416 - this.addMaterialLoading = true  
417 const isType = file.type === 'video/mp4' 322 const isType = file.type === 'video/mp4'
418 - const isLt = file.size / 1024 / 1024 < 10  
419 if (!isType) { 323 if (!isType) {
420 this.$message.error('上传视频格式不对!') 324 this.$message.error('上传视频格式不对!')
  325 + return false;
421 } 326 }
  327 + const isLt = file.size / 1024 / 1024 < 10
422 if (!isLt) { 328 if (!isLt) {
423 - this.$message.error('上传视频大小不能超过10M!') 329 + this.$message.error('上传视频大小不能超过 10M!')
  330 + return false
424 } 331 }
425 - this.addMaterialLoading = false  
426 - return isType && isLt; 332 + this.addMaterialLoading = true
  333 + return true
427 }, 334 },
428 handleUploadSuccess(response, file, fileList) { 335 handleUploadSuccess(response, file, fileList) {
429 this.loading = false 336 this.loading = false
@@ -442,6 +349,35 @@ export default { @@ -442,6 +349,35 @@ export default {
442 // 加载数据 349 // 加载数据
443 this.getList() 350 this.getList()
444 }, 351 },
  352 + // 下载文件
  353 + handleDownload(row) {
  354 + window.open(row.url,'_blank')
  355 + },
  356 + // 提交 video 新建的表单
  357 + submitVideo() {
  358 + this.$refs['uploadForm'].validate((valid) => {
  359 + if (!valid) {
  360 + return false;
  361 + }
  362 + this.$refs.uploadVideo.submit()
  363 + })
  364 + },
  365 + handleAddVideo() {
  366 + this.resetVideo();
  367 + this.dialogVideoVisible = true
  368 + },
  369 + /** 取消按钮 */
  370 + cancelVideo() {
  371 + this.dialogVideoVisible = false;
  372 + this.resetVideo();
  373 + },
  374 + /** 表单重置 */
  375 + resetVideo() {
  376 + this.fileList = []
  377 + this.uploadData.title = ''
  378 + this.uploadData.introduction = ''
  379 + this.resetForm("uploadForm");
  380 + },
445 381
446 // ======================== 其它操作 ======================== 382 // ======================== 其它操作 ========================
447 handleDelete(item) { 383 handleDelete(item) {