form.ftl 31 KB

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