newsadd.vue 16 KB

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