contentOperation.vue 34 KB

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