newsaddsq.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. <template>
  2. <view class="check">
  3. <uni-forms ref="form" :model="datainfo">
  4. <view class="cbox">
  5. <view class="chmain">
  6. <uni-forms-item label="资讯类型" name="communityType">
  7. <picker range-key='dictLabel' :disabled="isdisabled" :value="wzlxidx" :range="wzlxList" @change='bindDateChange'>
  8. <view class="flexc">
  9. <view class="flex1 txr f13 co27" v-if="datainfo.communityType&&!wzlx">{{statusFormats(datainfo.communityType,wzlxList,'wzlx')}}</view>
  10. <view class="flex1 txr f13" v-else :class="wzlx?'co27':'coa'">{{wzlx||"请选择资讯类型"}}</view>
  11. <view class="rimg"><image :src="rimg"></image></view>
  12. </view>
  13. </picker>
  14. </uni-forms-item>
  15. <uni-forms-item label="发布时间" name="publishTime">
  16. <picker mode="date" :disabled="isdisabled" @change='bindDateChangeb'>
  17. <view class="flexc">
  18. <view class="flex1 txr f13" :class="datainfo.publishTime?'co27':'coa'">{{datainfo.publishTime||"请选择发布时间"}}</view>
  19. <view class="rimg"><image :src="rimg"></image></view>
  20. </view>
  21. </picker>
  22. </uni-forms-item>
  23. <uni-forms-item label="是否启用" name="status">
  24. <view class="flexc" @click="getChangeFn">
  25. <view class="flex1"></view>
  26. <image :src="check" v-if="datainfo.status=='0'" class="checkimg"></image>
  27. <image :src="ncheck" v-else class="checkimg"></image>
  28. </view>
  29. </uni-forms-item>
  30. <!-- <uni-forms-item label="是否置顶" name="isTop">
  31. <picker range-key='dictLabel' :disabled="isdisabled" :value="sfztidx" :range="sfztList" @change='bindDateChangea'>
  32. <view class="flexc">
  33. <view class="flex1 txr f13 co27" v-if="datainfo.isTop&&!sfzt">{{statusFormats(datainfo.isTop,sfztList,'sfzt')}}</view>
  34. <view class="flex1 txr f13" v-else :class="sfzt?'co27':'coa'">{{sfzt||"请选择是否置顶"}}</view>
  35. <view class="rimg"><image :src="rimg"></image></view>
  36. </view>
  37. </picker>
  38. </uni-forms-item> -->
  39. </view>
  40. </view>
  41. <view class="cbox">
  42. <view class="chmain pb10">
  43. <uni-forms-item label-width='0' name="communityTitle">
  44. <uni-easyinput type="textarea" :disabled="isdisabled" autoHeight v-model="datainfo.communityTitle" :inputBorder='false' placeholder="输入标题" />
  45. </uni-forms-item>
  46. <view>
  47. <view class='toolbar' @tap="format">
  48. <view :class="formats.bold ? 'ql-active' : ''" class="iconfont icon-zitijiacu" data-name="bold"></view>
  49. <view :class="formats.italic ? 'ql-active' : ''" class="iconfont icon-zitixieti" data-name="italic"></view>
  50. <view :class="formats.underline ? 'ql-active' : ''" class="iconfont icon-zitixiahuaxian" data-name="underline"></view>
  51. <view :class="formats.strike ? 'ql-active' : ''" class="iconfont icon-zitishanchuxian" data-name="strike"></view>
  52. <view :class="formats.align === 'left' ? 'ql-active' : ''" class="iconfont icon-zuoduiqi" data-name="align"
  53. data-value="left"></view>
  54. <view :class="formats.align === 'center' ? 'ql-active' : ''" class="iconfont icon-juzhongduiqi" data-name="align"
  55. data-value="center"></view>
  56. <view :class="formats.align === 'right' ? 'ql-active' : ''" class="iconfont icon-youduiqi" data-name="align"
  57. data-value="right"></view>
  58. <view :class="formats.align === 'justify' ? 'ql-active' : ''" class="iconfont icon-zuoyouduiqi" data-name="align"
  59. data-value="justify"></view>
  60. <view :class="formats.lineHeight ? 'ql-active' : ''" class="iconfont icon-line-height" data-name="lineHeight"
  61. data-value="2"></view>
  62. <view :class="formats.letterSpacing ? 'ql-active' : ''" class="iconfont icon-Character-Spacing" data-name="letterSpacing"
  63. data-value="2em"></view>
  64. <view :class="formats.marginTop ? 'ql-active' : ''" class="iconfont icon-722bianjiqi_duanqianju" data-name="marginTop"
  65. data-value="20px"></view>
  66. <view :class="formats.previewarginBottom ? 'ql-active' : ''" class="iconfont icon-723bianjiqi_duanhouju"
  67. data-name="marginBottom" data-value="20px"></view>
  68. <view class="iconfont icon-clearedformat" @tap="removeFormat"></view>
  69. <view :class="formats.fontFamily ? 'ql-active' : ''" class="iconfont icon-font" data-name="fontFamily" data-value="Pacifico"></view>
  70. <view :class="formats.fontSize === '24px' ? 'ql-active' : ''" class="iconfont icon-fontsize" data-name="fontSize"
  71. data-value="24px"></view>
  72. <view :class="formats.color === '#0000ff' ? 'ql-active' : ''" class="iconfont icon-text_color" data-name="color"
  73. data-value="#0000ff"></view>
  74. <view :class="formats.backgroundColor === '#00ff00' ? 'ql-active' : ''" class="iconfont icon-fontbgcolor"
  75. data-name="backgroundColor" data-value="#00ff00"></view>
  76. <view class="iconfont icon-date" @tap="insertDate"></view>
  77. <view class="iconfont icon--checklist" data-name="list" data-value="check"></view>
  78. <view :class="formats.list === 'ordered' ? 'ql-active' : ''" class="iconfont icon-youxupailie" data-name="list"
  79. data-value="ordered"></view>
  80. <view :class="formats.list === 'bullet' ? 'ql-active' : ''" class="iconfont icon-wuxupailie" data-name="list"
  81. data-value="bullet"></view>
  82. <view class="iconfont icon-undo" @tap="undo"></view>
  83. <view class="iconfont icon-redo" @tap="redo"></view>
  84. <view class="iconfont icon-outdent" data-name="indent" data-value="-1"></view>
  85. <view class="iconfont icon-indent" data-name="indent" data-value="+1"></view>
  86. <view class="iconfont icon-fengexian" @tap="insertDivider"></view>
  87. <view class="iconfont icon-charutupian" @tap="insertImage"></view>
  88. <view :class="formats.header === 1 ? 'ql-active' : ''" class="iconfont icon-format-header-1" data-name="header"
  89. :data-value="1"></view>
  90. <view :class="formats.script === 'sub' ? 'ql-active' : ''" class="iconfont icon-zitixiabiao" data-name="script"
  91. data-value="sub"></view>
  92. <view :class="formats.script === 'super' ? 'ql-active' : ''" class="iconfont icon-zitishangbiao" data-name="script"
  93. data-value="super"></view>
  94. <view class="iconfont icon-shanchu" @tap="clear"></view>
  95. <view :class="formats.direction === 'rtl' ? 'ql-active' : ''" class="iconfont icon-direction-rtl" data-name="direction"
  96. data-value="rtl"></view>
  97. </view>
  98. <editor id="editor" class="ql-container" placeholder="开始输入..." showImgSize showImgToolbar showImgResize
  99. @statuschange="onStatusChange" :read-only="isdisabled" @ready="onEditorReady">
  100. </editor>
  101. <!-- <editor-box ></editor-box> -->
  102. </view>
  103. <!-- <uni-forms-item label="文章类型" name="phonenumber">
  104. <view class="flexc">
  105. <picker range-key='dictLabel' :value="syqxidx" :range="sexs" @change='bindDateChange'>
  106. <view class="rimg"><image :src="rimg"></image></view>
  107. </picker>
  108. </view>
  109. </uni-forms-item> -->
  110. </view>
  111. </view>
  112. </uni-forms>
  113. <view class="rfbtn" @click="getEditFn" v-if="isdisabled">修改</view>
  114. <view class="rfbtn" @click="getSubmit" v-else>发布</view>
  115. <loading></loading>
  116. </view>
  117. </template>
  118. <script>
  119. import config from '@/config'
  120. import editorBox from "@/manage/components/editor/editor.vue"
  121. import {checkPermi,checkRole} from "@/utils/permission"; // 权限判断函数
  122. import {getDictionaryFn} from "@/api/system/user.js"
  123. import {selectValueKey,uploadmore} from "@/utils/common.js"
  124. import {newsDet,newsPut,newsAdd} from "@/api/work/manage.js"
  125. export default {
  126. components: {editorBox},
  127. data() {
  128. return {
  129. rimg: require('@/people/static/people/rimg.png'),
  130. baseUrl: config.baseUrl,
  131. checkflag:true,
  132. check: require('@/people/static/people/check.png'),
  133. ncheck: require('@/people/static/people/ncheck.png'),
  134. datainfo: {
  135. // "communityId":"社区资讯ID",
  136. "communityTitle":"",//社区资讯标题
  137. "communityType":"",//社区资讯类型(1:公告 2:通知 3:资讯)
  138. "communityContent":"",//社区资讯内容
  139. "status":"0",//社区资讯状态(0正常 1关闭)
  140. "publishTime":"",//发布时间
  141. // "coverImage":"封面图片",
  142. // "author":"作者",
  143. // "source":"来源",
  144. // "viewCount":"浏览次数",
  145. // "isTop":"是否置顶:Y(置顶)、N(不置顶)"
  146. },
  147. formats: {},
  148. readOnly: false,
  149. wzlx:'',
  150. wzlxidx:'0',
  151. wzlxList:[],
  152. sfzt:'否',
  153. sfztidx:'1',
  154. sfztList:[{dictLabel:'是',dictValue:'Y'},{dictLabel:'否',dictValue:'N'}],
  155. id:'',
  156. ptype:"add",
  157. isdisabled:false,
  158. editinfo:''
  159. }
  160. },
  161. onLoad: function(e) {
  162. this.init()
  163. if(e.id){
  164. this.id=e.id;
  165. this.ptype='edit';
  166. // this.isdisabled=true;
  167. this.getDetailFn()
  168. }else{
  169. this.datainfo.publishTime=this.time()
  170. }
  171. if(e.tabval&&e.tabval!='yty'){
  172. this.datainfo.communityType=e.tabval
  173. }
  174. },
  175. methods: {
  176. checkPermi,
  177. checkRole,
  178. time(){
  179. var date = new Date();
  180. var y = date.getFullYear();
  181. var m = date.getMonth() + 1;
  182. var d = date.getDate();
  183. var h = date.getHours();
  184. var min = date.getMinutes();
  185. var s = date.getSeconds();
  186. var yearStr = y + '-' + (m < 10 ? ('0' + m) : m) + '-' + (d < 10 ? ('0' + d) : d)
  187. // var timeStr = (h < 10 ? ('0' + h) : h) + ':' + (min < 10 ? ('0' + min) : min) + ':' + (s < 10 ? (
  188. // '0' + s) : s);
  189. // var kaTime = yearStr + ' ' + timeStr;
  190. return yearStr
  191. },
  192. getEditFn(){
  193. this.isdisabled=false;
  194. },
  195. statusFormats(data, list,type) {
  196. var aite=selectValueKey(list, data);
  197. if(type=='wzlx'){
  198. this.wzlxidx=aite.key
  199. }else if(type=='sfzt'){
  200. this.sfztidx=aite.key
  201. }
  202. return aite.actions;
  203. },
  204. bindDateChange(e){
  205. var val=e.detail.value;
  206. this.datainfo.communityType=this.wzlxList[val].dictValue;
  207. this.wzlx=this.wzlxList[val].dictLabel;
  208. },
  209. bindDateChangea(e){
  210. var val=e.detail.value;
  211. this.datainfo.isTop=this.sfztList[val].dictValue;
  212. this.sfzt=this.sfztList[val].dictLabel;
  213. },
  214. bindDateChangeb(e){
  215. var val=e.detail.value;
  216. this.datainfo.publishTime=val;
  217. },
  218. getChangeFn(){
  219. if(this.isdisabled){
  220. return
  221. }
  222. if(this.datainfo.status=='1'){
  223. this.datainfo.status='2'
  224. }else{
  225. this.datainfo.status='1'
  226. }
  227. },
  228. init(){
  229. // 文章类型
  230. getDictionaryFn('community_typ').then(res=>{
  231. if(res.code==200){
  232. if(res.data){
  233. this.wzlxList = res.data.map(v => {
  234. return {
  235. dictLabel: v.dictLabel,
  236. dictValue: v.dictValue
  237. }
  238. })
  239. }
  240. }
  241. })
  242. },
  243. getDetailFn(){
  244. var that=this;
  245. newsDet(this.id).then(res=>{
  246. if(res.code==200){
  247. this.datainfo=res.data;
  248. var data=JSON.parse(JSON.stringify(res.data))
  249. if(data.communityContent){
  250. var fwbinfo=this.formatRichText(res.data.communityContent);
  251. this.editinfo=fwbinfo;
  252. uni.createSelectorQuery().select('#editor').context(function(res) {
  253. that.editorCtx = res.context||'';
  254. that.editorCtx.setContents({
  255. html:fwbinfo
  256. })
  257. }).exec();
  258. }
  259. }
  260. })
  261. },
  262. getEditorContent(){
  263. return new Promise((resolve, reject) => {
  264. if (this.editorCtx) {
  265. var infoContent='';
  266. this.editorCtx.getContents({
  267. success: function(data) {
  268. var s=data.html;
  269. infoContent=s.replace(/\<img src="(http?:\/\/)([^\/]+)(:\d+)?/g,'<img src="');
  270. infoContent=infoContent.replace(/\<img src="(https?:\/\/)([^\/]+)(:\d+)?/g,'<img src="');
  271. resolve(infoContent)
  272. },
  273. fail: (err) => {
  274. reject(err)
  275. }
  276. })
  277. } else {
  278. reject('编辑器未初始化')
  279. }
  280. })
  281. },
  282. async getSubmit() {
  283. try {
  284. var that=this;
  285. const content = await this.getEditorContent()
  286. this.$refs.form.validate().then(res => {
  287. var params=JSON.parse(JSON.stringify(this.datainfo))
  288. if(!params.communityType){
  289. this.$toast('请选择资讯类型')
  290. return
  291. }
  292. if(!params.publishTime){
  293. this.$toast('请选择发布时间')
  294. return
  295. }
  296. if(!params.communityTitle){
  297. this.$toast('请输入标题')
  298. return
  299. }
  300. params.communityContent=content;
  301. if(this.ptype=='add'){
  302. newsAdd(params).then(res=>{
  303. if(res.code==200){
  304. this.$toast("新增成功")
  305. setTimeout(function(){
  306. uni.$emit("newsList")
  307. uni.navigateBack({
  308. delta:1
  309. })
  310. },1500)
  311. }
  312. })
  313. }else{
  314. newsPut(params).then(res=>{
  315. if(res.code==200){
  316. this.$toast("修改成功")
  317. setTimeout(function(){
  318. uni.$emit("newsList")
  319. uni.navigateBack({
  320. delta:1
  321. })
  322. },1500)
  323. }
  324. })
  325. }
  326. })
  327. } catch (error) {
  328. console.error('提交失败:', error)
  329. uni.showToast({
  330. title: error.message || '提交失败',
  331. icon: 'none'
  332. })
  333. } finally {
  334. }
  335. },
  336. //解析富文本方法
  337. formatRichText(html) {
  338. let newContent = html.replace(/<img[^>]*>/gi, function(match, capture) {
  339. match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '').replace(/style=""/gi, '');
  340. // match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
  341. // match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
  342. return match;
  343. });
  344. newContent = newContent.replace(/style="[^"]+"/gi, function(match, capture) {
  345. match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi, 'max-width:100%;');
  346. return match;
  347. });
  348. newContent = newContent.replace(/<br[^>]*\/>/gi, '');
  349. newContent = newContent.replace(/\<img src="/gi,
  350. '<img style="max-width:100%;height:auto;display:block;margin:10rpx auto;" src="' +this.baseUrl);
  351. return newContent;
  352. },
  353. readOnlyChange() {
  354. this.readOnly = !this.readOnly
  355. },
  356. onEditorReady() {
  357. var that=this;
  358. // #ifdef MP-BAIDU
  359. this.editorCtx = requireDynamicLib('editorLib').createEditorContext('editor');
  360. // #endif
  361. // #ifdef APP-PLUS || MP-WEIXIN || H5
  362. uni.createSelectorQuery().select('#editor').context((res) => {
  363. this.editorCtx = res.context
  364. that.editorCtx.setContents({
  365. html:that.editinfo
  366. })
  367. }).exec()
  368. // #endif
  369. },
  370. undo() {
  371. this.editorCtx.undo()
  372. },
  373. redo() {
  374. this.editorCtx.redo()
  375. },
  376. format(e) {
  377. let {
  378. name,
  379. value
  380. } = e.target.dataset
  381. if (!name) return
  382. // console.log('format', name, value)
  383. this.editorCtx.format(name, value)
  384. },
  385. onStatusChange(e) {
  386. const formats = e.detail
  387. this.formats = formats
  388. },
  389. insertDivider() {
  390. this.editorCtx.insertDivider({
  391. success: function() {
  392. console.log('insert divider success')
  393. }
  394. })
  395. },
  396. clear() {
  397. uni.showModal({
  398. title: '清空编辑器',
  399. content: '确定清空编辑器全部内容?',
  400. success: res => {
  401. if (res.confirm) {
  402. this.editorCtx.clear({
  403. success: function(res) {
  404. console.log("clear success")
  405. }
  406. })
  407. }
  408. }
  409. })
  410. },
  411. removeFormat() {
  412. this.editorCtx.removeFormat()
  413. },
  414. insertDate() {
  415. const date = new Date()
  416. const formatDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`
  417. this.editorCtx.insertText({
  418. text: formatDate
  419. })
  420. },
  421. insertImage() {
  422. var that=this;
  423. uni.chooseImage({
  424. count: 1,
  425. success: (res) => {
  426. let img= res.tempFilePaths;
  427. let imglen = res.tempFilePaths.length;
  428. var fuwufile = [];
  429. uploadmore('/common/upload',img,0,0,0,imglen,fuwufile,function(rs){
  430. var url=that.baseUrl+rs;
  431. that.editorCtx.insertImage({
  432. src: url,
  433. alt: '图像',
  434. success: function() {
  435. console.log('insert image success')
  436. }
  437. })
  438. })
  439. }
  440. })
  441. }
  442. }
  443. }
  444. </script>
  445. <style>
  446. page{background: #F3F3F0;}
  447. </style>
  448. <style lang="scss" scoped>
  449. .check /deep/ .uni-forms-item{min-height: 106rpx;box-sizing: border-box;display: flex;align-items: center;margin-bottom: 0;border-bottom: 2rpx solid #E6E6E6;padding:10rpx 0;}
  450. .check .cbox /deep/ .uni-forms-item:last-child{border: none;}
  451. .check /deep/ .uni-forms-item__label{font-weight: bold;font-size: 26rpx;color: #222327;flex: 0 0 auto;width: auto !important;}
  452. .check /deep/ .uni-easyinput{flex: 1;text-align: left;font-size: 26rpx;color: #222327;}
  453. .check /deep/ .uni-easyinput__content-textarea{min-height: 40rpx;font-size: 26rpx;}
  454. .check /deep/ .uni-easyinput__placeholder-class{font-size: 26rpx;color: #AAAAAA;}
  455. .check /deep/ .uni-easyinput__content-input{padding-left: 0 !important;}
  456. .check /deep/ .uni-input-input{font-size: 26rpx;}
  457. .check /deep/ .uni-textarea-textarea{font-size: 26rpx;}
  458. .check /deep/ .is-disabled{color: #222327;background-color: #ffffff !important;}
  459. .check /deep/ .uni-data-checklist .checklist-group .checklist-box{margin:10rpx 8rpx 10rpx 16rpx;}
  460. .check /deep/ .uni-data-checklist{flex: 0 0 auto;}
  461. .check{min-height: 100vh;padding: 20rpx 18rpx 110rpx;box-sizing: border-box;}
  462. .cbox{background: #FFFFFF;border-radius: 20rpx;flex: 1;margin-bottom: 24rpx;
  463. .chmain{
  464. padding: 0 32rpx;
  465. .rimg{width: 16rpx;height: 28rpx;flex: 0 0 auto;margin-left: 20rpx;
  466. image{width: 100%;height: 100%;}
  467. }
  468. .checkimg{width: 80rpx;height: 40rpx;margin-right: 8rpx;}
  469. }
  470. }
  471. @import "@/static/editor-icon.css";
  472. .page-body {
  473. height: calc(100vh - var(--window-top) - var(--status-bar-height));
  474. }
  475. .wrapper {
  476. height: 100%;
  477. }
  478. .editor-wrapper {
  479. height: calc(100vh - var(--window-top) - var(--status-bar-height) - 140px);
  480. background: #fff;
  481. }
  482. .iconfont {
  483. display: inline-block;
  484. padding: 8px 8px;
  485. width: 24px;
  486. height: 24px;
  487. cursor: pointer;
  488. font-size: 20px;
  489. }
  490. .toolbar {
  491. margin-bottom: 20rpx;
  492. box-sizing: border-box;
  493. border-bottom: 0;
  494. font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
  495. }
  496. .ql-container {
  497. box-sizing: border-box;
  498. width: 100%;
  499. min-height: 30vh;
  500. height: 100%;
  501. font-size: 16px;
  502. line-height: 1.5;
  503. }
  504. .ql-active {
  505. color: #06c;
  506. }
  507. </style>