contentOperation.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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="form.title"></el-input>
  16. </el-form-item>
  17. <el-form-item label="排序值">
  18. <el-input v-model="form.order"></el-input>
  19. </el-form-item>
  20. <el-form-item label="链接地址"
  21. prop="linkUrl">
  22. <el-input v-model="form.linkUrl"></el-input>
  23. </el-form-item>
  24. <el-form-item label="封面图"
  25. prop="coverImage">
  26. <el-upload class="avatar-uploader"
  27. action="/api-web/uploadFile"
  28. :headers="headers"
  29. :show-file-list="false"
  30. :on-success="handleAvatarSuccess"
  31. :before-upload="beforeAvatarUpload">
  32. <img v-if="form.coverImage"
  33. :src="form.coverImage"
  34. class="avatar">
  35. <i v-else
  36. class="el-icon-plus avatar-uploader-icon"></i>
  37. </el-upload>
  38. <p class="imageSize" v-if="imageSize">上传图片尺寸为:{{ imageSize }}</p>
  39. </el-form-item>
  40. <el-form-item label="内容"
  41. prop="content">
  42. <!-- bidirectional data binding(双向数据绑定) -->
  43. <quill-editor v-model="form.content"
  44. ref="myQuillEditor"
  45. :options="editorOption"
  46. @change="onEditorChange($event)">
  47. </quill-editor>
  48. <el-upload class="ivu-upload"
  49. :show-upload-list="false"
  50. :headers="headers"
  51. :on-success="handleSuccess"
  52. :format="['jpg','jpeg','png','gif']"
  53. :max-size="2048"
  54. multiple
  55. action="/api-web/uploadFile">
  56. <Button icon="ios-cloud-upload-outline"></Button>
  57. </el-upload>
  58. </el-form-item>
  59. <el-form-item>
  60. <el-button @click="onSubmit('form')"
  61. type="primary">立即{{ pageType == "create" ? '创建' : '修改' }}</el-button>
  62. <el-button @click="onReSet('form')">重置</el-button>
  63. </el-form-item>
  64. </el-form>
  65. </div>
  66. </div>
  67. </template>
  68. <script>
  69. import { newsQueryId, newsAdd, newsUpdate } from '@/api/contentManager'
  70. import store from '@/store'
  71. import { getToken } from '@/utils/auth'
  72. import { vaildStudentUrl } from '@/utils/validate'
  73. // import E from 'wangeditor'
  74. // require styles
  75. import 'quill/dist/quill.core.css'
  76. import 'quill/dist/quill.snow.css'
  77. import 'quill/dist/quill.bubble.css'
  78. import { quillEditor } from 'vue-quill-editor'
  79. // 工具栏配置
  80. const toolbarOptions = [
  81. ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
  82. ["blockquote", "code-block"], // 引用 代码块
  83. [{ header: 1 }, { header: 2 }], // 1、2 级标题
  84. [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
  85. [{ script: "sub" }, { script: "super" }], // 上标/下标
  86. [{ indent: "-1" }, { indent: "+1" }], // 缩进
  87. // [{'direction': 'rtl'}], // 文本方向
  88. [{ size: ["small", false, "large", "huge"] }], // 字体大小
  89. [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  90. [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  91. [{ font: [] }], // 字体种类
  92. [{ align: [] }], // 对齐方式
  93. ["clean"], // 清除文本格式
  94. ["link", "image", "video"] // 链接、图片、视频
  95. ];
  96. // 标题
  97. const titleConfig = {
  98. 'ql-bold': '加粗',
  99. 'ql-color': '颜色',
  100. 'ql-font': '字体',
  101. 'ql-code': '插入代码',
  102. 'ql-italic': '斜体',
  103. 'ql-link': '添加链接',
  104. 'ql-background': '背景颜色',
  105. 'ql-size': '字体大小',
  106. 'ql-strike': '删除线',
  107. 'ql-script': '上标/下标',
  108. 'ql-underline': '下划线',
  109. 'ql-blockquote': '引用',
  110. 'ql-header': '标题',
  111. 'ql-indent': '缩进',
  112. 'ql-list': '列表',
  113. 'ql-align': '文本对齐',
  114. 'ql-direction': '文本方向',
  115. 'ql-code-block': '代码块',
  116. 'ql-formula': '公式',
  117. 'ql-image': '图片',
  118. 'ql-video': '视频',
  119. 'ql-clean': '清除字体样式',
  120. 'ql-upload': '文件'
  121. };
  122. export default {
  123. components: {
  124. quillEditor
  125. },
  126. data () {
  127. return {
  128. categoryList: [],
  129. type: this.$route.query.type,
  130. pageType: this.$route.query.pageType,
  131. organId: null,
  132. headers: {
  133. Authorization: getToken()
  134. },
  135. content: null,
  136. editorOption: {
  137. placeholder: '请输入内容',
  138. modules: {
  139. toolbar: {
  140. container: toolbarOptions,
  141. handlers: {
  142. 'image': function (value) {
  143. if (value) {
  144. // 调用iview图片上传
  145. document.querySelector('.ivu-upload .el-upload').click()
  146. } else {
  147. this.quill.format('image', false);
  148. }
  149. }
  150. }
  151. }
  152. }
  153. },
  154. form: {
  155. title: null,
  156. order: null,
  157. coverImage: null,
  158. linkUrl: vaildStudentUrl() + '/#/specialdetail',
  159. type: this.$route.query.type,
  160. status: 1,
  161. content: null
  162. },
  163. rules: {
  164. title: [{ required: true, message: '请输入标题', trigger: 'blur' },
  165. { min: 2, max: 30, message: '长度在 2 到 30 个字符', trigger: 'blur' }],
  166. linkUrl: [{ required: true, message: '请输入连接地址', trigger: 'blur' }],
  167. coverImage: [{ required: true, message: '请选择封面图', trigger: 'blur' }],
  168. content: [{ required: true, message: '请编辑内容', trigger: 'blur' }]
  169. },
  170. imageSize: null
  171. }
  172. },
  173. mounted () {
  174. // console.log('this is current quill instance object', this.editor)
  175. this.getList()
  176. this.addQuillTitle()
  177. // this.form.type
  178. let tempTitle = {
  179. 1: "468px * 552px",
  180. 2: "456px * 288px",
  181. 3: "686px * 140px",
  182. 4: null
  183. }
  184. this.imageSize = tempTitle[this.form.type]
  185. },
  186. methods: {
  187. addQuillTitle () {
  188. const oToolBar = document.querySelector('.ql-toolbar'),
  189. aButton = oToolBar.querySelectorAll('button'),
  190. aSelect = oToolBar.querySelectorAll('select');
  191. aButton.forEach(function (item) {
  192. if (item.className === 'ql-script') {
  193. item.value === 'sub' ? item.title = '下标' : item.title = '上标';
  194. } else if (item.className === 'ql-indent') {
  195. item.value === '+1' ? item.title = '向右缩进' : item.title = '向左缩进';
  196. } else {
  197. item.title = titleConfig[item.classList[0]];
  198. }
  199. });
  200. aSelect.forEach(function (item) {
  201. item.parentNode.title = titleConfig[item.classList[0]];
  202. });
  203. },
  204. onSubmit (formName) {
  205. this.$refs[formName].validate((valid) => {
  206. if (valid) {
  207. if (this.pageType == 'create') {
  208. if (this.form.id) { // 判断有没有Id,如果有则删除
  209. delete this.form.id
  210. }
  211. // return false
  212. newsAdd(this.form).then(res => {
  213. this.messageTips('添加', res)
  214. })
  215. } else if (this.pageType == 'update') {
  216. newsUpdate(this.form).then(res => {
  217. this.messageTips('修改', res)
  218. })
  219. }
  220. } else {
  221. return false
  222. }
  223. })
  224. },
  225. messageTips (title, res) {
  226. if (res.code == 200) {
  227. this.$message.success(title + '成功')
  228. this.$router.push({
  229. path: '/contentManager/contentManager',
  230. query: {
  231. type: this.typeIndex(this.type)
  232. }
  233. })
  234. } else {
  235. this.$message.error(res.msg)
  236. }
  237. },
  238. onCancel () {
  239. this.$router.push({
  240. path: '/contentManager/contentManager',
  241. query: {
  242. type: this.typeIndex(this.type)
  243. }
  244. })
  245. },
  246. handleSuccess (res) {
  247. // 获取富文本组件实例
  248. let quill = this.editor
  249. // 如果上传成功
  250. console.log(res)
  251. if (res.code) {
  252. // 获取光标所在位置
  253. let length = quill.getSelection().index;
  254. // 插入图片,res为服务器返回的图片链接地址
  255. quill.insertEmbed(length, 'image', res.data.url)
  256. // 调整光标到最后
  257. quill.setSelection(length + 1)
  258. } else {
  259. // 提示信息,需引入Message
  260. this.$message.error('图片插入失败')
  261. }
  262. },
  263. onReSet (formName) {
  264. this.$refs[formName].resetFields()
  265. },
  266. getList () {
  267. if (this.pageType == 'create') return false
  268. newsQueryId({ id: this.$route.query.id }).then(res => {
  269. if (res.code == 200) {
  270. let result = res.data
  271. let form = this.form
  272. this.form = {
  273. id: result.id,
  274. title: result.title,
  275. order: result.order,
  276. coverImage: result.coverImage,
  277. linkUrl: result.linkUrl,
  278. type: result.type,
  279. status: result.status,
  280. content: result.content
  281. }
  282. }
  283. })
  284. },
  285. handleAvatarSuccess (res, file) {
  286. this.form.coverImage = res.data.url
  287. },
  288. beforeAvatarUpload (file) {
  289. const imageType = {
  290. 'image/png': true,
  291. 'image/jpeg': true
  292. }
  293. const isImage = imageType[file.type]
  294. const isLt2M = file.size / 1024 / 1024 < 2
  295. if (!isImage) {
  296. this.$message.error('只能上传图片格式!')
  297. }
  298. if (!isLt2M) {
  299. this.$message.error('上传头像图片大小不能超过 2MB!')
  300. }
  301. return isImage && isLt2M;
  302. },
  303. typeChange (type) {
  304. let tempTitle = {
  305. 1: "精彩活动",
  306. 2: "热门资讯",
  307. 3: "活动列表",
  308. 4: "专项训练"
  309. }
  310. return tempTitle[type]
  311. },
  312. typeIndex (type) {
  313. let tempTitle = {
  314. 3: 0,
  315. 1: 1,
  316. 2: 2,
  317. 4: 3
  318. }
  319. return tempTitle[type]
  320. },
  321. // onEditorBlur(quill) {
  322. // console.log('editor blur!', quill)
  323. // },
  324. // onEditorFocus(quill) {
  325. // console.log('editor focus!', quill)
  326. // },
  327. // onEditorReady(quill) {
  328. // console.log('editor ready!', quill)
  329. // },
  330. onEditorChange ({ quill, html, text }) {
  331. this.form.content = html
  332. }
  333. },
  334. computed: {
  335. editor () {
  336. return this.$refs.myQuillEditor.quill
  337. }
  338. },
  339. }
  340. </script>
  341. <style lang="scss" scoped>
  342. .m-container {
  343. min-width: 100%;
  344. }
  345. .el-input {
  346. width: 400px;
  347. }
  348. /deep/.ql-editor {
  349. min-height: 300px;
  350. }
  351. .el-button--primary {
  352. background: #14928a;
  353. border-color: #14928a;
  354. color: #fff;
  355. &:hover,
  356. &:active,
  357. &:focus {
  358. background: #14928a;
  359. border-color: #14928a;
  360. color: #fff;
  361. }
  362. }
  363. .el-row {
  364. margin-top: 40px;
  365. }
  366. .el-col {
  367. display: flex;
  368. align-items: center;
  369. margin-bottom: 20px;
  370. justify-content: flex-end;
  371. margin-right: 50%;
  372. }
  373. .el-input-group {
  374. width: 200px;
  375. margin: 0 20px;
  376. }
  377. /deep/.el-tree-node__content {
  378. height: 40px !important;
  379. }
  380. /deep/.avatar-uploader .el-upload {
  381. border: 1px dashed #d9d9d9;
  382. border-radius: 6px;
  383. cursor: pointer;
  384. position: relative;
  385. overflow: hidden;
  386. }
  387. .avatar-uploader .el-upload:hover {
  388. border-color: #409eff;
  389. }
  390. .avatar-uploader-icon {
  391. font-size: 28px;
  392. color: #8c939d;
  393. width: 120px;
  394. height: 120px;
  395. line-height: 120px;
  396. text-align: center;
  397. }
  398. .avatar {
  399. width: 120px;
  400. height: 120px;
  401. display: block;
  402. }
  403. .ivu-upload {
  404. display: none;
  405. }
  406. </style>