hookehuyr

✨ feat(视频组件): 结构vue3,api请求模块化改造

1 +import axios from '@/utils/axios';
2 +import { fn } from '@/api/fn';
3 +
4 +const Api = {
5 + PROD_ACTION: '/srv/?a=prod_action',
6 + PROD_INFO: '/srv/?a=prod_info',
7 +}
8 +
9 +/**
10 + * @description: 操作作品动作
11 + * @param {String} type 动作类型:like, favor, play
12 + * @param {String} prod_id 作品 ID
13 + * @returns
14 + */
15 +export const prodActionAPI = (params) => fn(axios.post(Api.PROD_ACTION, params))
16 +
17 +/**
18 + * @description: 查询作品详情
19 + * @param {String} type 动作类型:like, favor, play
20 + * @param {String} prod_id 作品 ID
21 + * @returns
22 + */
23 +export const prodInfoAPI = (params) => fn(axios.get(Api.PROD_INFO, { params }))
...@@ -9,7 +9,7 @@ export const fn = (api) => { ...@@ -9,7 +9,7 @@ export const fn = (api) => {
9 return api 9 return api
10 .then(res => { 10 .then(res => {
11 if (res.data.code === 1) { 11 if (res.data.code === 1) {
12 - return res.data.data || true; 12 + return res.data || true;
13 } else { 13 } else {
14 console.warn(res); 14 console.warn(res);
15 if (!res.data.show) return false; 15 if (!res.data.show) return false;
......
1 <template> 1 <template>
2 <div class="video-wrapper"> 2 <div class="video-wrapper">
3 <div class="video-div" :id="'mui-player-' + item.id"></div> 3 <div class="video-div" :id="'mui-player-' + item.id"></div>
4 - <div v-if="mp" class="normal-module"> 4 + <div class="normal-module">
5 <div class="video-bar"> 5 <div class="video-bar">
6 <van-row> 6 <van-row>
7 <van-col span="12" @click="goTo"> 7 <van-col span="12" @click="goTo">
...@@ -38,86 +38,90 @@ ...@@ -38,86 +38,90 @@
38 /** 38 /**
39 * 视频组件通用模块 39 * 视频组件通用模块
40 */ 40 */
41 -import icon_dianzan1 from '@images/icon-dianzan01@2x.png' 41 +import { icon_dianzan1, icon_dianzan2, icon_liuyan, icon_avatar } from '@/utils/generateIcons.js'
42 -import icon_dianzan2 from '@images/icon-dianzan02@2x.png'
43 -import icon_liuyan from '@images/icon-liuyan@2x.png'
44 -import icon_avatar from '@images/que-touxiang@2x.png'
45 -
46 import { ref, reactive, onMounted } from 'vue' 42 import { ref, reactive, onMounted } from 'vue'
43 +import { _, Toast } from '@/utils/generatePackage.js'
44 +import { useRoute, useRouter } from 'vue-router'
47 import 'mui-player/dist/mui-player.min.css' 45 import 'mui-player/dist/mui-player.min.css'
48 import MuiPlayer from 'mui-player' 46 import MuiPlayer from 'mui-player'
49 -import _ from 'lodash'; 47 +import { prodActionAPI, prodInfoAPI } from '@/api/C/prod.js'
50 -import axios from 'axios';
51 -import { Toast } from 'vant';
52 48
53 -import { useRoute, useRouter } from 'vue-router'
54 const $route = useRoute(); 49 const $route = useRoute();
55 const $router = useRouter(); 50 const $router = useRouter();
56 51
57 -onMounted(() => { 52 +const props = defineProps({
53 + item: Object
58 }) 54 })
59 55
60 -</script> 56 +// 作品用户操作
57 +async function handleAction(action_type, prod_id) {
58 + const { msg } = await prodActionAPI({ action_type, prod_id });
59 + if (msg === `${action_type}-add-OK`) { // 动作操作成功
60 + if (action_type === 'favor') {
61 + Toast('收藏成功');
62 + }
63 + if (action_type === 'like') {
64 + Toast('点赞成功');
65 + }
66 + } else { // 取消操作
67 + if (action_type !== 'play') {
68 + Toast('取消成功');
69 + }
70 + }
71 + getProductDetail(action_type, prod_id); // 更新信息
72 +}
73 +// 查询作品详情
74 +async function getProductDetail(action_type, prod_id) {
75 + const { data } = await prodInfoAPI({ prod_id });
76 + // 更新详情显示
77 + detail.value[`is_${action_type}`] = data[`is_${action_type}`];
78 + detail.value[`${action_type}_num`] = data[`${action_type}_num`];
79 +}
61 80
62 -<script> 81 +let detail = ref({});
63 -// FIXME: VUE2写法 82 +
64 -import mixin from 'common/mixin'; 83 +onMounted(() => {
84 + const mp = new MuiPlayer({
85 + container: '#mui-player-' + props.item.id,
86 + title: props.item.title,
87 + src: props.item.video,
88 + poster: props.item.cover,
89 + autoFit: false,
90 + videoAttribute: [ // 声明启用同层播放, 不让会自动全屏播放
91 + { attrKey: 'webkit-playsinline', attrValue: 'webkit-playsinline' },
92 + { attrKey: 'playsinline', attrValue: 'playsinline' },
93 + { attrKey: 'x5-video-player-type', attrValue: 'h5-page' },
94 + ]
95 + })
96 + detail.value = _.cloneDeep(props.item);
97 + const video = mp.video();
98 + // 监听原生video事件
99 + video && video.addEventListener('play', function (event) {
100 + handleAction('play', props.item.id)
101 + });
102 +});
65 103
66 -export default { 104 +const goTo = () => { // 跳转作品详情页
67 - mixins: [mixin.likeFn], 105 + $router.push({
68 - props: ['item'], 106 + path: '/client/videoDetail',
69 - data() { 107 + query: {
70 - return { 108 + prod_id: props.item.id,
71 - detail: {}, 109 + book_id: props.item.book_id,
72 - mp: '' 110 + type: props.item.type // 特殊标识,判断入口 为keepAlive使用
73 } 111 }
74 - }, 112 + });
75 - created() { 113 +}
76 - }, 114 +
77 - mounted() { 115 +const setComment = () => {
78 - var mp = new MuiPlayer({ 116 + $router.push({
79 - container: '#mui-player-' + this.item.id, 117 + path: '/client/videoDetail/comment',
80 - title: this.item.title, 118 + query: {
81 - src: this.item.video, 119 + prod_id: props.item.id,
82 - poster: this.item.cover, 120 + book_id: props.item.book_id
83 - autoFit: false,
84 - videoAttribute: [ // 声明启用同层播放, 不让会自动全屏播放
85 - { attrKey: 'webkit-playsinline', attrValue: 'webkit-playsinline' },
86 - { attrKey: 'playsinline', attrValue: 'playsinline' },
87 - { attrKey: 'x5-video-player-type', attrValue: 'h5-page' },
88 - ]
89 - })
90 - this.mp = mp;
91 - this.detail = _.cloneDeep(this.item);
92 - var video = mp.video();
93 - // 监听原生video事件
94 - var _this = this;
95 - video && video.addEventListener('play', function (event) {
96 - _this.handleAction('play', _this.item.id)
97 - });
98 - },
99 - methods: {
100 - goTo () { // 跳转作品详情页
101 - this.$router.push({
102 - path: '/client/videoDetail',
103 - query: {
104 - prod_id: this.item.id,
105 - book_id: this.item.book_id,
106 - type: this.item.type // 特殊标识,判断入口 为keepAlive使用
107 - }
108 - });
109 - },
110 - setComment() {
111 - this.$router.push({
112 - path: '/client/videoDetail/comment',
113 - query: {
114 - prod_id: this.item.id,
115 - book_id: this.item.book_id
116 - }
117 - });
118 } 121 }
119 - } 122 + });
120 } 123 }
124 +
121 </script> 125 </script>
122 126
123 <style lang="less" scoped> 127 <style lang="less" scoped>
......
...@@ -5,6 +5,9 @@ import icon_subscribed from '@images/icon-dingyue01@2x.png' ...@@ -5,6 +5,9 @@ import icon_subscribed from '@images/icon-dingyue01@2x.png'
5 import icon_unsubscribe from '@images/icon-dingyue02@2x.png' 5 import icon_unsubscribe from '@images/icon-dingyue02@2x.png'
6 import no_image from '@images/que-shuju@2x.png' 6 import no_image from '@images/que-shuju@2x.png'
7 import icon_avatar from '@images/que-logo@2x.png' 7 import icon_avatar from '@images/que-logo@2x.png'
8 +import icon_dianzan1 from '@images/icon-dianzan01@2x.png'
9 +import icon_dianzan2 from '@images/icon-dianzan02@2x.png'
10 +import icon_liuyan from '@images/icon-liuyan@2x.png'
8 11
9 export { 12 export {
10 icon_video, 13 icon_video,
...@@ -13,5 +16,8 @@ export { ...@@ -13,5 +16,8 @@ export {
13 icon_subscribed, 16 icon_subscribed,
14 icon_unsubscribe, 17 icon_unsubscribe,
15 no_image, 18 no_image,
16 - icon_avatar 19 + icon_avatar,
20 + icon_dianzan1,
21 + icon_dianzan2,
22 + icon_liuyan,
17 } 23 }
......