contentOperation.vue 32 KB

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