contentOperation.vue 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. <template>
  2. <div class="m-container">
  3. <h2>
  4. <el-page-header @back="onCancel"
  5. :content="(pageType == 'create' ? '添加' : '修改') + typeChange(type)"></el-page-header>
  6. </h2>
  7. <div class="m-core">
  8. <el-form :model="form"
  9. :rules="rules"
  10. ref="form"
  11. label-width="120px"
  12. style="width: 100%">
  13. <el-form-item label="标题"
  14. prop="title">
  15. <el-input v-model.trim="form.title"></el-input>
  16. </el-form-item>
  17. <el-form-item label="排序值">
  18. <el-input v-model.trim="form.order"></el-input>
  19. </el-form-item>
  20. <!-- <el-form-item label="适用范围"
  21. prop="tenantId">
  22. <el-select v-model="form.tenantId" style="width: 400px !important">
  23. <el-option label="对内"
  24. value="1"></el-option>
  25. <el-option label="对外"
  26. value="2"></el-option>
  27. </el-select>
  28. </el-form-item> -->
  29. <el-form-item label="所属分部"
  30. prop="organIdList">
  31. <!-- <el-select v-model="form.organIdList" placeholder="请选择所属分部" style="width: 400px !important">
  32. <el-option
  33. v-for="(item, index) in selects.branchs"
  34. :key="index"
  35. :label="item.name"
  36. :value="item.id"
  37. ></el-option>
  38. </el-select> -->
  39. <select-all v-model.trim="form.organIdList"
  40. style="width: 400px !important"
  41. filterable
  42. placeholder="请选择分部"
  43. multiple
  44. clearable>
  45. <el-option v-for="(item,index) in selects.branchs"
  46. :key="index"
  47. :label="item.name"
  48. :value="item.id"></el-option>
  49. </select-all>
  50. </el-form-item>
  51. <el-form-item
  52. prop="subjectIdList" v-if="type == 7"
  53. label="所属声部"
  54. :rules="[{required: true, message:'请选择声部', trigger: 'blur, change'}]">
  55. <select-all v-model="form.subjectIdList" clearable filterable multiple placeholder="请选择声部" style="width: 400px !important">
  56. <el-option v-for="item in selects.subjects" :value="item.id" :label="item.name" :key="item.id"></el-option>
  57. </select-all>
  58. </el-form-item>
  59. <!-- banner图 && app按钮管理,才需要添加版本号 -->
  60. <el-form-item label="版本号"
  61. v-if="type == 3 || type == 6 || type == 8">
  62. <el-input v-model="form.memo"></el-input>
  63. </el-form-item>
  64. <!-- -->
  65. <!-- <el-form-item v-if="type == 3 || type == 6 || type == 5 || type == 8" label="链接地址">
  66. <el-input v-model.trim="form.linkUrl"></el-input>
  67. </el-form-item> -->
  68. <el-form-item label="链接地址"
  69. prop="linkUrl"
  70. :rules='[{ required: type == 3 || type == 6 || type == 5 || type == 8 ? false : true, message: "请输入链接地址", trigger: "blur" }]'>
  71. <el-input v-model.trim="form.linkUrl"></el-input>
  72. </el-form-item>
  73. <el-form-item label="上架时间" v-if="type == 5" prop="actionTime" :rules="[{required: true, message: '请选择上架时间范围', trigger: 'change'}]">
  74. <el-date-picker style="width:400px;"
  75. v-model="form.actionTime"
  76. :clearable="false"
  77. type="datetimerange"
  78. range-separator="至"
  79. :picker-options="{ firstDayOfWeek: 1 }"
  80. start-placeholder="上架开始日期"
  81. end-placeholder="上架结束日期">
  82. </el-date-picker>
  83. </el-form-item>
  84. <!-- 广告管理才有类型 -->
  85. <el-form-item label="广告类型"
  86. v-if="type == 8">
  87. <el-select v-model="uploadType" style="width: 400px !important"
  88. :disabled="pageType != 'create'">
  89. <el-option label="图片"
  90. :value="1"></el-option>
  91. <el-option label="视频"
  92. :value="2"></el-option>
  93. </el-select>
  94. </el-form-item>
  95. <el-form-item v-if="uploadType == 2 && type == 8"
  96. key="coverImage"
  97. label="广告视频"
  98. prop="coverImage">
  99. <div @click="addAdvVideo"
  100. style="display: inline-block;">
  101. <video class="avatar"
  102. v-if="form.coverImage"
  103. type="video/mp4"
  104. preload="auto"
  105. :poster="form.videoCoverImage"
  106. :src="form.coverImage"></video>
  107. <i v-else
  108. class="el-icon-plus avatar-uploader-icon"></i>
  109. </div>
  110. <p style="color: red">上传视频尺寸建议:1242px * 2208px;</p>
  111. </el-form-item>
  112. <el-form-item v-else
  113. key="coverImage"
  114. :label="type == 8 ? '广告图' : '封面图'"
  115. prop="coverImage">
  116. <el-upload class="avatar-uploader"
  117. action="/api-web/uploadFile"
  118. :headers="headers"
  119. :show-file-list="false"
  120. accept=".jpg, .jpeg, .png, .gif"
  121. :on-success="handleAvatarSuccess"
  122. :before-upload="beforeAvatarUpload">
  123. <!-- 判断是图片还是视频 -->
  124. <img v-if="form.coverImage"
  125. :src="form.coverImage"
  126. class="avatar" />
  127. <i v-else
  128. class="el-icon-plus avatar-uploader-icon"></i>
  129. </el-upload>
  130. <p class="imageSize"
  131. v-if="imageSize">上传图片尺寸为:{{ imageSize }}</p>
  132. </el-form-item>
  133. <!-- 广告管理才有时长 -->
  134. <el-form-item label="显示时长(秒)"
  135. prop="attribute1"
  136. :rules="[{required: true, validator: validNum, trigger: 'blur'}]"
  137. v-if="type == 8">
  138. <el-input type="number"
  139. v-model.number="form.attribute1"></el-input>
  140. <p style="color: red">建议时长不超过5秒</p>
  141. </el-form-item>
  142. <!-- 知识库管理才会有类型 -->
  143. <el-form-item v-if="type == 7 || type == 2"
  144. :label="type == 7 ? '知识类别' : '资讯类别'"
  145. prop="subType"
  146. :rules="[{ required: true, message: (type == 7 ? '请选择知识类别' : '请选择资讯类别'), trigger: 'change' }]">
  147. <el-select v-model="form.subType" style="width: 400px !important">
  148. <el-option v-for="item in typeList" :key="item.id" :label="item.name" :value="item.id"></el-option>
  149. <!-- <el-option label="演奏小技巧"
  150. :value="1"></el-option>
  151. <el-option label="乐理基础"
  152. :value="2"></el-option>
  153. <el-option label="乐器保养"
  154. :value="3"></el-option>
  155. <el-option label="乐曲演奏展示"
  156. :value="4"></el-option> -->
  157. </el-select>
  158. </el-form-item>
  159. <!-- 闪页管理 BANNER管理 APP按钮管理 广告管理 -->
  160. <el-form-item label="内容"
  161. v-show="type != 8 && type != 5 && type != 3 && type != 6"
  162. prop="content"
  163. :rules="[{ required: type != 8 && type != 5 && type != 3 && type != 6 ? true : false, message: '请编辑内容', trigger: 'blur' }]">
  164. <quill-editor class="ql-editor"
  165. v-model="form.content"
  166. ref="myQuillEditor"
  167. :options="editorOption"
  168. @change="onEditorChange($event)"></quill-editor>
  169. <el-upload class="ivu-upload"
  170. :show-upload-list="false"
  171. :headers="headers"
  172. :on-success="handleSuccess"
  173. accept=".jpg, .jpeg, .png, .gif"
  174. :max-size="2048"
  175. multiple
  176. action="/api-web/uploadFile">
  177. <Button icon="ios-cloud-upload-outline"></Button>
  178. </el-upload>
  179. </el-form-item>
  180. <el-form-item>
  181. <el-button @click="onSubmit('form')"
  182. type="primary">立即{{ pageType == "create" ? '创建' : '修改' }}</el-button>
  183. <el-button @click="onReSet('form')">重置</el-button>
  184. <el-button @click="onLook"
  185. v-if="type != 8 && type != 5 && type != 3 && type != 6">预览</el-button>
  186. </el-form-item>
  187. </el-form>
  188. </div>
  189. <el-dialog title="插入视频"
  190. width="500px"
  191. @close="onDialogClose('diologForm')"
  192. :visible.sync="dialogFormVisible">
  193. <el-form :model="dialogForm"
  194. ref="diologForm"
  195. :rules="dialogFormRules">
  196. <el-form-item label="封面图地址"
  197. prop="poster"
  198. :rules="[{required: uploadType == 2 ? true : false, message: '请上传封面图', trigger: 'blur'}]"
  199. label-width="120px">
  200. <el-upload class="avatar-uploader"
  201. style="line-height: 0;display: inline-block"
  202. action="/api-web/uploadFile"
  203. :headers="headers"
  204. :show-file-list="false"
  205. v-loading="uploadImgLoading"
  206. accept=".jpg, .jpeg, .png, .gif"
  207. :on-success="handleImgSuccess"
  208. :on-error="handleUploadImgError"
  209. :before-upload="beforeImgUpload">
  210. <img v-if="dialogForm.poster"
  211. :src="dialogForm.poster"
  212. class="avatar" />
  213. <i v-else
  214. class="el-icon-plus avatar-uploader-icon"></i>
  215. </el-upload>
  216. </el-form-item>
  217. <el-form-item label="视频类型"
  218. label-width="120px">
  219. <el-radio-group v-model="formRadio">
  220. <el-radio :label="1">外部链接</el-radio>
  221. <el-radio :label="2">上传</el-radio>
  222. </el-radio-group>
  223. </el-form-item>
  224. <el-form-item v-if="formRadio == 1"
  225. label="视频地址"
  226. label-width="120px"
  227. prop="url">
  228. <el-input v-model="dialogForm.url"
  229. style="width: 100%;"
  230. autocomplete="off"></el-input>
  231. </el-form-item>
  232. <el-form-item v-if="formRadio == 2"
  233. label="上传视频"
  234. label-width="120px"
  235. prop="videoUrl">
  236. <el-upload class="upload-demo"
  237. style="display: inline-block"
  238. v-loading="uploadLoading"
  239. action="/api-web/uploadFile"
  240. :before-upload="beforeUpload"
  241. :on-success="handleUploadSuccess"
  242. :on-error="handleUploadError"
  243. :show-file-list="false"
  244. accept=".mp4"
  245. :file-list="fileList"
  246. :on-exceed="handleExceed">
  247. <video style="width: 120px; height: 120px"
  248. v-if="dialogForm.videoUrl"
  249. type="video/mp4"
  250. preload="auto"
  251. :src="dialogForm.videoUrl"></video>
  252. <i v-else
  253. class="el-icon-plus avatar-uploader-icon"></i>
  254. </el-upload>
  255. <p class="imageSize">
  256. <!-- 广告管理 & 广告类型为 视频 -->
  257. <span v-if="uploadType == 2 && type == 8">上传视频尺寸建议:1242px * 2208px;</span><br />
  258. 只能上传mp4文件, 且不超过100M
  259. </p>
  260. </el-form-item>
  261. </el-form>
  262. <div slot="footer"
  263. class="dialog-footer">
  264. <el-button @click="dialogFormVisible = false">取 消</el-button>
  265. <el-button type="primary"
  266. @click="onVideoComfirm('diologForm')">确 定</el-button>
  267. </div>
  268. </el-dialog>
  269. <el-dialog width="375px" title="预览"
  270. :visible.sync="lookVisible">
  271. <div class="sd-container">
  272. <h2>{{ dataInfo.title }}</h2>
  273. <div class="titleInfo">
  274. <!-- <p>{{ dataInfo.tenantId == 2 ? '' : '大雅乐盟' }}</p> -->
  275. <p>{{ typeCheck(dataInfo.type) }}</p>
  276. <p>{{ dataInfo.updateTime }}</p>
  277. </div>
  278. <div class="msgWrap quill-editor ql-editor"
  279. v-html="dataInfo.content"></div>
  280. </div>
  281. </el-dialog>
  282. </div>
  283. </template>
  284. <script>
  285. import { newsQueryId, newsAdd, newsUpdate, newsTypeList } from "@/api/contentManager";
  286. import store from "@/store";
  287. import { getToken } from "@/utils/auth";
  288. import { vaildStudentUrl } from "@/utils/validate";
  289. // import E from 'wangeditor'
  290. // require styles
  291. import "quill/dist/quill.core.css";
  292. import "quill/dist/quill.snow.css";
  293. import "quill/dist/quill.bubble.css";
  294. import Quill from "quill";
  295. import { quillEditor } from "vue-quill-editor";
  296. // 工具栏配置
  297. const toolbarOptions = [
  298. ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
  299. ["blockquote", "code-block"], // 引用 代码块
  300. [{ header: 1 }, { header: 2 }], // 1、2 级标题
  301. [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
  302. [{ script: "sub" }, { script: "super" }], // 上标/下标
  303. [{ indent: "-1" }, { indent: "+1" }], // 缩进
  304. // [{'direction': 'rtl'}], // 文本方向
  305. [{ size: ["small", false, "large", "huge"] }], // 字体大小
  306. [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  307. [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  308. [{ font: [] }], // 字体种类
  309. [{ align: [] }], // 对齐方式
  310. ["clean"], // 清除文本格式
  311. ["image", "video"] // 链接、图片、视频
  312. // ["link", "image", "video"] // 链接、图片、视频
  313. ];
  314. // 标题
  315. const titleConfig = {
  316. "ql-bold": "加粗",
  317. "ql-color": "颜色",
  318. "ql-font": "字体",
  319. "ql-code": "插入代码",
  320. "ql-italic": "斜体",
  321. // 'ql-link': '添加链接',
  322. "ql-background": "背景颜色",
  323. "ql-size": "字体大小",
  324. "ql-strike": "删除线",
  325. "ql-script": "上标/下标",
  326. "ql-underline": "下划线",
  327. "ql-blockquote": "引用",
  328. "ql-header": "标题",
  329. "ql-indent": "缩进",
  330. "ql-list": "列表",
  331. "ql-align": "文本对齐",
  332. "ql-direction": "文本方向",
  333. "ql-code-block": "代码块",
  334. "ql-formula": "公式",
  335. "ql-image": "图片",
  336. "ql-video": "视频",
  337. "ql-clean": "清除字体样式",
  338. "ql-upload": "文件"
  339. };
  340. let validNum = (rule, value, callback) => {
  341. if (typeof value == 'string' || value == null) {
  342. callback(new Error('请输入显示时长'))
  343. } else if (value < 0) {
  344. callback(new Error('输入显示时长必须大于0'))
  345. } else {
  346. callback()
  347. }
  348. }
  349. // 这里引入修改过的video模块并注册
  350. import Video from "../quill/video.js";
  351. import dayjs from 'dayjs'
  352. Quill.register(Video, true);
  353. export default {
  354. name: "contentOperation",
  355. components: {
  356. quillEditor
  357. },
  358. data () {
  359. let that = this;
  360. const query = this.$route.query
  361. let url = ''
  362. // let url = query.type == 7 ? vaildStudentUrl() + "/#/knowledge" : vaildStudentUrl() + "/#/specialdetail"
  363. // console.log(query.type)
  364. if (query.type == 7) {
  365. url = vaildStudentUrl() + "/#/knowledge"
  366. } else if (query.type == 8 || query.type == 5) {
  367. url = ''
  368. } else {
  369. url = vaildStudentUrl() + "/#/specialdetail"
  370. }
  371. return {
  372. validNum: validNum,
  373. uploadType: 1, // 上传类型
  374. uploadStatus: false,
  375. categoryList: [],
  376. type: query.type,
  377. pageType: query.pageType,
  378. organId: null,
  379. headers: {
  380. Authorization: getToken()
  381. },
  382. content: null,
  383. dialogFormVisible: false,
  384. formRadio: 1,
  385. lookVisible: false,
  386. dataInfo: {
  387. title: '',
  388. type: query.type,
  389. updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
  390. content: null
  391. },
  392. editorIndex: 0, // 光标位置
  393. editorOption: {
  394. placeholder: "请输入内容",
  395. modules: {
  396. toolbar: {
  397. container: toolbarOptions,
  398. handlers: {
  399. image: function (value) {
  400. if (value) {
  401. // 调用iview图片上传
  402. document.querySelector(".ivu-upload .el-upload").click();
  403. } else {
  404. this.quill.format("image", false);
  405. }
  406. },
  407. video: function (value) {
  408. if (value) {
  409. that.dialogFormVisible = true;
  410. let editor = that.$refs.myQuillEditor.quill;
  411. // 光标所在位置
  412. that.editorIndex = editor.getSelection().index;
  413. } else {
  414. this.quill.format("image", false);
  415. }
  416. }
  417. }
  418. }
  419. }
  420. },
  421. dialogForm: {
  422. poster: null,
  423. url: null,
  424. videoUrl: null
  425. },
  426. uploadLoading: false,
  427. uploadImgLoading: false,
  428. fileList: [],
  429. dialogFormRules: {
  430. url: [{ required: true, message: "请输入视频地址", trigger: "blur" }],
  431. videoUrl: [{ required: true, message: "请上传视频", trigger: 'blur' }]
  432. },
  433. form: {
  434. title: null,
  435. order: null,
  436. tenantId: null,
  437. coverImage: null,
  438. videoCoverImage: null,
  439. attribute1: null, // 时长
  440. linkUrl: url,
  441. subjectIdList: null, // 声部编号
  442. type: query.type,
  443. status: 1,
  444. content: null,
  445. subType: null,
  446. actionTime: null,
  447. organIdList: null,
  448. },
  449. rules: {
  450. title: [
  451. { required: true, message: "请输入标题", trigger: "blur" },
  452. { min: 2, max: 30, message: "长度在 2 到 30 个字符", trigger: "blur" }
  453. ],
  454. coverImage: [
  455. { required: true, message: '请选择封面图或广告视频', trigger: "blur" }
  456. ],
  457. organIdList: [{ required: true, message: "请选择分部", trigger: "change" }],
  458. },
  459. imageSize: null,
  460. typeList: [], //子分类列表
  461. };
  462. },
  463. created () { },
  464. mounted () {
  465. const query = this.$route.query
  466. if (query.pageType == "create") {
  467. let url = ''
  468. if (query.type == 7) {
  469. url = vaildStudentUrl() + "/#/knowledge"
  470. } else if (query.type == 8 || query.type == 5) {
  471. url = ''
  472. } else {
  473. url = vaildStudentUrl() + "/#/specialdetail"
  474. }
  475. this.form = {
  476. title: null,
  477. order: null,
  478. coverImage: null,
  479. videoCoverImage: null,
  480. attribute1: null,
  481. linkUrl: url,
  482. type: query.type,
  483. subjectIdList: null,
  484. status: 1,
  485. content: null,
  486. tenantId: null,
  487. organIdList: null,
  488. subType: null,
  489. actionTime: null
  490. };
  491. this.$refs["form"].clearValidate();
  492. this.dialogForm = {
  493. poster: null,
  494. url: null,
  495. videoUrl: null
  496. }
  497. this.fileList = []
  498. }
  499. this.type = query.type;
  500. this.pageType = query.pageType;
  501. // 获取声部
  502. this.$store.dispatch('setSubjects')
  503. this.$store.dispatch("setBranchs");
  504. this.init();
  505. },
  506. methods: {
  507. init () {
  508. this.getList();
  509. this.addQuillTitle();
  510. const query = this.$route.query
  511. this.type = query.type;
  512. this.pageType = query.pageType;
  513. // this.form.type
  514. let tempTitle = {
  515. 1: "468px * 552px;图片不能超过 2M;",
  516. 2: "456px * 288px; 图片不能超过 2M;",
  517. 3: "686px * 140px; 图片不能超过 2M;",
  518. 4: "图片不能超过 2M;",
  519. 5: "图片不能超过 2M;",
  520. 6: "图片不能超过 2M;",
  521. 7: "图片不能超过 2M;",
  522. 8: "1242px * 2208px; 图片不能超过 2M;"
  523. };
  524. this.imageSize = tempTitle[this.form.type];
  525. this.$refs["form"].clearValidate();
  526. },
  527. addAdvVideo () {
  528. this.dialogFormVisible = true
  529. let dialogForm = this.dialogForm
  530. dialogForm.poster = this.form.videoCoverImage
  531. if (this.formRadio == 1) {
  532. dialogForm.url = this.form.coverImage
  533. } else {
  534. dialogForm.videoUrl = this.form.coverImage
  535. }
  536. this.uploadStatus = true
  537. },
  538. onVideoComfirm (formName) {
  539. this.$refs[formName].validate(valid => {
  540. if (valid) {
  541. let dialogForm = this.dialogForm;
  542. if (this.uploadStatus) {
  543. // 添加视频类型
  544. let form = this.form
  545. form.coverImage = this.formRadio == 1 ? dialogForm.url : dialogForm.videoUrl
  546. form.videoCoverImage = dialogForm.poster
  547. this.uploadStatus = false
  548. } else {
  549. // 编辑器输入视频
  550. // 获取富文本组件实例
  551. let quill = this.editor;
  552. // 插入图片,res为服务器返回的图片链接地址
  553. const params = {
  554. poster: dialogForm.poster,
  555. url: this.formRadio == 1 ? dialogForm.url : dialogForm.videoUrl,
  556. }
  557. quill.insertEmbed(this.editorIndex, "video", params);
  558. // 调整光标到最后
  559. quill.setSelection(this.editorIndex + 1, { preload: false });
  560. }
  561. this.dialogFormVisible = false;
  562. this.dialogForm = {
  563. poster: null,
  564. url: null,
  565. videoUrl: null
  566. };
  567. } else {
  568. return false;
  569. }
  570. });
  571. },
  572. onDialogClose (diologForm) {
  573. this.dialogForm = {
  574. poster: null,
  575. url: null,
  576. videoUrl: null
  577. }
  578. this.$refs[diologForm].resetFields()
  579. },
  580. addQuillTitle () {
  581. const oToolBar = document.querySelector(".ql-toolbar"),
  582. aButton = oToolBar.querySelectorAll("button"),
  583. aSelect = oToolBar.querySelectorAll("select");
  584. aButton.forEach(function (item) {
  585. if (item.className === "ql-script") {
  586. item.value === "sub" ? (item.title = "下标") : (item.title = "上标");
  587. } else if (item.className === "ql-indent") {
  588. item.value === "+1"
  589. ? (item.title = "向右缩进")
  590. : (item.title = "向左缩进");
  591. } else {
  592. item.title = titleConfig[item.classList[0]];
  593. }
  594. });
  595. aSelect.forEach(function (item) {
  596. item.parentNode.title = titleConfig[item.classList[0]];
  597. });
  598. },
  599. onSubmit (formName) {
  600. this.$refs[formName].validate(valid => {
  601. if (valid) {
  602. let { subjectIdList, organIdList, ...rest } = this.form
  603. let form = {
  604. ...rest,
  605. subjectIdList: subjectIdList ? subjectIdList.join(',') : null,
  606. organIdList: organIdList ? organIdList.join(',') : null
  607. }
  608. let actionTime = form.actionTime
  609. // console.log(actionTime)
  610. if(actionTime && actionTime.length > 0) {
  611. form.onlineTime = dayjs(actionTime[0]).format('YYYY-MM-DD HH:mm:ss')
  612. form.offlineTime = dayjs(actionTime[1]).format('YYYY-MM-DD HH:mm:ss')
  613. }
  614. if (this.pageType == "create") {
  615. if (form.id) {
  616. // 判断有没有Id,如果有则删除
  617. delete form.id;
  618. }
  619. if(this.type == 5) {
  620. form.status = 0
  621. }
  622. // return false
  623. newsAdd(form).then(res => {
  624. this.messageTips("添加", res);
  625. });
  626. } else if (this.pageType == "update") {
  627. newsUpdate(form).then(res => {
  628. this.messageTips("修改", res);
  629. });
  630. }
  631. } else {
  632. this.$nextTick(() => {
  633. let isError = document.getElementsByClassName('is-error')
  634. isError[0].scrollIntoView({
  635. block: 'center',
  636. behavior: 'smooth',
  637. })
  638. })
  639. return false;
  640. }
  641. });
  642. },
  643. messageTips (title, res) {
  644. if (res.code == 200) {
  645. this.$message.success(title + "成功");
  646. this.$store.dispatch('delVisitedViews', this.$route)
  647. this.$router.push({
  648. path: "/contentManager/contentManager",
  649. query: {
  650. tabrouter: this.typeIndex(this.type)
  651. }
  652. });
  653. } else {
  654. this.$message.error(res.msg);
  655. }
  656. },
  657. onCancel () {
  658. this.$store.dispatch('delVisitedViews', this.$route)
  659. this.$router.push({
  660. path: "/contentManager/contentManager",
  661. query: {
  662. tabrouter: this.typeIndex(this.type)
  663. }
  664. });
  665. },
  666. handleSuccess (res) {
  667. // 获取富文本组件实例
  668. let quill = this.editor;
  669. // 如果上传成功
  670. if (res.code) {
  671. // 获取光标所在位置
  672. let length = quill.getSelection().index;
  673. // 插入图片,res为服务器返回的图片链接地址
  674. quill.insertEmbed(length, "image", res.data.url);
  675. // 调整光标到最后
  676. quill.setSelection(length + 1);
  677. } else {
  678. // 提示信息,需引入Message
  679. this.$message.error("图片插入失败");
  680. }
  681. },
  682. onReSet (formName) {
  683. const query = this.$route.query
  684. let url = ''
  685. if (query.type == 7) {
  686. url = vaildStudentUrl() + "/#/knowledge"
  687. } else if (query.type == 8 || query.type == 5) {
  688. url = ''
  689. } else {
  690. url = vaildStudentUrl() + "/#/specialdetail"
  691. }
  692. this.form = {
  693. title: null,
  694. order: null,
  695. coverImage: null,
  696. videoCoverImage: null,
  697. attribute1: null,
  698. linkUrl: url,
  699. type: query.type,
  700. status: 1,
  701. content: null,
  702. tenantId: null,
  703. organIdList: null,
  704. subType: null,
  705. actionTime: null
  706. };
  707. this.$refs[formName].resetFields();
  708. },
  709. onLook () {
  710. // 预览
  711. let dataInfo = this.dataInfo
  712. dataInfo.title = this.form.title
  713. dataInfo.content = this.form.content
  714. // 处理图片显示问题
  715. setTimeout(() => {
  716. let imgNode = document.querySelectorAll(".msgWrap img");
  717. if (imgNode.length > 0) {
  718. imgNode.forEach(item => {
  719. item.style.width = "100%";
  720. });
  721. }
  722. let videoNode = document.querySelectorAll(".msgWrap .ql-video");
  723. if (videoNode.length > 0) {
  724. videoNode.forEach(item => {
  725. item.style.width = "100%";
  726. item.style.height = "195px";
  727. });
  728. }
  729. }, 500);
  730. this.lookVisible = true
  731. },
  732. async getList () {
  733. if(this.type == 7 || this.type == 2) {
  734. await newsTypeList({ parentId: this.type }).then(res => {
  735. console.log(res)
  736. if(res.code ==200) {
  737. this.typeList = res.data
  738. }
  739. })
  740. }
  741. if (this.pageType == "create") {
  742. return;
  743. } else {
  744. newsQueryId({ id: this.$route.query.id }).then(res => {
  745. if (res.code == 200) {
  746. let result = res.data;
  747. let form = this.form;
  748. if (result.videoCoverImage) {
  749. this.uploadType = 2
  750. } else {
  751. this.uploadType = 1
  752. }
  753. let tempActionTime = null
  754. if(result.onlineTime && result.offlineTime) {
  755. tempActionTime = [result.onlineTime, result.offlineTime]
  756. }
  757. let subject = result.subjectIdList ? result.subjectIdList.split(',') : []
  758. let organ = result.organIdList ? result.organIdList.split(',') : []
  759. this.form = {
  760. id: result.id,
  761. title: result.title,
  762. order: result.order,
  763. coverImage: result.coverImage,
  764. videoCoverImage: result.videoCoverImage,
  765. attribute1: Number(result.attribute1),
  766. linkUrl: result.linkUrl,
  767. type: result.type,
  768. status: result.status,
  769. tenantId: result.tenantId.toString(),
  770. subjectIdList: subject.map(item => { return +item }),
  771. organIdList: organ.map(item => { return +item }),
  772. memo: result.memo,
  773. content: result.content,
  774. actionTime: tempActionTime,
  775. subType: result.subType ? result.subType : null
  776. };
  777. this.dataInfo.updateTime = result.updateTime
  778. }
  779. });
  780. }
  781. },
  782. handleUploadImgError (file) {
  783. this.uploadImgLoading = false
  784. this.$message.error('上传失败')
  785. },
  786. handleImgSuccess (res, file) {
  787. this.uploadImgLoading = false
  788. if (res.code == 200) {
  789. this.dialogForm.poster = res.data.url
  790. } else {
  791. this.$message.error('上传失败')
  792. }
  793. },
  794. beforeImgUpload (file) {
  795. const imageType = {
  796. "image/png": true,
  797. "image/jpeg": true,
  798. "image/gif": true
  799. };
  800. const isImage = imageType[file.type];
  801. const isLt2M = file.size / 1024 / 1024 < 2;
  802. // console.log(isImage, isLt2M)
  803. if (!isImage) {
  804. this.$message.error("只能上传图片格式!");
  805. }
  806. if (!isLt2M) {
  807. this.$message.error("上传图片大小不能超过 2MB!");
  808. }
  809. if (isImage && isLt2M) {
  810. this.uploadImgLoading = true
  811. }
  812. return isImage && isLt2M;
  813. },
  814. handleAvatarSuccess (res, file) {
  815. if (res.code == 200) {
  816. this.form.coverImage = res.data.url;
  817. } else {
  818. this.$message.error('上传失败')
  819. }
  820. },
  821. beforeAvatarUpload (file) {
  822. const imageType = {
  823. "image/png": true,
  824. "image/jpeg": true,
  825. "image/gif": true
  826. };
  827. const isImage = imageType[file.type];
  828. const isLt2M = file.size / 1024 / 1024 < 2;
  829. if (!isImage) {
  830. this.$message.error("只能上传图片格式!");
  831. }
  832. if (!isLt2M) {
  833. this.$message.error("上传图片大小不能超过 2M!");
  834. }
  835. return isImage && isLt2M;
  836. },
  837. typeChange (type) {
  838. let tempTitle = {
  839. 1: "精彩活动",
  840. 2: "热门资讯",
  841. 4: "专项训练",
  842. 5: "闪页管理",
  843. 3: "BANNER管理",
  844. 6: "APP按钮管理",
  845. 7: "知识库管理",
  846. 8: "广告管理"
  847. };
  848. return tempTitle[type];
  849. },
  850. typeCheck (type) {
  851. // 精彩活动 1 0
  852. // 热门资讯 2 1
  853. // 专项训练 4 2
  854. // 闪页管理 5 3
  855. // BANNER管理 3 4
  856. // APP按钮管理 6 5
  857. // 知识库 7 5
  858. let params = {
  859. 1: '精彩活动',
  860. 2: '热门资讯',
  861. 4: '专项训练',
  862. 7: '知识库'
  863. }
  864. return params[type] ? params[type] : '大雅乐盟'
  865. },
  866. typeIndex (type) {
  867. let tempTitle = {
  868. 1: 0,
  869. 2: 1,
  870. 3: 4,
  871. 4: 2,
  872. 5: 3,
  873. 6: 5,
  874. 7: 6,
  875. 8: 7
  876. };
  877. return tempTitle[type];
  878. },
  879. onEditorChange ({ quill, html, text }) {
  880. this.form.content = html;
  881. },
  882. beforeUpload (file) {
  883. // const isJPG = file.type === 'image/jpeg';
  884. const isLt2M = file.size / 1024 / 1024 < 100;
  885. // if (!isJPG) {
  886. // this.$message.error('上传头像图片只能是 JPG 格式!');
  887. // }
  888. if (!isLt2M) {
  889. this.$message.error('上传视频大小不能超过 100MB!');
  890. }
  891. this.uploadLoading = true
  892. return isLt2M;
  893. },
  894. handleUploadError (file) {
  895. this.uploadLoading = false
  896. this.$message.error('上传视频失败')
  897. },
  898. handleUploadSuccess (file, fileList) {
  899. this.uploadLoading = false
  900. if (file.code == 200) {
  901. this.$message.success('上传视频成功')
  902. this.dialogForm.videoUrl = file.data.url;
  903. } else {
  904. this.$message.error('上传视频失败')
  905. }
  906. },
  907. handleExceed (files, fileList) {
  908. this.$message.error('您已上传过视频')
  909. // this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
  910. }
  911. },
  912. computed: {
  913. editor () {
  914. return this.$refs.myQuillEditor.quill;
  915. }
  916. }
  917. };
  918. </script>
  919. <style lang="scss" scoped>
  920. .m-container {
  921. min-width: 100%;
  922. }
  923. .el-input {
  924. width: 400px;
  925. }
  926. /deep/.ql-editor {
  927. min-height: 300px;
  928. padding: 0;
  929. }
  930. /deep/.ql-container .ql-editor {
  931. max-height: 500px;
  932. }
  933. .el-button--primary {
  934. background: #14928a;
  935. border-color: #14928a;
  936. color: #fff;
  937. &:hover,
  938. &:active,
  939. &:focus {
  940. background: #14928a;
  941. border-color: #14928a;
  942. color: #fff;
  943. }
  944. }
  945. .el-row {
  946. margin-top: 40px;
  947. }
  948. .el-col {
  949. display: flex;
  950. align-items: center;
  951. margin-bottom: 20px;
  952. justify-content: flex-end;
  953. margin-right: 50%;
  954. }
  955. .el-input-group {
  956. width: 200px;
  957. margin: 0 20px;
  958. }
  959. /deep/.el-tree-node__content {
  960. height: 40px !important;
  961. }
  962. /deep/.avatar-uploader .el-upload,
  963. /deep/.upload-demo .el-upload {
  964. border-radius: 6px;
  965. cursor: pointer;
  966. position: relative;
  967. overflow: hidden;
  968. }
  969. .avatar-uploader .el-upload:hover {
  970. border-color: #409eff;
  971. }
  972. .avatar-uploader-icon {
  973. border: 1px dashed #d9d9d9;
  974. font-size: 28px;
  975. color: #8c939d;
  976. width: 120px;
  977. height: 120px;
  978. line-height: 120px;
  979. text-align: center;
  980. }
  981. .avatar {
  982. width: 120px;
  983. height: 120px;
  984. display: block;
  985. }
  986. .ivu-upload {
  987. display: none;
  988. }
  989. .sd-container {
  990. // padding: 15px;
  991. h2 {
  992. height: auto;
  993. font-weight: 500;
  994. color: rgba(68, 68, 68, 1);
  995. line-height: 37px;
  996. font-size: 26px;
  997. margin-bottom: 10px;
  998. }
  999. .titleInfo {
  1000. height: 15px;
  1001. line-height: 15px;
  1002. display: flex;
  1003. flex-direction: row;
  1004. justify-content: space-between;
  1005. color: #444;
  1006. margin-bottom: 25px;
  1007. }
  1008. .imgWrap {
  1009. /* width: 100;
  1010. height: 1.45rem; */
  1011. margin-bottom: 0.15rem;
  1012. p {
  1013. font-size: 0.16rem;
  1014. font-family: PingFangSC;
  1015. font-weight: 400;
  1016. color: rgba(68, 68, 68, 1);
  1017. line-height: 0.28rem;
  1018. text-indent: 0.32rem;
  1019. }
  1020. img {
  1021. width: 100%;
  1022. }
  1023. }
  1024. }
  1025. .imageSize {
  1026. color: red;
  1027. line-height: 1.5;
  1028. }
  1029. </style>