index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. <template>
  2. <div class="article-manager">
  3. <div class="i-layout-page-header header-title">
  4. <div class="fl_header">
  5. <span>
  6. <Button icon="ios-arrow-back" size="small" type="text" @click="$router.go(-1)">返回</Button>
  7. </span>
  8. <Divider type="vertical"/>
  9. <span class="ivu-page-header-title">{{ $route.params.id ? '编辑文章' : '添加文章' }}</span>
  10. </div>
  11. </div>
  12. <Card :bordered="false" dis-hover class="ivu-mt">
  13. <Form
  14. class="form"
  15. ref="formValidate"
  16. :model="formValidate"
  17. :rules="ruleValidate"
  18. :label-width="labelWidth"
  19. :label-position="labelPosition"
  20. @submit.native.prevent
  21. >
  22. <div class="goodsTitle acea-row">
  23. <div class="title">文章信息</div>
  24. </div>
  25. <Row :gutter="24" type="flex">
  26. <Col v-bind="grid" class="mr50">
  27. <FormItem label="标题:" prop="title" label-for="title">
  28. <Input v-model="formValidate.title" placeholder="请输入" element-id="title" style="width: 90%" />
  29. </FormItem>
  30. </Col>
  31. <Col v-bind="grid" class="mr50">
  32. <FormItem label="作者:" prop="author" label-for="author">
  33. <Input v-model="formValidate.author" placeholder="请输入" element-id="author" style="width: 90%" />
  34. </FormItem>
  35. </Col>
  36. <Col v-bind="grid" class="mr50">
  37. <FormItem label="文章分类:" label-for="cid" prop="cid">
  38. <div class="perW90">
  39. <Select v-model="formValidate.cid">
  40. <Option v-for="item in treeData" :value="item.id" :key="item.id">{{ item.html + item.title }}</Option>
  41. </Select>
  42. </div>
  43. </FormItem>
  44. </Col>
  45. <Col v-bind="grid" class="mr50">
  46. <FormItem label="文章简介:" prop="synopsis" label-for="synopsis">
  47. <Input v-model="formValidate.synopsis" type="textarea" placeholder="请输入" style="width: 90%" />
  48. </FormItem>
  49. </Col>
  50. <Col v-bind="grid" class="mr50">
  51. <FormItem label="图文封面:" prop="image_input">
  52. <div class="picBox" @click="modalPicTap('单选')">
  53. <div class="pictrue" v-if="formValidate.image_input">
  54. <img :src="formValidate.image_input" />
  55. </div>
  56. <div class="upLoad acea-row row-center-wrapper" v-else>
  57. <Icon type="ios-camera-outline" size="24" />
  58. </div>
  59. </div>
  60. <div class="tip">建议尺寸:500 x 312 px</div>
  61. </FormItem>
  62. </Col>
  63. </Row>
  64. <div class="goodsTitle acea-row">
  65. <div class="title">文章内容</div>
  66. </div>
  67. <FormItem label="文章内容:" prop="content">
  68. <WangEditor style="width: 90%" :content="formValidate.content" @editorContent="getEditorContent"></WangEditor>
  69. </FormItem>
  70. <div class="goodsTitle acea-row">
  71. <div class="title">其他设置</div>
  72. </div>
  73. <Row :gutter="24" type="flex">
  74. <!-- <Col span="24">-->
  75. <!-- <FormItem label="原文链接:">-->
  76. <!-- <Input v-model="formValidate.url" placeholder="请输入" element-id="url" style="width: 60%"/>-->
  77. <!-- </FormItem>-->
  78. <!-- </Col>-->
  79. <Col span="24">
  80. <FormItem label="banner显示:" label-for="is_banner">
  81. <RadioGroup v-model="formValidate.is_banner" element-id="is_banner">
  82. <Radio :label="1" class="radio">显示</Radio>
  83. <Radio :label="0">不显示</Radio>
  84. </RadioGroup>
  85. </FormItem>
  86. </Col>
  87. <Col span="24">
  88. <FormItem label="热门文章:" label-for="is_hot">
  89. <RadioGroup v-model="formValidate.is_hot" element-id="is_hot">
  90. <Radio :label="1" class="radio">显示</Radio>
  91. <Radio :label="0">不显示</Radio>
  92. </RadioGroup>
  93. </FormItem>
  94. </Col>
  95. </Row>
  96. <Button type="primary" class="submission" @click="onsubmit('formValidate')">提交</Button>
  97. </Form>
  98. <Modal
  99. v-model="modalPic"
  100. width="950px"
  101. scrollable
  102. footer-hide
  103. closable
  104. title="上传商品图"
  105. :mask-closable="false"
  106. :z-index="888"
  107. >
  108. <uploadPictures
  109. :isChoice="isChoice"
  110. @getPic="getPic"
  111. :gridBtn="gridBtn"
  112. :gridPic="gridPic"
  113. v-if="modalPic"
  114. ></uploadPictures>
  115. </Modal>
  116. </Card>
  117. </div>
  118. </template>
  119. <script>
  120. import { mapState } from 'vuex';
  121. import uploadPictures from '@/components/uploadPictures';
  122. import WangEditor from '@/components/wangEditor/index.vue';
  123. import { cmsAddApi, createApi, categoryTreeListApi } from '@/api/cms';
  124. export default {
  125. name: 'addArticle',
  126. components: { uploadPictures, WangEditor },
  127. data() {
  128. const validateUpload = (rule, value, callback) => {
  129. if (this.formValidate.image_input) {
  130. callback();
  131. } else {
  132. callback(new Error('请上传图文封面'));
  133. }
  134. };
  135. const validateUpload2 = (rule, value, callback) => {
  136. if (!this.formValidate.cid) {
  137. callback(new Error('请选择文章分类'));
  138. } else {
  139. callback();
  140. }
  141. };
  142. return {
  143. dialog: {},
  144. isChoice: '单选',
  145. grid: {
  146. xl: 8,
  147. lg: 8,
  148. md: 12,
  149. sm: 24,
  150. xs: 24,
  151. },
  152. gridPic: {
  153. xl: 6,
  154. lg: 8,
  155. md: 12,
  156. sm: 12,
  157. xs: 12,
  158. },
  159. gridBtn: {
  160. xl: 4,
  161. lg: 8,
  162. md: 8,
  163. sm: 8,
  164. xs: 8,
  165. },
  166. loading: false,
  167. formValidate: {
  168. id: 0,
  169. title: '',
  170. author: '',
  171. image_input: '',
  172. content: '',
  173. synopsis: '',
  174. url: '',
  175. is_hot: 0,
  176. is_banner: 0,
  177. cid: '',
  178. visit: 0,
  179. },
  180. content: '',
  181. ruleValidate: {
  182. title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
  183. cid: [
  184. {
  185. required: true,
  186. validator: validateUpload2,
  187. trigger: 'change',
  188. type: 'number',
  189. },
  190. ],
  191. image_input: [{ required: true, validator: validateUpload, trigger: 'change' }],
  192. content: [{ required: true, message: '请输入文章内容', trigger: 'change' }],
  193. },
  194. value: '',
  195. modalPic: false,
  196. template: false,
  197. treeData: [],
  198. formValidate2: {
  199. type: 1,
  200. },
  201. myConfig: {
  202. autoHeightEnabled: false, // 编辑器不自动被内容撑高
  203. initialFrameHeight: 500, // 初始容器高度
  204. initialFrameWidth: '100%', // 初始容器宽度
  205. UEDITOR_HOME_URL: '/UEditor/',
  206. serverUrl: '',
  207. },
  208. };
  209. },
  210. computed: {
  211. ...mapState('media', ['isMobile']),
  212. labelWidth() {
  213. return this.isMobile ? undefined : 120;
  214. },
  215. labelPosition() {
  216. return this.isMobile ? 'top' : 'right';
  217. },
  218. },
  219. watch: {
  220. $route(to, from) {
  221. if (this.$route.params.id) {
  222. this.getDetails();
  223. } else {
  224. this.formValidate = {
  225. id: 0,
  226. title: '',
  227. author: '',
  228. image_input: '',
  229. content: '',
  230. synopsis: '',
  231. url: '',
  232. is_hot: 0,
  233. is_banner: 0,
  234. };
  235. }
  236. },
  237. },
  238. methods: {
  239. getEditorContent(data) {
  240. this.content = data;
  241. },
  242. // 选择图片
  243. modalPicTap() {
  244. this.modalPic = true;
  245. },
  246. // 选中图片
  247. getPic(pc) {
  248. this.formValidate.image_input = pc.att_dir;
  249. this.modalPic = false;
  250. },
  251. // 分类
  252. getClass() {
  253. categoryTreeListApi()
  254. .then(async (res) => {
  255. this.treeData = res.data;
  256. })
  257. .catch((res) => {
  258. this.$Message.error(res.msg);
  259. });
  260. },
  261. // 提交数据
  262. onsubmit(name) {
  263. this.formValidate.content = this.content;
  264. this.$refs[name].validate((valid) => {
  265. if (valid) {
  266. cmsAddApi(this.formValidate)
  267. .then(async (res) => {
  268. this.$Message.success(res.msg);
  269. setTimeout(() => {
  270. this.$router.push({ path: this.$routeProStr + '/cms/article/index' });
  271. }, 500);
  272. })
  273. .catch((res) => {
  274. this.$Message.error(res.msg);
  275. });
  276. } else {
  277. return false;
  278. }
  279. });
  280. },
  281. // 文章详情
  282. getDetails() {
  283. createApi(this.$route.params.id ? this.$route.params.id : 0)
  284. .then(async (res) => {
  285. let data = res.data;
  286. let news = data.info;
  287. this.formValidate = {
  288. id: news.id,
  289. title: news.title,
  290. author: news.author,
  291. image_input: news.image_input,
  292. content: news.content,
  293. synopsis: news.synopsis,
  294. url: news.url,
  295. is_hot: news.is_hot,
  296. is_banner: news.is_banner,
  297. cid: news.cid,
  298. visit: news.visit,
  299. };
  300. })
  301. .catch((res) => {
  302. this.loading = false;
  303. this.$Message.error(res.msg);
  304. });
  305. },
  306. },
  307. mounted() {
  308. if (this.$route.params.id) {
  309. this.getDetails();
  310. }
  311. },
  312. created() {
  313. this.getClass();
  314. },
  315. };
  316. </script>
  317. <style scoped>
  318. /deep/.ivu-form-item-content {
  319. line-height: unset !important;
  320. }
  321. .picBox {
  322. display: inline-block;
  323. cursor: pointer;
  324. }
  325. .form .goodsTitle {
  326. border-bottom: 1px solid rgba(0, 0, 0, 0.09);
  327. margin-bottom: 25px;
  328. }
  329. .form .goodsTitle ~ .goodsTitle {
  330. margin-top: 20px;
  331. }
  332. .form .goodsTitle .title {
  333. border-bottom: 2px solid #1890ff;
  334. padding: 0 8px 12px 5px;
  335. color: #000;
  336. font-size: 14px;
  337. }
  338. .form .goodsTitle .icons {
  339. font-size: 15px;
  340. margin-right: 8px;
  341. color: #999;
  342. }
  343. .form .add {
  344. font-size: 12px;
  345. color: #1890ff;
  346. padding: 0 12px;
  347. cursor: pointer;
  348. }
  349. .form .radio {
  350. margin-right: 20px;
  351. }
  352. .form .submission {
  353. width: 10%;
  354. margin-left: 27px;
  355. }
  356. .form .upLoad {
  357. width: 58px;
  358. height: 58px;
  359. line-height: 58px;
  360. border: 1px dotted rgba(0, 0, 0, 0.1);
  361. border-radius: 4px;
  362. background: rgba(0, 0, 0, 0.02);
  363. }
  364. .form .iconfont {
  365. color: #898989;
  366. }
  367. .form .pictrue {
  368. width: 60px;
  369. height: 60px;
  370. border: 1px dotted rgba(0, 0, 0, 0.1);
  371. margin-right: 10px;
  372. }
  373. .form .pictrue img {
  374. width: 100%;
  375. height: 100%;
  376. }
  377. .Modals .address {
  378. width: 90%;
  379. }
  380. .Modals .address .iconfont {
  381. font-size: 20px;
  382. }
  383. .tip {
  384. margin-top: 10px;
  385. color: #bbb;
  386. }
  387. </style>