form.ftl 31 KB

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