contentOperation.vue 35 KB

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