creatNews.vue 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. <template>
  2. <div class="mainBox">
  3. <div class="layerBox">
  4. <tableTitle :name="tableDivTitle" />
  5. <el-form :model="form" ref="form" :rules="formRules" label-position="left" label-width="120px">
  6. <div class="formDiv">
  7. <el-form-item label="资讯题目:" prop="title" class="custom-align-right">
  8. <template #label>
  9. <span class="askBox">
  10. 资讯题目:
  11. <!-- <el-tooltip class="item" effect="dark" content="资讯标题,如:三农市场网_网站列表_全国信息一体化网络平台_项目大全。" placement="top">
  12. <i class="el-icon-question"></i>
  13. </el-tooltip> -->
  14. </span>
  15. </template>
  16. <el-input v-model="form.title" autocomplete="off" placeholder="请输入资讯标题"></el-input>
  17. <el-checkbox v-model="form.islink">是否使用外链</el-checkbox>
  18. </el-form-item>
  19. <div v-if="form.islink == true">
  20. <el-form-item label="站点名称:" prop="cat_arr_id" class="custom-align-right">
  21. <el-cascader :key="parentKey" v-model="form.web_site_id" placeholder="请选择站点名称"
  22. :options="creatNews_nav_pool_arr" @change="creatNews_nav_pool_change_fun(form.web_site_id)" filterable
  23. clearable></el-cascader>
  24. </el-form-item>
  25. <el-form-item label="导航池名称:" prop="cat_arr_id" class="custom-align-right">
  26. <el-cascader :key="parentKey_2" v-model="form.cat_arr_id" placeholder="请选择要绑定的父级导航" :props="parentData_2"
  27. filterable clearable></el-cascader>
  28. </el-form-item>
  29. <!-- <el-form-item label="导航池名称:" prop="cat_arr_id" class="custom-align-right">
  30. <el-cascader :key="parentKey" v-model="form.cat_arr_id" placeholder="请选择要绑定的导航池名称" :props="parentData" filterable clearable></el-cascader>
  31. </el-form-item> -->
  32. <el-form-item label="外链地址:" prop="linkurl" class="custom-align-right">
  33. <el-input v-model="form.linkurl" autocomplete="off" placeholder="请输入外链地址"></el-input>
  34. </el-form-item>
  35. <el-form-item label="作者:" prop="author" class="custom-align-right">
  36. <el-input v-model="form.author" autocomplete="off" placeholder="请输入作者"></el-input>
  37. </el-form-item>
  38. </div>
  39. <div v-if="form.islink == false">
  40. <div v-if="creatNews_user_type != 10000">
  41. <el-form-item label="导航池名称:" prop="cat_arr_id" class="custom-align-right">
  42. <el-cascader :key="parentKey" v-model="form.cat_arr_id" placeholder="请选择要绑定的导航池名称" :props="parentData"
  43. filterable clearable></el-cascader>
  44. </el-form-item>
  45. </div>
  46. <div>
  47. <div v-if="creatNews_user_type == 10000">
  48. <el-form-item label="站点名称:" prop="cat_arr_id" class="custom-align-right">
  49. <el-cascader :key="parentKey" v-model="form.web_site_id" placeholder="请选择站点名称"
  50. :options="creatNews_nav_pool_arr" @change="creatNews_nav_pool_change_fun(form.web_site_id)"
  51. filterable clearable></el-cascader>
  52. </el-form-item>
  53. <el-form-item label="导航池名称:" prop="cat_arr_id" class="custom-align-right">
  54. <el-cascader :key="parentKey_2" v-model="form.cat_arr_id" placeholder="请选择要绑定的父级导航"
  55. :props="parentData_2" filterable clearable></el-cascader>
  56. </el-form-item>
  57. </div>
  58. <el-form-item label="推荐等级:" class="custom-align-right">
  59. <el-select v-model="form.level" clearable placeholder="请选择推荐等级..">
  60. <el-option label="头条" :value="1"></el-option>
  61. <el-option label="轮播图" :value="2"></el-option>
  62. <el-option label="推荐图" :value="3"></el-option>
  63. <el-option label="热点资讯" :value="4"></el-option>
  64. <el-option label="资讯推荐" :value="5"></el-option>
  65. </el-select>
  66. </el-form-item>
  67. <el-form-item label="缩略图:" class="custom-align-right" prop="imgUrl"
  68. v-if="form.level == 2 || form.level == 3">
  69. <div class="uploaderBox">
  70. <el-upload class="avatar-uploader" action="#" :show-file-list="false"
  71. :before-upload="beforeAvatarUpload">
  72. <!-- <img v-if="imgUrl" :src="imgUrl" class="avatar">
  73. <i v-else class="el-icon-plus avatar-uploader-icon"></i> -->
  74. <!-- 预览图片 -->
  75. <img v-if="imgUrl" :src="imgUrl" class="avatar">
  76. <!-- 上传图标 -->
  77. <!-- <i v-else class="el-icon-plus avatar-uploader-icon"></i> -->
  78. <div v-else class="chooseImgDiv">
  79. <div>
  80. <img src="@/assets/public/upload/noImage.png">
  81. <div>选择图片</div>
  82. </div>
  83. </div>
  84. </el-upload>
  85. <input type="hidden" v-model="form.imgurl">
  86. </div>
  87. </el-form-item>
  88. <el-form-item label="资讯关键词:" prop="keyword" class="custom-align-right">
  89. <template #label>
  90. <span class="askBox">
  91. 资讯关键词:
  92. <el-tooltip class="item" effect="dark" content="资讯关键词,如:三农市场网、全国三农、信息一体化。" placement="top">
  93. <i class="el-icon-question"></i>
  94. </el-tooltip>
  95. </span>
  96. </template>
  97. <el-input v-model="form.keyword" autocomplete="off" placeholder="请输入资讯关键词"></el-input>
  98. </el-form-item>
  99. <el-form-item label="资讯描述:" prop="introduce" class="custom-align-right">
  100. <template #label>
  101. <span class="askBox">
  102. 资讯描述:
  103. <el-tooltip class="item" effect="dark" content="资讯描述,如:中国三农市场网创建以来,社会效益和会员经济效益贡献。" placement="top">
  104. <i class="el-icon-question"></i>
  105. </el-tooltip>
  106. </span>
  107. </template>
  108. <el-input type="textarea" v-model="form.introduce" class="custom-textarea"
  109. placeholder="请输入资讯描述"></el-input>
  110. </el-form-item>
  111. <div class="QuillTitle">
  112. <span>* </span>资讯内容:
  113. <div @click="toggleSourceMode" class="QuillModelBtn">
  114. {{ showHtml ? '切换到编辑模式' : '切换到源码模式' }}
  115. </div>
  116. </div>
  117. <el-form-item label="" prop="content">
  118. <div class="editor-container">
  119. <div v-if="showHtml">
  120. <textarea v-model="editorHtml" style="width: 100%; height: 400px;"></textarea>
  121. </div>
  122. <div v-else>
  123. <quill-editor ref="quillEditor" v-model="form.content" :options="editorOptions"
  124. class="my-quill-editor" />
  125. </div>
  126. <!-- 多图上传隐藏的input -->
  127. <input type="file" ref="multiFileInput" @change="handleMultipleFiles" multiple hidden
  128. accept="image/jpeg, image/png" />
  129. </div>
  130. </el-form-item>
  131. <el-form-item label="作者:" prop="author" class="custom-align-right">
  132. <el-input v-model="form.author" autocomplete="off" placeholder="请输入作者"></el-input>
  133. </el-form-item>
  134. <el-form-item label="浏览量:" class="custom-align-right">
  135. <el-input v-model="form.hits" autocomplete="off" placeholder="请输入浏览量"></el-input>
  136. </el-form-item>
  137. <el-form-item label="是否为原创:" prop="is_original" class="custom-align-right">
  138. <el-radio-group v-model="form.is_original" @change="changeIsOriginal">
  139. <el-radio :label="1">是</el-radio>
  140. <el-radio :label="0">否</el-radio>
  141. </el-radio-group>
  142. </el-form-item>
  143. <div v-if="form.is_original == 0">
  144. <el-form-item label="来源名称:" prop="copyfrom" class="custom-align-right">
  145. <el-input v-model="form.copyfrom" autocomplete="off" placeholder="请输入来源名称"></el-input>
  146. </el-form-item>
  147. <el-form-item label="来源链接:" prop="fromurl" class="custom-align-right">
  148. <el-input v-model="form.fromurl" autocomplete="off" placeholder="请输入来源链接"></el-input>
  149. </el-form-item>
  150. <div class="disclaimerBox">
  151. <div class="disclaimerTitle">
  152. <img src="@/assets/public/check.png" />同意《免责声明》:
  153. <!-- <el-checkbox v-model="disclaimer" disabled="disabled"></el-checkbox> -->
  154. </div>
  155. <div class="disclaimerText">
  156. 本文来源于网络转载,仅供学习交流使用,不构成商业目的。版权归原作者所有,如涉及作品内容、版权和其他问题,请在30日内与本站联系,我们将在第一时间处理。</div>
  157. </div>
  158. </div>
  159. <div v-if="form.is_original == 1">
  160. <el-form-item label="来源名称:" prop="copyfrom" class="custom-align-right">
  161. <el-input v-model="form.copyfrom" autocomplete="off" placeholder="请输入来源名称"
  162. disabled="disabled"></el-input>
  163. </el-form-item>
  164. </div>
  165. <el-form-item label="资讯状态:" class="custom-align-right" style="width: 100%;" v-if="creatNews_user_type == 10000">
  166. <el-select v-model="form.status" placeholder="请选择..">
  167. <el-option label="已发布" :value="1"></el-option>
  168. <el-option label="待发布" :value="0"></el-option>
  169. </el-select>
  170. </el-form-item>
  171. <el-form-item label="是否开启投票:" prop="is_survey" class="custom-align-right">
  172. <el-radio-group v-model="form.is_survey">
  173. <el-radio :label="1">是</el-radio>
  174. <el-radio :label="0">否</el-radio>
  175. </el-radio-group>
  176. </el-form-item>
  177. <div v-if="form.is_survey == 1">
  178. <el-form-item label="问卷标题:" prop="survey_name" class="custom-align-right">
  179. <el-input v-model="form.survey_name" autocomplete="off" placeholder="请输入问卷标题"></el-input>
  180. </el-form-item>
  181. <el-form-item label="选项:" prop="survey_type" class="custom-align-right">
  182. <el-radio-group v-model="form.survey_type">
  183. <el-radio :label="0">单选</el-radio>
  184. <el-radio :label="1">多选</el-radio>
  185. </el-radio-group>
  186. </el-form-item>
  187. <el-form-item label="" class="custom-align-right">
  188. <div v-for="(input, index) in inputList" :key="index">
  189. <div class="formLabelFloatBox">
  190. <el-input autocomplete="off" v-model="input.value" maxlength="150" :label-width="formLabelWidth"
  191. placeholder="">
  192. <template slot="prepend">{{ index + 1 }}</template>
  193. </el-input>
  194. <el-button type="info" icon="el-icon-plus" circle size="mini" @click="addInput(index)"
  195. class="formLabeladdIcon"></el-button>
  196. <el-button type="info" icon="el-icon-delete" circle size="mini" @click="deleteInput(index)"
  197. class="formLabelDelIcon"></el-button>
  198. </div>
  199. </div>
  200. </el-form-item>
  201. <el-form-item label="" class="custom-align-right">
  202. <el-checkbox v-model="checked">允许用户自己填写</el-checkbox>
  203. </el-form-item>
  204. </div>
  205. </div>
  206. </div>
  207. </div>
  208. </el-form>
  209. </div>
  210. <div class="bottomBtnBox">
  211. <el-button type="info" @click="returnPage">返回</el-button>
  212. <el-button type="primary" @click="editToServe" v-if="editStatus == true">确定</el-button>
  213. <el-button type="primary" @click="addToServe" v-else>发布资讯</el-button>
  214. </div>
  215. </div>
  216. </template>
  217. <script>
  218. import { getWebSiteId, getUseType } from '@/utils/auth'
  219. //表格标题
  220. import tableTitle from './components/tableTitle';
  221. //引入公用样式
  222. import '@/styles/global.less';
  223. import { quillEditor } from 'vue-quill-editor';
  224. import 'quill/dist/quill.snow.css';
  225. import ImageResize from 'quill-image-resize-module';
  226. import Quill from 'quill'; // 引入 Quill
  227. import Delta from 'quill-delta'; // 引入 Delta,用于手动修改文档
  228. // 注册 Image Resize 模块
  229. Quill.register('modules/imageResize', ImageResize);
  230. //解决富文本样式居中不显示
  231. import 'quill/dist/quill.core.css';
  232. export default {
  233. components: {
  234. quillEditor,
  235. tableTitle
  236. },
  237. data() {
  238. //0.全局操作 start ------------------------------------------------------------>
  239. //表单验证
  240. const validateEmpty = (rule, value, callback) => {
  241. if (value == '') {
  242. callback(new Error('该项不能为空!'))
  243. } else {
  244. callback()
  245. }
  246. }
  247. const validateArray = (rule, value, callback) => {
  248. if (value.length == 0) {
  249. callback(new Error('该项不能为空!'))
  250. } else {
  251. callback()
  252. }
  253. }
  254. const validateRadio = (rule, value, callback) => {
  255. if (value != '1' || value != '0') {
  256. callback()
  257. } else {
  258. callback()
  259. }
  260. }
  261. let self = this;
  262. //0.全局操作 end ------------------------------------------------------------>
  263. return {
  264. websiteid: 0,
  265. creatNews_pid_num: "0",//请求子导航用的pid
  266. creatNews_nav_pool_arr: [],//
  267. creatNews_add_nav_pool_arr: [],//
  268. creatNews_son_website_id_num: "",
  269. checked: false,
  270. formLabelWidth: '80px',//表单的长度
  271. //1.表单项 start ------------------------------------------------------------>
  272. editStatus: false,
  273. tableDivTitle: "添加资讯",
  274. disclaimer: true,//免责声明
  275. //提交表单
  276. creatNews_user_type: 0,//判断用户类型'
  277. form: {
  278. user_type: "??",//判断用户类型'
  279. cat_arr_id: 0,//导航池名称
  280. nav_add_pool_id: [],//导航池子级
  281. //1.1使用了外链
  282. title: '',//资讯标题
  283. islink: 0,//是否使用外链 0非 1是
  284. linkurl: "",//外链地址
  285. //1.2没有使用外链
  286. cat_arr_id: '',//导航池名称
  287. level: "",//推荐等级
  288. imgurl: "",//缩略图
  289. keyword: "",//关键词
  290. introduce: "",//描述
  291. content: "",//内容
  292. author: "",//作者
  293. hits: "",//浏览量
  294. is_original: 0,//是否为原创 0非 1是
  295. copyfrom: "",//来源名称
  296. fromurl: "",//来源地址
  297. status: 0,//状态 0待发布 1已发布 404已删除 如果是普通用户,这里始终为0
  298. web_site_id: 0,
  299. is_survey: 1,//调查问卷:0:否;1:是;
  300. survey_name: "",//问卷名称
  301. suvey_array: "",//选项名称集合
  302. survey_type: 0 //0:单选 1:复选
  303. },
  304. //1.2 表单验证规则
  305. formRules: {
  306. //导航池名称不能为空
  307. cat_arr_id: [{ required: true, trigger: 'blur', validator: validateArray }],
  308. //资讯名称不能为空
  309. title: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  310. //如果使用了外链,外链地址不能为空
  311. linkurl: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  312. //导航池名称不能为空
  313. cat_arr_id: [{ required: true, trigger: 'blur', validator: validateArray }],
  314. //推荐等级不能为空
  315. //level:[{required:true,trigger:'blur',validator:validateEmpty}],
  316. //关键词不能为空
  317. keyword: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  318. //描述不能为空
  319. introduce: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  320. //内容不能为空
  321. content: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  322. //作者不能为空
  323. author: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  324. //是否原创不能为空
  325. is_original: [{ required: true, trigger: 'blur', validator: validateRadio }],
  326. //来源名称和地址不能为空
  327. copyfrom: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  328. fromurl: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  329. //缩略图不能为空
  330. imgUrl: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  331. level: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  332. //是否开启投票
  333. is_survey: [{ required: true, trigger: 'blur', validator: validateRadio }],
  334. //问卷标题
  335. survey_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  336. //选项
  337. survey_type: [{ required: true, trigger: 'blur', validator: validateRadio }],
  338. },
  339. //1.3富文本编辑器配置
  340. showHtml: false, //用于保存源码内容
  341. editorHtml: '',
  342. editorOptions: {
  343. placeholder: '请输入内容...',
  344. theme: 'snow', // 主题样式
  345. modules: {
  346. toolbar: {
  347. container: [
  348. [{ 'font': [] }], // 字体
  349. [{ 'header': [1, 2, 3, 4, 5, 6, false] }], // 标题
  350. [{ 'size': ['small', false, 'large', 'huge'] }], // 字体大小
  351. ['bold', 'italic', 'underline', 'strike'], // 加粗、斜体、下划线、删除线
  352. [{ 'color': [] }, { 'background': [] }], // 文字颜色、背景颜色
  353. [{ 'script': 'sub' }, { 'script': 'super' }], // 上标、下标
  354. [{ 'list': 'ordered' }, { 'list': 'bullet' }], // 列表
  355. [{ 'indent': '-1' }, { 'indent': '+1' }], // 缩进
  356. [{ 'align': [] }], // 对齐方式
  357. ['blockquote', 'code-block'], // 引用、代码块
  358. ['link', 'image', 'video'], // 链接、图片、视频
  359. ['clean'],
  360. [{ 'html': true }] // 添加自定义按钮的占位符
  361. ],
  362. handlers: {
  363. image: () => {
  364. this.handleImageClick();
  365. },
  366. showHtml: function () {
  367. this.$emit('toggleSourceMode');
  368. }
  369. }
  370. },
  371. imageResize: {
  372. displayStyles: {
  373. backgroundColor: 'black',
  374. border: 'none',
  375. color: 'white'
  376. },
  377. modules: ['Resize', 'DisplaySize', 'Toolbar'] // 启用不同的调整方式
  378. }
  379. }
  380. },
  381. //1.4图片上传
  382. imgUrl: "",//在页面上显示缩略图
  383. //获取父级导航池
  384. parentKey: 0,//获取父级导航
  385. parentData: {
  386. checkStrictly: true,
  387. lazy: true,
  388. async lazyLoad(node, resolve) {
  389. const { level, data } = node;
  390. if (data && data.children && data.children.length !== 0) {
  391. return resolve(node)
  392. }
  393. console.log(level)
  394. let parentId;
  395. parentId = level == 0 ? 0 : data.value;
  396. let parames = {
  397. 'website_id': getWebSiteId(),
  398. 'pid': parentId
  399. }
  400. self.$store.dispatch('pool/get_creatNews_nav_son_actions', parames).then(res => {
  401. if (res.data) {
  402. const nodes = res.data.map(item => ({
  403. value: item.category_id,
  404. label: item.name,
  405. leaf: level >= 3,
  406. children: []
  407. }))
  408. resolve(nodes)
  409. }
  410. })
  411. }
  412. },
  413. parentKey_2: 0,//获取父级导航
  414. parentData_2: {
  415. checkStrictly: true,
  416. lazy: true,
  417. async lazyLoad(node, resolve) {
  418. const { level, data } = node;
  419. if (data && data.children && data.children.length !== 0) {
  420. return resolve(node)
  421. }
  422. let parentId;
  423. if (self.ifwebsitId == true) {
  424. console.log("网站选择已经改变!")
  425. parentId = 0;
  426. self.ifwebsitId = false;
  427. self.cat_arr_id = [];
  428. } else {
  429. parentId = level == 0 ? 0 : data.value;
  430. self.ifwebsitId = false;
  431. }
  432. console.log(123123)
  433. console.log(self.form.web_site_id)
  434. // if(data!=undefined){
  435. // parentId = data.value;
  436. // }else{
  437. // parentId = self.creatNews_pid_num.toString();
  438. // }
  439. let parames = {
  440. 'website_id': self.form.web_site_id,
  441. 'pid': parentId
  442. }
  443. self.$store.dispatch('pool/get_creatNews_nav_son_actions', parames).then(res => {
  444. if (res.data) {
  445. const nodes = res.data.map(item => ({
  446. value: item.category_id,
  447. label: item.alias,
  448. leaf: level >= 3,
  449. children: []
  450. }))
  451. resolve(nodes)
  452. }
  453. })
  454. }
  455. },
  456. inputList: [
  457. { value: '' }
  458. ]
  459. //表单项 end ------------------------------------------------------------>
  460. };
  461. },
  462. methods: {
  463. //---------------------------
  464. addInput(index) {
  465. // 在当前索引后插入一个新的输入框对象
  466. if (this.inputList.length > 10) {
  467. this.$message.warning('最多只能添加10个文本框');
  468. return false;
  469. }
  470. this.inputList.splice(index + 1, 0, { value: '' });
  471. },
  472. deleteInput(index) {
  473. if (this.inputList.length > 1) {
  474. // 如果输入框数量大于 1,则删除当前索引对应的输入框对象
  475. this.inputList.splice(index, 1);
  476. } else {
  477. this.$message.warning('至少保留一个输入框');
  478. }
  479. },
  480. //1.提交表单 start ------------------------------------------------------------>
  481. //1.1 直接上传图片
  482. beforeAvatarUpload(file) {
  483. const isJPG = file.type === 'image/jpeg';
  484. const isPNG = file.type === 'image/png';
  485. const isLt2M = file.size / 1024 / 1024 < 2;
  486. if (!isJPG && !isPNG) {
  487. this.$message.error('上传缩略图只能是 JPG 或 PNG 格式!');
  488. return false;
  489. }
  490. if (!isLt2M) {
  491. this.$message.error('上传缩略图大小不能超过 2MB!');
  492. return false;
  493. }
  494. const formData = new FormData();
  495. formData.append('file', file);
  496. this.$store.dispatch('pool/uploadFile', formData).then(res => {
  497. this.imgUrl = res.data.imgUrl;//显示缩略图
  498. this.form.imgurl = res.data.imgUrl;//提供表单地址
  499. console.log(res.data.imgUrl)
  500. }).catch(() => {
  501. this.$message({
  502. type: 'info',
  503. message: '网络错误,请重试!'
  504. });
  505. })
  506. // 阻止默认的上传行为
  507. return false;
  508. },
  509. //1.2 提交表单
  510. addToServe() {
  511. if (this.form.islink == false) {
  512. if (this.form.is_survey == 1) {
  513. const hasEmptyInput = this.inputList.some(input => input.value === '');
  514. if (hasEmptyInput) {
  515. // 如果有输入框为空,弹出提示信息
  516. this.$message.error('请确保所有输入框都有内容');
  517. return;
  518. }
  519. const inputLists = this.inputList.map(input => input.value);
  520. const allowList = [this.checked ? 1 : 0, ""];
  521. if (this.checked) {
  522. inputLists.push(allowList);
  523. }
  524. if (inputLists.length <= 2) {
  525. this.$message.error('投票答案必须大于2条');
  526. return;
  527. }
  528. this.form.suvey_array = JSON.stringify(inputLists);
  529. }
  530. }
  531. // console.log('提交的数据:', this.inputList.map(input => input.value));
  532. // this.form.suvey_array
  533. // return false;
  534. //提交之前先判断是否为外链
  535. //如果使用了外链,清理掉除了外链以外的内容
  536. if (this.form.islink == true) {
  537. this.form.islink = 1;
  538. this.cleatForm(1)
  539. } else {
  540. this.form.islink = 0;
  541. }
  542. //如果推荐等级为空,则设置为0
  543. if (this.form.level == "") {
  544. this.form.level = 0;
  545. }
  546. //先进行验证
  547. this.$refs.form.validate(valid => {
  548. if (valid) {
  549. //console.log(this.form)
  550. this.$store.dispatch('news/addArticle', this.form).then(res => {
  551. if (res.code == 200) {
  552. //汇报结果
  553. this.$message({
  554. type: 'success',
  555. message: '已成功添加资讯!'
  556. });
  557. this.cleatForm(2);
  558. //返回列表页
  559. this.returnPage()
  560. } else {
  561. this.$message({
  562. type: 'error',
  563. message: "资讯发布失败,请稍后再试!"
  564. });
  565. }
  566. }).catch(() => {
  567. this.$message({
  568. type: 'info',
  569. message: '网络错误,请重试!'
  570. });
  571. })
  572. }
  573. })
  574. },
  575. //1.3 清理表单
  576. cleatForm(type) {
  577. if (type == 1) {
  578. //使用了外链,进行部分表单清理
  579. //this.form.cat_arr_id = "";
  580. this.form.level = "";
  581. this.form.imgurl = "";
  582. this.form.keyword = "";
  583. this.form.introduce = "";
  584. this.form.content = "";
  585. //this.form.author = "";
  586. this.form.hits = "";
  587. this.form.is_original = "";
  588. this.form.copyfrom = "";
  589. this.form.fromurl = "";
  590. this.form.status = "";
  591. }
  592. if (type == 2) {
  593. //完全清理表单
  594. this.form.title = "";
  595. this.form.islink = "";
  596. this.form.linkurl = "";
  597. this.form.cat_arr_id = "";
  598. this.form.level = "";
  599. this.form.imgurl = "";
  600. this.form.keyword = "";
  601. this.form.introduce = "";
  602. this.form.content = "";
  603. this.form.author = "";
  604. this.form.hits = "";
  605. this.form.is_original = "";
  606. this.form.copyfrom = "";
  607. this.form.fromurl = "";
  608. this.form.status = "";
  609. }
  610. },
  611. //提交表单 end ------------------------------------------------------------>
  612. //2.跳转操作 start ------------------------------------------------------------>
  613. returnPage() {
  614. this.$router.push({
  615. path: '/articleList',
  616. });
  617. },
  618. //跳转操作 end ------------------------------------------------------------>
  619. //3.回显操作 ------------------------------------------------------------>
  620. //3.1回显数据
  621. getMainData() {
  622. let data = {
  623. id: this.$route.query.id
  624. };
  625. this.$store.dispatch('news/getArticleInfo', data).then(res => {
  626. console.log(res);
  627. this.form.title = res.data.title;
  628. //判断是否使用了外链
  629. if (res.data.islink == 1) {
  630. this.form.islink = true;
  631. } else {
  632. this.form.islink = false;
  633. }
  634. //不是原创的时候显示来源
  635. if (res.data.is_original == 1) {
  636. this.form.is_original = 1;
  637. this.form.copyfrom = "本网";
  638. } else {
  639. this.form.is_original = 0;
  640. this.$nextTick(() => {
  641. this.form.is_original = 0;
  642. console.log('is_original:', this.form.is_original); // 确保值已更新
  643. });
  644. this.form.copyfrom = res.data.copyfrom;
  645. this.form.linkurl = res.data.linkurl;
  646. }
  647. //如果推荐等级为0 不再回显等级
  648. if (res.data.level == 0) {
  649. this.form.level = "";
  650. } else {
  651. this.form.level = res.data.level;
  652. }
  653. //回显站点名称
  654. this.form.web_site_id = res.data.web_site_id //站点名称
  655. this.form.cat_arr_id = Array.isArray(res.data.cat_arr_id) ? res.data.cat_arr_id : JSON.parse(res.data.cat_arr_id);
  656. console.log(this.form.cat_arr_id)
  657. //回显导航池 连同非管理员得一起刷新
  658. this.parentKey += 1; // 触发级联选择器重新加载
  659. this.loadCascaderPath(this.form.cat_arr_id); // 加载路径数据
  660. this.parentKey_2 += 1; // 触发级联选择器重新加载
  661. this.loadCascaderPath(this.form.cat_arr_id); // 加载路径数据
  662. //回显其他数据
  663. this.form.imgurl = res.data.imgurl;
  664. this.imgUrl = res.data.imgurl;
  665. this.form.keyword = res.data.keyword;
  666. this.form.introduce = res.data.introduce;
  667. this.form.content = res.data.content;
  668. this.form.author = res.data.author;
  669. this.form.hits = res.data.hits;
  670. this.form.is_original = res.data.is_original;
  671. this.form.copyfrom = res.data.copyfrom;
  672. this.form.fromurl = res.data.fromurl;
  673. this.form.status = res.data.status;
  674. this.form.survey_name = res.data.survey_name;
  675. this.form.is_survey = res.data.is_survey;
  676. this.form.survey_type = res.data.survey_type;
  677. this.inputList = [];
  678. if (res.data.survey_array.length > 0) {
  679. res.data.survey_array.forEach(item => {
  680. if (item.is_other == 0) {
  681. this.inputList.push({ "value": item.choice_name });
  682. } else {
  683. this.checked = true
  684. }
  685. });
  686. } else {
  687. this.inputList.push({ "value": "" });
  688. }
  689. console.log(this.inputList)
  690. })
  691. },
  692. async loadCascaderPath(path) {
  693. for (let i = 0; i < path.length; i++) {
  694. const parentId = path[i - 1] || 0; // 获取当前层级的父级ID
  695. const level = i; // 当前层级的索引
  696. await this.$store.dispatch('pool/categoryList', { pid: parentId })
  697. .then((res) => {
  698. const nodes = res.data.map(item => ({
  699. value: item.id,
  700. label: item.name,
  701. leaf: level >= 3, // 假设4层结构,设置叶子节点标记
  702. }));
  703. // 级联选择器加载数据
  704. if (level === path.length - 1) {
  705. this.form.cat_arr_id = path; // 确保最后一级路径正确设置
  706. this.parentKey += 1; // 强制刷新 cascader
  707. }
  708. });
  709. }
  710. },
  711. //1.3提交修改
  712. editToServe() {
  713. //不使用外联 验证投票逻辑
  714. if (this.form.islink == false) {
  715. if (this.form.is_survey == 1) {
  716. const hasEmptyInput = this.inputList.some(input => input.value === '');
  717. if (hasEmptyInput) {
  718. // 如果有输入框为空,弹出提示信息
  719. this.$message.error('请确保所有输入框都有内容');
  720. return;
  721. }
  722. const inputLists = this.inputList.map(input => input.value);
  723. const allowList = [this.checked ? 1 : 0, ""];
  724. if (this.checked) {
  725. inputLists.push(allowList);
  726. }
  727. if (inputLists.length < 2) {
  728. this.$message.error('投票答案必须大于2条');
  729. return;
  730. }
  731. this.form.suvey_array = JSON.stringify(inputLists);
  732. }
  733. }
  734. console.log(this.form)
  735. if (this.form.islink == 1) {
  736. this.cleatForm(1)
  737. }
  738. //如果推荐等级为空,则设置为0
  739. if (this.form.level == "") {
  740. this.form.level = 0;
  741. }
  742. //添加要修改的id
  743. this.form.id = this.editId;
  744. //先进行验证
  745. this.$refs.form.validate(valid => {
  746. if (valid) {
  747. //console.log(this.form)
  748. this.$store.dispatch('news/updateArticle', this.form).then(res => {
  749. if (res.code != 200) {
  750. this.$message.error("修改失败,请稍后再试!");
  751. } else {
  752. //汇报结果
  753. this.$message({
  754. type: 'success',
  755. message: '已成功编辑资讯!'
  756. });
  757. this.cleatForm(2);
  758. //返回列表页
  759. this.returnPage()
  760. }
  761. }).catch(() => {
  762. this.$message({
  763. type: 'info',
  764. message: '网络错误,请重试!'
  765. });
  766. })
  767. }
  768. })
  769. },
  770. //1.4 修改是否原创
  771. changeIsOriginal() {
  772. if (this.form.is_original == 1) {
  773. this.form.copyfrom = "本网";
  774. } else {
  775. this.form.copyfrom = "";
  776. this.form.fromurl = "";
  777. }
  778. },
  779. //跳转操作 end ------------------------------------------------------------>
  780. //4.富文本编辑器 start ------------------------------------------------------------>
  781. //4.1 编辑器点击上传图片
  782. handleImageClick() {
  783. this.$refs.multiFileInput.click(); // 打开文件选择框
  784. },
  785. handleMultipleFiles(event) {
  786. const files = event.target.files;
  787. if (files.length) {
  788. this.uploadMultipleImages(files); // 处理多图片上传
  789. }
  790. },
  791. uploadMultipleImages(files) {
  792. const uploadPromises = [];
  793. for (let i = 0; i < files.length; i++) {
  794. uploadPromises.push(this.uploadImage(files[i]));
  795. }
  796. Promise.all(uploadPromises).then(urls => {
  797. const quillEditor = this.$refs.quillEditor.quill;
  798. urls.forEach(url => {
  799. const range = quillEditor.getSelection();
  800. quillEditor.insertEmbed(range.index, 'image', url); // 在编辑器中插入图片
  801. });
  802. }).catch(error => {
  803. this.$message.error('图片上传失败,请重试!');
  804. });
  805. },
  806. uploadImage(file) {
  807. const formData = new FormData();
  808. formData.append('file', file);
  809. return this.$store.dispatch('pool/uploadFile', formData)
  810. .then(res => {
  811. if (res && res.data && res.data.imgUrl) {
  812. return res.data.imgUrl;
  813. } else {
  814. throw new Error('图片上传失败');
  815. }
  816. })
  817. .catch(error => {
  818. this.$message.error('图片上传失败,请重试!');
  819. throw error;
  820. });
  821. },
  822. //4.2 图片粘贴上传
  823. // 处理从网页粘贴的图片 URL
  824. handleImageFromWeb(imageUrl) {
  825. return new Promise((resolve) => {
  826. console.log('开始下载图片:', imageUrl);
  827. this.fetchImageAsBlob(imageUrl).then((blob) => {
  828. console.log('图片已下载为 Blob:', blob);
  829. const formData = new FormData();
  830. formData.append('file', blob, 'image.jpg');
  831. this.$store.dispatch('pool/uploadFile', formData).then((res) => {
  832. if (res && res.data && res.data.imgUrl) {
  833. console.log('图片上传成功:', res.data.imgUrl);
  834. resolve(res.data.imgUrl);
  835. } else {
  836. console.log('图片上传失败,保留原 URL:', imageUrl);
  837. resolve(imageUrl);
  838. }
  839. }).catch((error) => {
  840. console.error('图片上传时出现错误:', error);
  841. resolve(imageUrl);
  842. });
  843. }).catch((error) => {
  844. console.error('图片下载失败:', error);
  845. resolve(imageUrl);
  846. });
  847. });
  848. },
  849. fetchImageAsBlob(url) {
  850. return fetch(url)
  851. .then(response => {
  852. if (!response.ok) {
  853. throw new Error('Failed to fetch image');
  854. }
  855. return response.blob();
  856. });
  857. },
  858. //编辑源码
  859. toggleSourceMode() {
  860. if (!this.showHtml) {
  861. // 切换到源码模式,将编辑器内容同步到 textarea 中
  862. this.editorHtml = this.$refs.quillEditor.quill.root.innerHTML;
  863. this.showHtml = true; // 显示 textarea
  864. } else {
  865. // 切换回富文本模式,将 textarea 内容同步回编辑器
  866. this.showHtml = false; // 显示 Quill 编辑器
  867. // Quill 编辑器可能被销毁,所以使用 $nextTick 确保 DOM 渲染完成后再操作编辑器
  868. this.$nextTick(() => {
  869. if (this.$refs.quillEditor) {
  870. this.$refs.quillEditor.quill.root.innerHTML = this.editorHtml;
  871. } else {
  872. console.error('Quill 编辑器实例未找到');
  873. }
  874. });
  875. }
  876. },
  877. //富文本编辑器 end ------------------------------------------------------------>
  878. get_creatNews_form_id_fun() {//判断用户类型ajax
  879. this.$store.dispatch('public/getInfo').then(res => {
  880. // console.log("res======",res)
  881. this.form.user_type = res.data.type_id;
  882. }).catch(() => {
  883. this.$message({
  884. type: 'info',
  885. message: '网络错误,请重试!'
  886. });
  887. })
  888. // console.log("this.form.user_type==",this.form);
  889. // console.log("this.form.user_type==2",this.form.user_type);
  890. },
  891. get_creatNews_nav_pool_arr_fun() {//xx
  892. this.$store.dispatch('pool/get_creatNews_nav_actions', { page: 1, pageSize: 666666 }).then(res => {
  893. res.data.rows.forEach((per_obj) => {
  894. let new_per = {
  895. label: per_obj.website_name,
  896. value: per_obj.id,
  897. }
  898. this.creatNews_nav_pool_arr.push(new_per)
  899. })
  900. }).catch(() => {
  901. this.$message({
  902. type: 'info',
  903. message: '网络错误,请重试!'
  904. });
  905. })
  906. },
  907. creatNews_nav_pool_change_fun() {
  908. //开启导航池级联选择器
  909. this.ifwebsitId = true;
  910. console.log(this.ifwebsitId)
  911. //xx 导航池级
  912. let that = this;
  913. this.form.web_site_id = this.form.web_site_id[0]
  914. that.parentKey_2 += 1;
  915. this.$store.dispatch('pool/get_creatNews_nav_son_actions', { pid: String(this.creatNews_pid_num), website_id: String(this.form.web_site_id) }).then(res => {
  916. if (res.data.length == 0) {//没有导航池子级
  917. // alert("没有导航池子级");
  918. return
  919. }
  920. this.creatNews_add_nav_pool_arr = res.data;
  921. this.creatNews_add_nav_pool_arr.forEach((per_obj) => {
  922. per_obj.label = per_obj.name,
  923. per_obj.value = per_obj.id,
  924. this.creatNews_pid_num = per_obj.category_id
  925. })
  926. }).catch(() => {
  927. this.$message({
  928. type: 'info',
  929. message: '网络错误,请重试!'
  930. });
  931. })
  932. },
  933. },
  934. mounted() {
  935. this.creatNews_user_type = getUseType()
  936. this.websiteid = getWebSiteId()
  937. console.log(123456)
  938. console.log(this.websiteid)
  939. this.get_creatNews_form_id_fun()
  940. this.get_creatNews_nav_pool_arr_fun()
  941. //1.判断是新建还是回显
  942. if (this.$route.query.id != undefined) {
  943. this.editId = this.$route.query.id;
  944. this.editStatus = true;
  945. console.log("编辑新闻!")
  946. this.getMainData();
  947. } else {
  948. this.editStatus = false;
  949. console.log("添加新闻!")
  950. }
  951. //复制内容到富文本 start ------------------------------------------------------------>
  952. this.$nextTick(() => {
  953. const quillEditor = this.$refs.quillEditor.quill;
  954. if (quillEditor) {
  955. console.log('Quill 编辑器已初始化');
  956. // 在粘贴事件触发时,记录所有 img 的 src
  957. quillEditor.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => {
  958. if (node.tagName === 'IMG') {
  959. const imageUrl = node.getAttribute('src');
  960. console.log('检测到粘贴的图片 URL:', imageUrl);
  961. if (imageUrl && !imageUrl.startsWith('data:') && !imageUrl.startsWith('file://')) {
  962. // 先处理图片上传
  963. this.handleImageFromWeb(imageUrl).then((uploadedImageUrl) => {
  964. // 查找编辑器中所有 img 标签并替换 src
  965. const imgs = quillEditor.root.querySelectorAll('img');
  966. imgs.forEach((img) => {
  967. if (img.getAttribute('src') === imageUrl) {
  968. img.setAttribute('src', uploadedImageUrl); // 替换 src
  969. console.log('图片 src 已替换为:', uploadedImageUrl);
  970. }
  971. });
  972. });
  973. }
  974. }
  975. return delta; // 返回原始 delta
  976. });
  977. } else {
  978. console.error('Quill 初始化失败');
  979. }
  980. });
  981. //复制富文本 end ------------------------------------------------------------>
  982. },
  983. };
  984. </script>
  985. <style scoped lang="less">
  986. //文本编辑器
  987. .QuillTitle {
  988. line-height: 36px;
  989. font-size: 14px;
  990. color: #606266;
  991. font-weight: bold;
  992. padding-left: 30px;
  993. span {
  994. color: #ff4949
  995. }
  996. .QuillModelBtn {
  997. display: inline-block;
  998. margin-left: 10px;
  999. font-size: 12px;
  1000. color: #999;
  1001. cursor: pointer;
  1002. }
  1003. }
  1004. .editor-container {
  1005. height: 420px;
  1006. padding-bottom: 20px;
  1007. }
  1008. .my-quill-editor {
  1009. height: 320px;
  1010. }
  1011. .ql-editor {
  1012. height: 320px;
  1013. }
  1014. /* 富文本对齐方式 */
  1015. .ql-align-center {
  1016. text-align: center;
  1017. }
  1018. .ql-align-right {
  1019. text-align: right;
  1020. }
  1021. .ql-indent-1 {
  1022. padding-left: 16px;
  1023. }
  1024. .ql-indent-2 {
  1025. padding-left: 32px;
  1026. }
  1027. .ql-indent-3 {
  1028. padding-left: 48px;
  1029. }
  1030. .ql-indent-4 {
  1031. padding-left: 64px;
  1032. }
  1033. .ql-indent-5 {
  1034. padding-left: 80px;
  1035. }
  1036. .ql-indent-6 {
  1037. padding-left: 96px;
  1038. }
  1039. .ql-indent-7 {
  1040. padding-left: 112px;
  1041. }
  1042. .ql-indent-8 {
  1043. padding-left: 128px;
  1044. }
  1045. //执行v-deep穿透scope选择器 start------------------------------------------------------------>*/
  1046. ::v-deep .custom-form-item>.el-form-item__label {
  1047. line-height: 140px !important;
  1048. }
  1049. ::v-deep .custom-textarea .el-textarea__inner {
  1050. resize: none;
  1051. /* 禁止用户拖拽调整大小 */
  1052. }
  1053. ::v-deep .custom-align-right .el-form-item__label {
  1054. text-align: right;
  1055. /* 设置标签文字右对齐 */
  1056. }
  1057. ::v-deep .el-select {
  1058. width: 100%;
  1059. /* 禁止用户拖拽调整大小 */
  1060. }
  1061. ::v-deep .el-input-group__prepend {
  1062. color: black !important;
  1063. }
  1064. .formLabelFloatBox {
  1065. margin-bottom: 10px;
  1066. position: relative;
  1067. .formLabeladdIcon {
  1068. position: absolute;
  1069. right: 45px;
  1070. top: 5px;
  1071. width: 38px;
  1072. height: 24px;
  1073. }
  1074. .formLabelDelIcon {
  1075. position: absolute;
  1076. right: 5px;
  1077. top: 5px;
  1078. width: 38px;
  1079. height: 24px;
  1080. }
  1081. }
  1082. //执行v-deep穿透scope选择器 end------------------------------------------------------------>*/</style>