From 1b6f1e454fff0187d4d30dcf0d5819d4f57f1787 Mon Sep 17 00:00:00 2001 From: inleft <inleft@qq.com> Date: Mon, 29 Aug 2022 01:05:14 +0800 Subject: [PATCH] 新增iframe 播放页 新增日志编辑页 --- src/components/mini/box15-videoPlayBox.vue | 11 src/assets/md.less | 6 src/components/mini/box10-add.vue | 2 src/components/fixed/header.vue | 9 src/components/swichLabel/edit.vue | 524 ++++++++++++++++++++++++++++++++++++++++++- src/config/myConstant.js | 1 src/config/router.config.js | 10 src/components/iframe/videoMiniBox.vue | 148 ++++++++++++ src/components/mini/box16-videoDetail.vue | 2 9 files changed, 685 insertions(+), 28 deletions(-) diff --git a/src/assets/md.less b/src/assets/md.less index ebd8b45..bf64bd8 100644 --- a/src/assets/md.less +++ b/src/assets/md.less @@ -17,6 +17,12 @@ } } + iframe{ + display: flex; + margin: 0px auto; + border-radius: 8px; + } + p{ text-indent: 2rem; } diff --git a/src/components/fixed/header.vue b/src/components/fixed/header.vue index a5b9549..3c7566f 100644 --- a/src/components/fixed/header.vue +++ b/src/components/fixed/header.vue @@ -7,6 +7,7 @@ <router-link to="/link">友人帐</router-link> <router-link to="/platform">月台</router-link> <router-link to="/login">登录</router-link> + <router-link to="/edit" v-if="showHidenButton">编辑</router-link> <!-- <router-link to="/comment">测试页</router-link> --> </div> </a-col> @@ -24,8 +25,15 @@ </template> <script> + import myConstant from "../../config/myConstant.js" export default { mounted() { + let tempVisitorData = localStorage.getItem(myConstant.visitorDataKey); + if (tempVisitorData != null && JSON.parse(tempVisitorData).nickName == myConstant.userName) { + //this.$message.info("认证成功..") + this.showHidenButton = true + } + let self = this; let code = 0; let code2 = 0; @@ -65,6 +73,7 @@ }, data() { return { + showHidenButton: false, search: { //placeholder: "ctrl+shift+f/enter", placeholder: "搜索框未营业..", diff --git a/src/components/iframe/videoMiniBox.vue b/src/components/iframe/videoMiniBox.vue new file mode 100644 index 0000000..a73e200 --- /dev/null +++ b/src/components/iframe/videoMiniBox.vue @@ -0,0 +1,148 @@ +<template> + <div v-if="closePlayer" style="display: flex; justify-content: center;align-items: center;height: 180px;"> + 无效视频资源 + </div> + <div v-else id="videoPlay" ref="myVdeoPlay" style="position: absolute; top: 0;left: 0;width: 100%;height: 100%;"> + </div> +</template> + +<script> + import Hls from 'hls.js' + import DPlayer from 'dplayer' + export default { + components: {}, + mounted() { + var url = this.$route.query.url; + if (url == null || url == '') { + this.closePlayer = true; + return + } + + let _this = this; + + this.videoData.url = 'http://t.inleft.com/blog/mp4/' + url + + + //弹窗初始化后先不加载视频,等待手动播放 + this.init(); + + this.dp.volume(0, true, false); + + this.dp.on('pause', function() { + _this.$message.info("停止播放") + }); + + this.dp.on('play', function() { + _this.$message.info("开始播放..") + }); + + this.dp.on('error', function() { + _this.disabledPointer = true + }); + + _this.$nextTick(function() { + _this.startPlay(this.videoData) + }) + }, + data() { + return { + dp: null, + hls: null, + videoData: {}, + closePlayer: false + } + }, + methods: { + //加载播放 + startPlay(videoData) { + if (videoData == null || videoData == undefined) { + this.$message.error("无效资源..") + return + } + + if (videoData.url != null && videoData.url != "" && videoData.url.endsWith("m3u8")) { + videoData.type = "customHls"; + } else { + videoData.type = "normal"; + } + + if (videoData.pic === null || videoData.pic == '') { + videoData.pic = myConstant.defaultBGVideo; + } + + //重要!!防止hls类型视频在切换后不停在后台缓存 + if (this.hls != null) { + this.hls.destroy(); + } + + this.disabledPointer = false; + this.isPlaying = false; + + //重要!!防止hls类型视频在切换后不停在后台缓存 + if (videoData.type == "customHls") { + this.hls = new Hls(); + + } + + this.dp.switchVideo(videoData) + + }, + //播放器初始化 + init() { + var _this = this; + this.dp = new DPlayer({ + element: document.getElementById("videoPlay"), + //logo: "https://qczh-1252727916.cos.ap-nanjing.myqcloud.com/pic/273658f508d04d488414fd2b84c9f923.png", // 在视频左上角上打一个logo + hotkey: true, // 是否支持热键,调节音量,播放,暂停等 + mutex: false, // 防止同时播放多个用户,在该用户开始播放时暂停其他用户 + theme: "#b7daff", // 风格颜色,例如播放条,音量条的颜色 + loop: false, // 是否自动循环 + lang: "zh-cn", // 语言,'en', 'zh-cn', 'zh-tw' + // screenshot: true, // 是否允许截图(按钮),点击可以自动将截图下载到本地 + preload: "metadata", // 自动预加载 'none', 'metadata', 'auto' + volume: _this.volumeInit, // 初始化音量 + playbackSpeed: [2, 1, 0.5], //可选的播放速度,可自定义 + video: { + pic: _this.defalutImg, // 视频封面 + // url: videoInfo.url, + //url: "http://t.inleft.com/share/mp3/EOPMusic%282%29.mp3", + type: "normal", + customType: { + customHls: function(video, player) { + //const hls = new Hls() + if (_this.hls != null) { + _this.hls.loadSource(video.src) + _this.hls.attachMedia(video) + + // 监听Hls.Events.ERROR事件, + // DNS解析、下载超时,都会触发manifestLoadError错误 + _this.hls.on(Hls.Events.ERROR, function(eventName, data) { + // 埋点上报,可以追踪data.details + // track() + _this.$message.error("hls加载异常", 5) + console.log(eventName); + console.log(data); + }) + } + + } + } + } + }) + + // 以下为隐藏一些作者的信息和视频播放源 如不需要可删除 + document.querySelector(".dplayer-menu").remove(); //隐藏右键菜单 + + // document.querySelector(".dplayer-mask").remove(); + // document.querySelector(".dplayer-info-panel-item-url").remove(); //隐藏播放源 + // let length = document.querySelectorAll(".dplayer-menu-item").length; + // document.querySelectorAll(".dplayer-menu-item")[length - 1].remove(); // 去掉作者信息 + // document.querySelectorAll(".dplayer-menu-item")[length - 2].remove(); // 去掉作者信息 + }, + } + + } +</script> + +<style> +</style> diff --git a/src/components/mini/box10-add.vue b/src/components/mini/box10-add.vue index 31ba449..cdab9cb 100644 --- a/src/components/mini/box10-add.vue +++ b/src/components/mini/box10-add.vue @@ -41,11 +41,9 @@ <a-form-model-item label="分类" prop="class"> <a-select v-model="form.class" :allowClear="true" mode="default" placeholder="日志分类" :getPopupContainer="getCalendarContainer()"> - <a-select-option v-for="(item,index) in this.blogArticleType" :key="index" :value="item.id"> {{ item.typeName }} </a-select-option> - </a-select> </a-form-model-item> diff --git a/src/components/mini/box15-videoPlayBox.vue b/src/components/mini/box15-videoPlayBox.vue index 99132eb..8e56ba5 100644 --- a/src/components/mini/box15-videoPlayBox.vue +++ b/src/components/mini/box15-videoPlayBox.vue @@ -51,12 +51,14 @@ <script> import Hls from 'hls.js' import DPlayer from 'dplayer' + import myConstant from "../../config/myConstant.js" export default { data() { return { disabledPointer: false, dp: null, + hls: null, playHistory: [], playRecordIds: [], volumeInit: 0.1, @@ -65,13 +67,12 @@ currentTime: 0, duration: 0, playingVideoData: { - pic: "http://t.inleft.com/share/media_photo/idea_beijing.jpg", + pic: "", url: "", type: "normal", title: "", id: "" }, - hls: null, } }, mounted() { @@ -173,12 +174,16 @@ return } - if (videoData.url != null && videoData.urlL != "" && videoData.url.endsWith("m3u8")) { + if (videoData.url != null && videoData.url != "" && videoData.url.endsWith("m3u8")) { videoData.type = "customHls"; } else { videoData.type = "normal"; } + if (videoData.pic === null || videoData.pic == ''){ + videoData.pic = myConstant.defaultBGVideo; + } + //重要!!防止hls类型视频在切换后不停在后台缓存 if (this.hls != null) { this.hls.destroy(); diff --git a/src/components/mini/box16-videoDetail.vue b/src/components/mini/box16-videoDetail.vue index 5eae95f..feb99a5 100644 --- a/src/components/mini/box16-videoDetail.vue +++ b/src/components/mini/box16-videoDetail.vue @@ -96,7 +96,7 @@ myLock: false, showFade: true, videoData: { - img: "http://t.inleft.com/share/media_photo/idea_beijing.jpg", + pic: "", url: "", type: "normal", title: "", diff --git a/src/components/swichLabel/edit.vue b/src/components/swichLabel/edit.vue index fa56745..220052c 100644 --- a/src/components/swichLabel/edit.vue +++ b/src/components/swichLabel/edit.vue @@ -1,31 +1,457 @@ <template> <div class="blog-main"> - <div class="edit-main"> + <div class="edit-main fade"> <div class="edit-info"> - <div class="edit-info-head"> - 头 + <div class="edit-info-body blog-container "> + 配置项 + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>标题:</span> + </div> + <div class="edit-article-value"> + <a-input placeholder="限 50字内" /> + </div> + </div> + <div class="edit-article-meta"> + + <div class="edit-article-item"> + <span>分类:</span> + </div> + <div class="edit-article-value"> + <a-select v-model="typeId" :allowClear="true" mode="default" placeholder="日志分类" + :getPopupContainer="getCalendarContainer()" style="width: 100%;"> + <a-select-option v-for="(item,index) in this.blogArticleType" :key="index" + :value="item.id"> + {{ item.typeName }} + </a-select-option> + </a-select> + </div> + + </div> + <div class="edit-article-meta"> + + <div class="edit-article-item"> + <span>主类型:</span> + </div> + <div class="edit-article-value"> + <a-select mode="default" placeholder="" :getPopupContainer="getCalendarContainer()" + style="width: 100%;"> + <a-select-option value="1"> + markdown + </a-select-option> + <a-select-option value="2"> + html + </a-select-option> + <a-select-option value="3"> + 视频 + </a-select-option> + <a-select-option value="4"> + 音频 + </a-select-option> + <a-select-option value="5"> + 图组 + </a-select-option> + <a-select-option value="9"> + taking + </a-select-option> + </a-select> + </div> + + </div> + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>引言:</span> + </div> + <div class="edit-article-value"> + <a-textarea placeholder="限 700字内" style="max-height: 100px;" /> + </div> + </div> + + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>是否置顶:</span> + </div> + <div class="edit-article-value"> + <a-select mode="default" placeholder="" :getPopupContainer="getCalendarContainer()" + style="width: 100%;"> + <a-select-option value="0"> + 否 + </a-select-option> + <a-select-option value="1"> + 是 + </a-select-option> + </a-select> + </div> + </div> + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>公开状态:</span> + </div> + <div class="edit-article-value"> + <a-select mode="default" placeholder="" :getPopupContainer="getCalendarContainer()" + style="width: 100%;"> + <a-select-option value="1"> + 公开 + </a-select-option> + <a-select-option value="2"> + 私人 + </a-select-option> + <a-select-option value="3"> + 密码授权 + </a-select-option> + </a-select> + </div> + </div> + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>授权密码:</span> + </div> + <div class="edit-article-value"> + <a-input placeholder="限 50字内" /> + </div> + </div> + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>编辑状态:</span> + </div> + <div class="edit-article-value"> + <a-select mode="default" placeholder="" :getPopupContainer="getCalendarContainer()" + style="width: 100%;"> + <a-select-option value="1"> + 草稿 + </a-select-option> + <a-select-option value="2"> + 发布 + </a-select-option> + </a-select> + </div> + </div> + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>是否允许评论:</span> + </div> + <div class="edit-article-value"> + <a-select mode="default" placeholder="" :getPopupContainer="getCalendarContainer()" + style="width: 100%;"> + <a-select-option value="0"> + 否 + </a-select-option> + <a-select-option value="1"> + 是 + </a-select-option> + </a-select> + </div> + </div> + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>外链:</span> + </div> + <div class="edit-article-value"> + <a-input placeholder="限 50字内" /> + </div> + </div> + <div> + <a-button type="primary" style="margin-right: 10px;"> + 仅保存配置(含附件) + </a-button> + <a-button type="primary"> + 创建新的日志 + </a-button> + </div> + <div>附件</div> + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>封面:</span> + </div> + <div class="edit-article-value"> + <a-input placeholder="限 50字内" /> + </div> + </div> + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>图组:</span> + </div> + <div class="edit-article-value"> + <a-input placeholder="限 50字内" /> + </div> + </div> + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>视频组:</span> + </div> + <div class="edit-article-value"> + <a-input placeholder="限 50字内" /> + </div> + </div> </div> - <div class="edit-info-body"> - 信息 + + <div class="edit-info-head blog-container "> + <p>基本信息</p> + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>上次编辑时间:</span> + </div> + <div class="edit-article-config"> + 2022-08-27 12:12:12 + </div> + </div> + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>上次更新时间:</span> + </div> + <div class="edit-article-config"> + 2022-08-27 12:12:12 + </div> + </div> + + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>归档时间:</span> + </div> + <div class="edit-article-config"> + 2022-08-27 12:12:12 + </div> + </div> + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>首次发布时间:</span> + </div> + <div class="edit-article-config"> + 2022-08-27 12:12:12 + </div> + </div> + <div class="edit-article-meta"> + <div class="edit-article-item"> + <span>创建时间:</span> + </div> + <div class="edit-article-config"> + 2022-08-27 12:12:12 + </div> + </div> </div> </div> - <div class="edit-write"> - <div class="edit-write-input">输入区</div> - <div class="edit-write-preview">对比区</div> + <div class="edit-body"> + <div class="edit-write"> + <div class="edit-write-input "> + <a-textarea id="myInput" style="height: 100%;" v-model="text" class="defenseExpand" + @keydown.9.native.prevent="tabFunc" /> + </div> + <div class="edit-write-preview "> + <div v-viewer class="markdown-body defenseExpand" + style="height: 100%;border: 1px solid #d9d9d9;"> + <vue-markdown :source="text"></vue-markdown> + </div> + </div> + </div> + + <div class="edit-tool blog-container"> + + <div class="edit-tool-item" style="gap: 0px;"> + <div style="display: flex;width: 350px;"> + <div style="display: flex;align-items: center;justify-content: flex-end;margin-right: 5px;"> + <span>日志选取:</span> + </div> + <a-select v-model="articleTypeId" mode="default" placeholder="" + :getPopupContainer="getCalendarContainer()" style="width: 100%;"> + <a-select-option value="1"> + 十里平湖霜满天 + </a-select-option> + <a-select-option value="2"> + 寸寸青丝愁华年 + </a-select-option> + <a-select-option value="3"> + 对月形单望相护 + </a-select-option> + <a-select-option value="4"> + 只羡鸳鸯不羡仙 + </a-select-option> + <a-select-option value="5"> + 江水春沉沉 + </a-select-option> + <a-select-option value="9"> + 上有双竹林 + </a-select-option> + </a-select> + <a-button style="margin-left: 10px;"> + <a-icon type="reload"></a-icon> + </a-button> + </div> + + <div class="edit-tool-item" style="gap: 0px;"> + <a-button type="primary"> + 调取当前日志内容 + </a-button> + <span class="myTip">(触发前提示手动保存)</span> + </div> + + <div style="display: flex;width: 350px;"> + <div style="display: flex;align-items: center;justify-content: flex-end;margin-right: 5px"> + <span>草稿列表:</span> + </div> + <a-select v-model="articleTypeId" mode="default" placeholder="" + :getPopupContainer="getCalendarContainer()" style="width: 100%;"> + <a-select-option value="1"> + 十里平湖霜满天 + </a-select-option> + <a-select-option value="2"> + 寸寸青丝愁华年 + </a-select-option> + <a-select-option value="3"> + 对月形单望相护 + </a-select-option> + <a-select-option value="4"> + 只羡鸳鸯不羡仙 + </a-select-option> + <a-select-option value="5"> + 江水春沉沉 + </a-select-option> + <a-select-option value="9"> + 上有双竹林 + </a-select-option> + </a-select> + <a-button style="margin-left: 10px;"> + <a-icon type="reload"></a-icon> + </a-button> + </div> + + + <div class="edit-tool-item" style="gap: 0px;"> + <a-button type="primary"> + 调取草稿到内容 + </a-button> + <span class="myTip">(触发前提示手动保存)</span> + </div> + + + </div> + <div class="edit-tool-item"> + <a-button type="primary"> + 同步滚动对比 + </a-button> + <a-button type="primary"> + 插入自定义视频 + </a-button> + <a-button type="primary"> + 插入自定义音频 + </a-button> + </div> + <div class="edit-tool-item"> + <a-button type="primary"> + 仅更新文本框内容到数据库 + </a-button> + + <a-button type="primary"> + 一键保存所有(含配置,草稿) + </a-button> + + <div class="edit-tool-item" style="gap: 0px;"> + <span class="caogaoTip myTip">auto草稿策略:如果文本框在聚焦状态改变内容后,10秒自动保存一次当前文本框内容,最多同时保存10个</span> + <span class="caogaoTip myTip">manual草稿策略:手动保存草稿会另外保存在一个文件夹,最多同时保存10个,手动无cd,按钮防抖1秒</span> + <span class="caogaoTip myTip">草稿列表是两者叠加</span> + </div> + + </div> + + <div class="edit-tool-item" style="gap: 5px;"> + + <a-button type="primary"> + 手动存稿 + </a-button> + <span> 实时保存草稿状态:5秒前</span> + + <span class="myTip"> + 自动存稿时间: <span class="myTip">草稿-auto-2022-08-27 12:12:12</span> + </span> + <span class="myTip"> + 手动存稿时间: <span class="myTip">草稿-manual-2022-08-27 12:12:15</span> + </span> + <div class="edit-tool-item" style="gap: 0px;"> + <span class="caogaoTip myTip">保存文件夹格式</span> + <span class="caogaoTip myTip"> caogao/id/auto/xxx.md</span> + <span class="caogaoTip myTip">caogao/id/manual/xxx.md</span> + </div> + + </div> + + + </div> + + </div> + </div> </div> </template> <script> + import { + queryBlogArticleType + } from '../../api/blogArticleType.js' + + import VueMarkdown from 'vue-markdown' + const exp1 = + "###   十里平湖 \r> ##### (卢照邻·唐) \r> 化自《长安古意》 \r* 十里平湖霜满天 \r* 寸寸青丝愁华年 \r* 对月形单望相护 \r* 只羡鸳鸯不羡仙 \r![](http://blog.inleft.com/photo/example.jpg)\n\n"; + const exp2 = "###   杂曲歌辞·春江曲 \r> ##### (郭元振·唐) \r* 江水春沉沉 \r* 上有双竹林 \r* 竹叶坏水色 \r* 郎亦坏人心 \r\n"; + + const exp3 = "\r> 「探清水河」\r引用化作 「上有竹林深 」 " + + export default { + components: { + VueMarkdown + }, + beforeMount() { + queryBlogArticleType({}).then((res) => { + this.blogArticleType = res.data; + }) + }, + data() { + return { + text: exp1 + exp2 + exp3, + articleTypeId: "", + typeId: "", + blogArticleType: [], + } + }, + methods: { + insertInputTxt(id, insertTxt) { + var elInput = document.getElementById(id); + var startPos = elInput.selectionStart + var endPos = elInput.selectionEnd + if (startPos === undefined || endPos === undefined) return + var txt = elInput.value + var result = txt.substring(0, startPos) + insertTxt + txt.substring(endPos) + elInput.value = result + elInput.focus() + elInput.selectionStart = startPos + insertTxt.length + elInput.selectionEnd = startPos + insertTxt.length + }, + getCalendarContainer(trigger) { + return trigger => trigger.parentNode; + }, + } + + } </script> <style lang="less"> + .defenseExpand { + max-height: 820px; + overflow: auto; + } + .edit-main { min-height: 860px; - width: 100%; display: grid; grid-template-columns: repeat(11, 1fr); + grid-gap: 20px; } .edit-info { @@ -33,37 +459,97 @@ grid-column-end: 4; display: flex; flex-direction: column; + gap: 20px; } .edit-info-head, .edit-info-body { - width: 100%; + width: 80%; + margin: 0px auto; } + .edit-info-head { - height: 200px; - background-color: #aa55ff; + height: 300px; } .edit-info-body { - background-color: #aa007f; height: 100%; } - .edit-write { + + .edit-info-head, + .edit-info-body { + display: flex; + gap: 10px; + flex-direction: column; + } + + .edit-body { grid-column-start: 4; grid-column-end: 12; - background-color: #ffaaff; display: flex; + gap: 20px; + flex-direction: column; + } + + .edit-tool { + height: 300px; + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + + button { + margin-right: 10px; + } + } + + .edit-tool-item { + display: flex; + flex-direction: column; + padding: 10px 20px; + gap: 20px; + } + + .edit-write { + display: flex; + flex-wrap: wrap; + gap: 20px; } .edit-write-input { - width: 100%; - background-color: #aa557f; + flex: 1; } .edit-write-preview { - width: 100%; - background-color: #55007f; + flex: 1; + } + + .edit-article-meta { + display: flex; + } + + .edit-article-item { + width: 140px; + display: flex; + padding-right: 10px; + justify-content: flex-end; + align-items: center; + } + + + .edit-article-value { + width: 50%; + } + + .edit-article-config { + width: 50%; + text-align: center; + } + + .caogaoTip { + width: 300px; + white-space: initial; + border: 1px solid #d9d9d9; } </style> diff --git a/src/config/myConstant.js b/src/config/myConstant.js index 883812f..0e5c3c4 100644 --- a/src/config/myConstant.js +++ b/src/config/myConstant.js @@ -6,6 +6,7 @@ userName: "inleft", img404: "this.onerror='';this.src=\"http://t.inleft.com/share/media_photo/idea_beijing.jpg\"", defaultBG:"http://t.inleft.com/share/media_photo/background.jpg", + defaultBGVideo:"http://t.inleft.com/share/media_photo/idea_beijing.jpg", fileType: { fileTypeMarkDown_1: 1, fileTypeHtml_2: 2, diff --git a/src/config/router.config.js b/src/config/router.config.js index 7e46f71..4ce50ee 100644 --- a/src/config/router.config.js +++ b/src/config/router.config.js @@ -20,6 +20,8 @@ import videoDetail from '../components/mini/box16-videoDetail.vue' import videoList from '../components/mini/box14-video.vue' +import videoMiniBox from '../components/iframe/videoMiniBox.vue' + export const asyncRouterMap = [{ path: '*', @@ -117,11 +119,13 @@ name: 'edit', component: edit, }, + ], - - ] }, - + { + path: '/v', + component: videoMiniBox, + } ] -- Gitblit v1.9.1