form.ftl 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>文章</title>
  5. <#include "../../include/head-file.ftl">
  6. </head>
  7. <body>
  8. <div id="form" v-cloak>
  9. <el-header class="ms-header ms-tr" height="50px">
  10. <el-button type="primary" icon="iconfont icon-baocun" size="mini" @click="save()" :loading="saveDisabled">保存
  11. </el-button>
  12. <el-button size="mini" icon="iconfont icon-fanhui" plain onclick="javascript:history.go(-1)">返回
  13. </el-button>
  14. </el-header>
  15. <el-main class="ms-container" style="position:relative;">
  16. <el-scrollbar style="height: 100%;">
  17. <el-tabs v-model="activeName" style="height: calc(100% - 10px);">
  18. <el-tab-pane style="position:relative;" v-for="(item, index) in editableTabs" :key="index"
  19. :label="item.title" :name="item.name">
  20. <el-form v-if="item.title=='文章编辑'" ref="form" :model="form" :rules="rules" label-width="120px"
  21. size="mini">
  22. <el-row gutter="0" justify="start" align="top">
  23. <el-col :span="returnIsShow?'12':'24'">
  24. <el-form-item label="文章标题" prop="contentTitle">
  25. <template slot='label'>文章标题
  26. <el-popover placement="top-start" title="提示" trigger="hover">
  27. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  28. target="_blank">${'$'}{field.title}</a>
  29. <i class="el-icon-question" slot="reference"></i>
  30. </el-popover>
  31. </template>
  32. <el-input v-model="form.contentTitle"
  33. :disabled="false"
  34. :style="{width: '100%'}"
  35. :clearable="true"
  36. placeholder="请输入文章标题">
  37. </el-input>
  38. </el-form-item>
  39. </el-col>
  40. <el-col span="12" v-if="returnIsShow">
  41. <el-form-item label="所属栏目" prop="categoryId">
  42. <template slot='label'>所属栏目
  43. <el-popover placement="top-start" title="提示" trigger="hover">
  44. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  45. target="_blank">${'$'}{field.typetitle}</a><br/>
  46. 不能为链接和封面类型新建文章
  47. <i class="el-icon-question" slot="reference"></i>
  48. </el-popover>
  49. </template>
  50. <tree-select :props="{value: 'id',label: 'categoryTitle',children: 'children'}"
  51. :options="contentCategoryIdOptions" :style="{width:'100%'}"
  52. @change="categoryChange"
  53. v-model="form.categoryId"></tree-select>
  54. </el-form-item>
  55. </el-col>
  56. </el-row>
  57. <el-row
  58. gutter="0"
  59. justify="start" align="top">
  60. <el-col span="12">
  61. <el-form-item label="文章类型" prop="contentType">
  62. <template slot='label'>文章类型
  63. <el-popover placement="top-start" title="提示" trigger="hover">
  64. 用于筛选文章,在自定义字典添加
  65. <i class="el-icon-question" slot="reference"></i>
  66. </el-popover>
  67. </template>
  68. <el-select v-model="form.contentType"
  69. :style="{width: '100%'}"
  70. :filterable="false"
  71. :disabled="false"
  72. :multiple="true" :clearable="true"
  73. placeholder="请选择文章类型">
  74. <el-option v-for='item in contentTypeOptions' :key="item.dictValue"
  75. :value="item.dictValue"
  76. :label="item.dictLabel"></el-option>
  77. </el-select>
  78. </el-form-item>
  79. </el-col>
  80. <el-col span="12">
  81. <el-form-item label="发布时间" prop="contentDatetime">
  82. <template slot='label'>发布时间
  83. <el-popover placement="top-start" title="提示" trigger="hover">
  84. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  85. target="_blank">${'$'}{field.date?string("yyyy-MM-dd")}</a>
  86. <i class="el-icon-question" slot="reference"></i>
  87. </el-popover>
  88. </template>
  89. <el-date-picker
  90. v-model="form.contentDatetime"
  91. placeholder="请选择发布时间"
  92. start-placeholder=""
  93. end-placeholder=""
  94. :readonly="false"
  95. :disabled="false"
  96. :editable="true"
  97. :clearable="true"
  98. format="yyyy-MM-dd HH:mm:ss"
  99. value-format="yyyy-MM-dd HH:mm:ss"
  100. :style="{width:'100%'}"
  101. type="datetime">
  102. </el-date-picker>
  103. </el-form-item>
  104. </el-col>
  105. </el-row>
  106. <el-row
  107. gutter="0"
  108. justify="start" align="top">
  109. <el-col span="12">
  110. <el-form-item label="文章作者" prop="contentAuthor">
  111. <template slot='label'>文章作者
  112. <el-popover placement="top-start" title="提示" trigger="hover">
  113. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  114. target="_blank">${'$'}{field.author}</a>
  115. <i class="el-icon-question" slot="reference"></i>
  116. </el-popover>
  117. </template>
  118. <el-input v-model="form.contentAuthor"
  119. :disabled="false"
  120. :style="{width: '100%'}"
  121. :clearable="true"
  122. placeholder="请输入文章作者">
  123. </el-input>
  124. </el-form-item>
  125. </el-col>
  126. <el-col span="12">
  127. <el-form-item label="文章来源" prop="contentSource">
  128. <template slot='label'>文章来源
  129. <el-popover placement="top-start" title="提示" trigger="hover">
  130. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  131. target="_blank">${'$'}{field.source}</a>
  132. <i class="el-icon-question" slot="reference"></i>
  133. </el-popover>
  134. </template>
  135. <el-input v-model="form.contentSource"
  136. :disabled="false"
  137. :style="{width: '100%'}"
  138. :clearable="true"
  139. placeholder="请输入文章来源">
  140. </el-input>
  141. </el-form-item>
  142. </el-col>
  143. </el-row>
  144. <el-row
  145. gutter="0"
  146. justify="start" align="top">
  147. <el-col span="12">
  148. <el-form-item label="" prop="contentDisplay">
  149. <template slot='label'>是否显示
  150. <el-popover slot="label" placement="top-start" title="提示" width="200"
  151. trigger="hover"
  152. content="选择否后前端将不显示,需要重新生成才有效果">
  153. <i class="el-icon-question" slot="reference"></i>
  154. </el-popover>
  155. </template>
  156. <el-radio-group v-model="form.contentDisplay"
  157. :style="{width: ''}"
  158. :disabled="false">
  159. <el-radio :style="{display: true ? 'inline-block' : 'block'}"
  160. :label="item.value"
  161. v-for='(item, index) in contentDisplayOptions'
  162. :key="item.value + index">
  163. {{true? item.label : item.value}}
  164. </el-radio>
  165. </el-radio-group>
  166. </el-form-item>
  167. </el-col>
  168. <el-col span="12">
  169. <el-form-item label="自定义顺序" prop="contentSort">
  170. <el-input-number
  171. v-model="form.contentSort"
  172. :disabled="false"
  173. controls-position="">
  174. </el-input-number>
  175. </el-form-item>
  176. </el-col>
  177. </el-row>
  178. <el-form-item label="" prop="contentImg">
  179. <template slot='label'>文章缩略图
  180. <el-popover placement="top-start" title="提示" trigger="hover">
  181. 文章缩略图,支持jpg格式
  182. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  183. target="_blank">${'$'}{field.litpic}</a>
  184. <i class="el-icon-question" slot="reference"></i>
  185. </el-popover>
  186. </template>
  187. <el-upload
  188. :file-list="form.contentImg"
  189. :action="ms.base+'/file/upload.do'"
  190. :on-remove="contentImghandleRemove"
  191. :style="{width:''}"
  192. :limit="1"
  193. :on-exceed="contentImghandleExceed"
  194. :disabled="false"
  195. :data="{uploadPath:'/cms/content','isRename':true ,'appId':true}"
  196. :on-success="contentImgSuccess"
  197. accept="image/*"
  198. list-type="picture-card">
  199. <i class="el-icon-plus"></i>
  200. <div slot="tip" class="el-upload__tip">最多上传1张图片</div>
  201. </el-upload>
  202. </el-form-item>
  203. <el-form-item label="关键字" prop="contentKeyword">
  204. <template slot='label'>关键字
  205. <el-popover placement="top-start" title="提示" trigger="hover">
  206. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  207. target="_blank">${'$'}{field.keyword}</a>
  208. <i class="el-icon-question" slot="reference"></i>
  209. </el-popover>
  210. </template>
  211. <el-input
  212. type="textarea" :rows="5"
  213. :disabled="false"
  214. v-model="form.contentKeyword"
  215. :style="{width: '100%'}"
  216. placeholder="请输入文章关键字">
  217. </el-input>
  218. </el-form-item>
  219. <el-form-item label="描述" prop="contentDescription">
  220. <template slot='label'>描述
  221. <el-popover placement="top-start" title="提示" trigger="hover">
  222. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  223. target="_blank">${'$'}{field.descrip}</a>
  224. <i class="el-icon-question" slot="reference"></i>
  225. </el-popover>
  226. </template>
  227. <el-input
  228. type="textarea" :rows="5"
  229. :disabled="false"
  230. v-model="form.contentDescription"
  231. :style="{width: '100%'}"
  232. placeholder="请输入对该文章的简短描述,以便用户查看文章简略">
  233. </el-input>
  234. </el-form-item>
  235. <el-form-item label="文章内容" prop="contentDetails">
  236. <template slot='label'>文章内容
  237. <el-popover placement="top-start" title="提示" trigger="hover">
  238. <a href="http://doc.mingsoft.net/plugs-cms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
  239. target="_blank">${'$'}{field.content}</a>
  240. <i class="el-icon-question" slot="reference"></i>
  241. </el-popover>
  242. </template>
  243. <vue-ueditor-wrap style="line-height: 0px" v-model="form.contentDetails"
  244. :config="editorConfig"></vue-ueditor-wrap>
  245. </el-form-item>
  246. </el-form>
  247. <div :id="'model'+index" v-else></div>
  248. </el-tab-pane>
  249. </el-tabs>
  250. </el-scrollbar>
  251. </el-main>
  252. </div>
  253. </body>
  254. </html>
  255. <script>
  256. var form = new Vue({
  257. el: '#form',
  258. data: function () {
  259. return {
  260. saveDisabled: false,
  261. activeName: 'form',
  262. //自定义模型实例
  263. model: undefined,
  264. editableTabs: [{
  265. title: '文章编辑',
  266. name: 'form'
  267. }],
  268. editorConfig: {
  269. imageScaleEnabled: true,
  270. autoHeightEnabled: true,
  271. autoFloatEnabled: false,
  272. scaleEnabled: true,
  273. compressSide: 0,
  274. maxImageSideLength: 1000,
  275. maximumWords: 2000,
  276. initialFrameWidth: '100%',
  277. initialFrameHeight: 400,
  278. serverUrl: ms.base + "/static/plugins/ueditor/1.4.3.1/jsp/editor.do?jsonConfig=%7BvideoUrlPrefix:\'" + ms.base + "\',fileUrlPrefix:\'" + ms.base + "\',imageUrlPrefix:\'" + ms.base + "\',imagePathFormat:\'/upload/${appId}/cms/content/editor/%7Btime%7D\',filePathFormat:\'/upload/${appId}/cms/content/editor/%7Btime%7D\',videoPathFormat:\'/upload/${appId}/cms/content/editor/%7Btime%7D\'%7D",
  279. UEDITOR_HOME_URL: ms.base + '/static/plugins/ueditor/1.4.3.1/'
  280. },
  281. contentCategoryIdOptions: [],
  282. returnIsShow: true,
  283. type: '',
  284. //表单数据
  285. form: {
  286. // 文章标题
  287. contentTitle: '',
  288. // 所属栏目
  289. categoryId: '',
  290. // 文章类型
  291. contentType: [],
  292. // 是否显示
  293. contentDisplay: '0',
  294. // 文章作者
  295. contentAuthor: '',
  296. // 文章来源
  297. contentSource: '',
  298. // 自定义顺序
  299. contentSort: 0,
  300. // 文章缩略图
  301. contentImg: [],
  302. // 描述
  303. contentDescription: '',
  304. // 关键字
  305. contentKeyword: '',
  306. // 文章内容
  307. contentDetails: '',
  308. contentDatetime: ms.util.date.fmt(Date.now(),"yyyy-MM-dd hh:mm:ss"),
  309. },
  310. contentTypeOptions: [],
  311. categoryIdOptions: [],
  312. contentDisplayOptions: [{
  313. "value": "0",
  314. "label": "是"
  315. }, {
  316. "value": "1",
  317. "label": "否"
  318. }],
  319. rules: {
  320. // 文章标题
  321. contentTitle: [{
  322. "required": true,
  323. "message": "请选择文章标题"
  324. }],
  325. // 发布时间
  326. contentDatetime: [{
  327. "required": true,
  328. "message": "发布时间不能为空"
  329. }],
  330. categoryId: [{
  331. "required": true,
  332. "message": "所属栏目不能为空"
  333. }]
  334. }
  335. };
  336. },
  337. watch: {},
  338. computed: {
  339. currCategory: function () {
  340. var that = this;
  341. return this.categoryIdOptions.find(function (value) {
  342. return value.id === that.form.categoryId;
  343. });
  344. }
  345. },
  346. methods: {
  347. save: function () {
  348. var _this = this;
  349. var that = this; //自定义模型需要验证
  350. if (this.model && !this.model.validate()) {
  351. this.activeName = 'custom-name';
  352. return;
  353. }
  354. var url = ms.manager + "/cms/content/save.do";
  355. if (that.form.id > 0) {
  356. url = ms.manager + "/cms/content/update.do";
  357. }
  358. this.$refs.form[0].validate(function (valid) {
  359. if (valid) {
  360. that.saveDisabled = true; //判断
  361. // if (that.categoryIdOptions.filter(function (f) {
  362. // return f['id'] == that.form.categoryId;
  363. // })[0].categoryType == '2' && that.returnIsShow) {
  364. // that.$notify({
  365. // title: '提示',
  366. // message: '所属栏目不能为封面',
  367. // type: 'error'
  368. // });
  369. // that.saveDisabled = false;
  370. // return;
  371. // }
  372. var data = JSON.parse(JSON.stringify(that.form));
  373. if (data.contentType) {
  374. data.contentType = data.contentType.join(',');
  375. }
  376. data.contentImg = JSON.stringify(data.contentImg);
  377. ms.http.post(url, data).then(function (data) {
  378. if (data.result) {
  379. //保存时需要赋值关联ID
  380. if (that.model) {
  381. that.model.form.linkId = data.data.id;
  382. that.model.save();
  383. }
  384. that.$notify({
  385. title: '成功',
  386. message: '保存成功',
  387. type: 'success'
  388. });
  389. if (that.returnIsShow) {
  390. javascript: history.go(-1);
  391. } else {
  392. //如果是顶级封面或封面,则重新拿到当前封面id,避免重复保存
  393. that.list(that.form.categoryId);
  394. }
  395. } else {
  396. that.$notify({
  397. title: '失败',
  398. message: data.msg,
  399. type: 'warning'
  400. });
  401. }
  402. that.saveDisabled = false;
  403. });
  404. } else {
  405. _this.activeName = 'form';
  406. return false;
  407. }
  408. });
  409. },
  410. removeModel: function () {
  411. var that = this;
  412. var model = document.getElementById('model1');
  413. var custom = document.getElementById('c_model');
  414. if (custom) {
  415. model.removeChild(custom);
  416. }
  417. that.model = undefined;
  418. },
  419. categoryChange: function () {
  420. this.changeModel();
  421. },
  422. changeModel: function () {
  423. var that = this;
  424. that.editableTabs = [that.editableTabs[0]];
  425. this.removeModel();
  426. if (this.currCategory) {
  427. if (this.currCategory.mdiyModelId) {
  428. ms.http.get(ms.manager + "/mdiy/model/get.do", {
  429. id: this.currCategory.mdiyModelId
  430. }).then(function (data) {
  431. if (data.data && data.data.id) {
  432. that.rederModel(data.data, JSON.parse(data.data.modelJson));
  433. }
  434. });
  435. }
  436. }
  437. },
  438. rederModel: function (modelEntity, data) {
  439. var that = this;
  440. that.editableTabs.push({
  441. title: modelEntity.modelName,
  442. name: 'custom-name'
  443. });
  444. this.removeModel();
  445. that.$nextTick(function () {
  446. var div = document.createElement('div');
  447. div.id = 'c_model';
  448. var model = document.getElementById('model1');
  449. model.appendChild(div);
  450. var s = document.createElement('script');
  451. s.innerHTML = data.script;
  452. var con = document.createElement('div');
  453. con.id = 'custom-model';
  454. con.innerHTML = data.html;
  455. div.appendChild(s);
  456. div.appendChild(con); //初始化自定义模型并传入关联参数
  457. that.model = new custom_model({
  458. data: {
  459. title: modelEntity.modelName,
  460. modelId: modelEntity.id,
  461. form: {
  462. linkId: that.form.id
  463. }
  464. }
  465. });
  466. });
  467. },
  468. getValue: function (data) {
  469. this.form.categoryId = data.id;
  470. },
  471. //获取当前文章
  472. get: function (id) {
  473. var that = this;
  474. ms.http.get(ms.manager + "/cms/content/get.do", {
  475. "id": id
  476. }).then(function (res) {
  477. if (res.result && res.data) {
  478. if (res.data.contentType && res.data.contentType != '') {
  479. res.data.contentType = res.data.contentType.split(',');
  480. } else {
  481. res.data.contentType = [];
  482. }
  483. if (res.data.contentImg) {
  484. res.data.contentImg = JSON.parse(res.data.contentImg);
  485. res.data.contentImg.forEach(function (value) {
  486. value.url = ms.base + value.path;
  487. });
  488. } else {
  489. res.data.contentImg = [];
  490. }
  491. that.form = res.data;
  492. var category = that.categoryIdOptions.filter(function (f) {
  493. return f['id'] == that.form.categoryId;
  494. });
  495. if (category.length == 1) {
  496. if (category[0].categoryType == '2') {
  497. that.returnIsShow = false;
  498. }
  499. }
  500. that.changeModel();
  501. }
  502. }).catch(function (err) {
  503. console.log(err);
  504. });
  505. },
  506. //获取contentCategoryId数据源
  507. contentCategoryIdOptionsGet: function () {
  508. var that = this;
  509. ms.http.get(ms.manager + "/cms/category/list.do", {
  510. pageSize: 9999
  511. }).then(function (res) {
  512. if (res.result) {
  513. res.data.rows.forEach(function (item) {
  514. if (item.categoryType == '2' || item.categoryType == '3') {
  515. item.isDisabled = true;
  516. }
  517. });
  518. that.contentCategoryIdOptions = ms.util.treeData(res.data.rows, 'id', 'categoryId', 'children');
  519. that.categoryIdOptions = res.data.rows;
  520. that.changeModel();
  521. }
  522. }).catch(function (err) {
  523. console.log(err);
  524. });
  525. },
  526. //获取contentType数据源
  527. contentTypeOptionsGet: function () {
  528. var that = this;
  529. ms.http.get(ms.base + '/mdiy/dict/list.do', {
  530. dictType: '文章属性',
  531. pageSize: 99999
  532. }).then(function (data) {
  533. if(data.result){
  534. data = data.data;
  535. that.contentTypeOptions = data.rows;
  536. }
  537. }).catch(function (err) {
  538. console.log(err);
  539. });
  540. },
  541. //contentImg文件上传完成回调
  542. contentImgSuccess: function (response, file, fileList) {
  543. if(response.result){
  544. this.form.contentImg.push({
  545. url: file.url,
  546. name: file.name,
  547. path: response.data,
  548. uid: file.uid
  549. });
  550. }else {
  551. this.$notify({
  552. title: response.msg,
  553. type: 'warning'
  554. });
  555. }
  556. },
  557. contentImghandleRemove: function (file, files) {
  558. var index = -1;
  559. index = this.form.contentImg.findIndex(function (text) {
  560. return text == file;
  561. });
  562. if (index != -1) {
  563. this.form.contentImg.splice(index, 1);
  564. }
  565. },
  566. //上传超过限制
  567. contentImghandleExceed: function (files, fileList) {
  568. this.$notify({
  569. title: '当前最多上传1个文件',
  570. type: 'warning'
  571. });
  572. },
  573. //查询列表
  574. list: function (categoryId) {
  575. var that = this;
  576. ms.http.post(ms.manager + "/cms/content/list.do", {
  577. categoryId: categoryId
  578. }).then(function (res) {
  579. if (res.result && res.data.total > 0) {
  580. if (res.data.rows[0].contentType) {
  581. res.data.rows[0].contentType = res.data.rows[0].contentType.split(',');
  582. }
  583. if (res.data.rows[0].contentImg) {
  584. res.data.rows[0].contentImg = JSON.parse(res.data.rows[0].contentImg);
  585. res.data.rows[0].contentImg.forEach(function (value) {
  586. value.url = ms.base + value.path;
  587. });
  588. } else {
  589. res.data.rows[0].contentImg = [];
  590. }
  591. that.form = res.data.rows[0];
  592. }
  593. }).catch(function (err) {
  594. console.log(err);
  595. });
  596. }
  597. },
  598. created: function () {
  599. this.contentCategoryIdOptionsGet();
  600. this.contentTypeOptionsGet();
  601. this.form.id = ms.util.getParameter("id");
  602. if (ms.util.getParameter("categoryId")) {
  603. this.form.categoryId = ms.util.getParameter("categoryId");
  604. }
  605. this.type = ms.util.getParameter("type");
  606. if (this.form.id) {
  607. this.get(this.form.id);
  608. }
  609. if (this.type) {
  610. this.list(this.form.categoryId);
  611. this.returnIsShow = false;
  612. }
  613. }
  614. });
  615. </script>
  616. <style>
  617. .el-select {
  618. width: 100%;
  619. }
  620. body {
  621. overflow: hidden;
  622. }
  623. #form {
  624. overflow: hidden;
  625. }
  626. .el-scrollbar__bar.is-vertical{
  627. width: 6px!important;
  628. }
  629. </style>