企微助手 ,仓库名 短剧

editCon.vue 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. <template>
  2. <div class="container">
  3. <div class="editCon" :style="disabled ? 'padding:0' : ''">
  4. <div class="insert" v-if="source == 'welcom'">
  5. <span @click="insertAtCursor">「插入客户昵称」</span>
  6. </div>
  7. <textarea class="textarea self-scrollbar-3" ref="textarea" v-if="!disabled" autocomplete="off"
  8. :placeholder="source == 'welcom' ? '请输入欢迎语' : '请输入群发内容'" v-model="content" @input="contentChange"></textarea>
  9. <!-- <div contentEditable='true' id="textarea" class="textarea self-scrollbar-3" v-if="!disabled" autocomplete="off" maxlength="1000" v-html="content" :placeholder="source=='welcom'?'请输入欢迎语':'请输入群发内容'" @input="contentChange">
  10. {{content}}
  11. </div> -->
  12. <div class="textarea self-scrollbar-3 pointer-drop" style="white-space: pre-wrap;color:#666" v-else>{{ content }}
  13. </div>
  14. <div class="flex">
  15. <div class="warning_hint" v-if="$getStrBytes(content) > 4000"> <i class="el-icon-warning-outline"></i>
  16. 消息文本内容,最多4000个字节,已超出!</div>
  17. <div class="maxFont" style="flex:1">{{ $getStrBytes(content) }}/4000字节</div>
  18. </div>
  19. <div class="fujian" v-if="attachments && attachments.length > 0">
  20. <draggable class="syllable_ul" element="ul" :disabled="disabled" :list="attachments"
  21. :options="{ group: 'name', animation: 100 }">
  22. <div class="fujianItem" :class="disabled ? 'pointer-drop' : ''" v-for="(item, index) in attachments"
  23. :key="index + attachments_idx">
  24. <div class="left"><i class="el-icon-remove-outline" v-if="!disabled" @click="deleteAttachment(index)"></i>
  25. <span v-if="item.msgtype == 'image'" class="flex-align-center">【图片】:<img style="width:16px;height:16px"
  26. :src="item.image.pic_url" alt=""></span>
  27. <span v-if="item.msgtype == 'promote'">【H5推广】:{{ item.promote.title }}</span>
  28. <span v-if="item.msgtype == 'miniprogram'">【小程序】:{{ item.miniprogram.title }}</span>
  29. <span v-if="item.msgtype == 'radar'">【智能雷达】:{{ item.radar.name }}</span>
  30. <span v-if="item.msgtype == 'link'">【链接】:{{ item.link.title }}</span>
  31. </div>
  32. <div class="right" v-if="!disabled">
  33. <i class="el-icon-edit-outline" @click="editAttachment(item, index)"></i>
  34. </div>
  35. </div>
  36. </draggable>
  37. </div>
  38. <div class="addFileBox" v-if="!disabled">
  39. <el-popover placement="top" trigger="click">
  40. <div slot="reference" style="display:inline-block" class="pointer">
  41. <i class="el-icon-circle-plus-outline"></i>
  42. <span>添加附件</span>
  43. </div>
  44. <div class="propoverItem" @click="fileEvent('img')">
  45. <img src="@/assets/img/tupian.png" alt="">
  46. <span>图片</span>
  47. </div>
  48. <div class="propoverItem" @click="fileEvent('linkExtend')">
  49. <img src="@/assets/img/tg_link.png" alt="">
  50. <span>H5推广</span>
  51. </div>
  52. <div class="propoverItem" @click="fileEvent('miniprogram')">
  53. <img src="@/assets/img/xiaochengxu.png" alt="">
  54. <span>小程序</span>
  55. </div>
  56. <div class="propoverItem" @click="fileEvent('radar')">
  57. <img src="@/assets/img/radar.png" alt="">
  58. <span>智能雷达</span>
  59. </div>
  60. <div class="propoverItem" @click="fileEvent('link')">
  61. <img src="@/assets/img/lianjie.png" alt="">
  62. <span>链接</span>
  63. </div>
  64. </el-popover>
  65. </div>
  66. </div>
  67. <div class="self-hint" style="margin-top:10px" v-if="source == 'qun'">
  68. <span>注意:
  69. 每位客户每天可以接收1条群发消息,不限企业发布的群发还是个人发布的群发。</span>
  70. </div>
  71. <div class="phonePreviewBox">
  72. <phonePreview :phone_width='phone_width' :content='content' :attachments='attachments'></phonePreview>
  73. </div>
  74. <!-- 添加图片 -->
  75. <el-dialog title="添加图片" append-to-body :visible.sync="imgVisible" width="500px" center
  76. :close-on-click-modal="false">
  77. <!-- <div class="lineItem">
  78. <label>图片标题:</label>
  79. <el-input class="input" size="small" placeholder="请输入图片标题(选填)" v-model="image.media_id" clearable>
  80. </el-input>
  81. </div> -->
  82. <div class="lineItem">
  83. <label><em>*</em>图片:</label>
  84. <el-upload class="avatar-uploader" :action="URL.BASEURL + URL.material_upload" name="material_file"
  85. :show-file-list="false" :data="fileData2" :on-success="uploadSuccess" :on-progress='beforeUploadUpload'
  86. :on-error='uploadFail' accept=".jpg,.jpeg,.png">
  87. <img v-if="image.pic_url" :src="image.pic_url" class="fm_img">
  88. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  89. </el-upload>
  90. </div>
  91. <p class="uploadImgHint">*图片仅支持png或jpg格式,且文件大小不得超过10M。</p>
  92. <div class="buttons">
  93. <el-button type="primary" plain size="mini" @click="imgVisible = false">取消</el-button>
  94. <el-button type="primary" size="mini" @click="imageDefine">确定</el-button>
  95. </div>
  96. </el-dialog>
  97. <!-- 添加链接 -->
  98. <el-dialog title="添加链接" append-to-body :visible.sync="linkVisible" width="500px" center
  99. :close-on-click-modal="false">
  100. <div class="lineItem">
  101. <label><em>*</em>链接标题:</label>
  102. <div class="input">
  103. <div class="flex">
  104. <el-input class="input" type="textarea" size="small" placeholder="请输入链接标题" v-model="link.title" clearable>
  105. </el-input>
  106. <span class="font_zj">{{ $getStrBytes(link.title) }}/128字节</span>
  107. </div>
  108. <div class="warning_hint f12" style="margin-left:0" v-if="$getStrBytes(link.title) > 128"> <i
  109. class="el-icon-warning-outline"></i> 链接标题,最多128个字节,已超出!</div>
  110. </div>
  111. </div>
  112. <div class="lineItem">
  113. <label><em>*</em>链接地址:</label>
  114. <div class="input">
  115. <div class="flex">
  116. <el-input class="input" type="textarea" size="small" placeholder="请输入链接地址" v-model="link.url" clearable>
  117. </el-input>
  118. <span class="font_zj">{{ $getStrBytes(link.url) }}/2048字节</span>
  119. </div>
  120. <div class="warning_hint f12" style="margin-left:0" v-if="$getStrBytes(link.url) > 2048"> <i
  121. class="el-icon-warning-outline"></i> 链接地址,最多2048个字节,已超出!</div>
  122. </div>
  123. <!-- <el-input class="input" size="small" placeholder="请输入链接地址" v-model="link.url" clearable></el-input> -->
  124. </div>
  125. <div class="lineItem">
  126. <label>图文封面:</label>
  127. <el-upload class="avatar-uploader" :action="URL.BASEURL + URL.material_upload" name="material_file"
  128. :show-file-list="false" :data="fileData" :on-success="uploadSuccess" :on-progress='beforeUploadUpload'
  129. :on-error='uploadFail' accept=".jpg,.jpeg,.png">
  130. <img v-if="link.picurl" :src="link.picurl" class="fm_img">
  131. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  132. </el-upload>
  133. </div>
  134. <p class="uploadImgHint" style="margin-left:40px;">*图片仅支持png或jpg格式,且文件大小不得超过10M。</p>
  135. <div class="lineItem">
  136. <label>封面描述:</label>
  137. <div class="input">
  138. <div class="flex">
  139. <el-input class="input" type="textarea" size="small" placeholder="请输入封面描述" v-model="link.desc" clearable>
  140. </el-input>
  141. <span class="font_zj">{{ $getStrBytes(link.desc) }}/512字节</span>
  142. </div>
  143. <div class="warning_hint f12" style="margin-left:0" v-if="$getStrBytes(link.desc) > 512"> <i
  144. class="el-icon-warning-outline"></i> 封面描述,最多512个字节,已超出!</div>
  145. </div>
  146. <!-- <el-input class="input" size="small" placeholder="请输入封面描述" v-model="link.desc" clearable></el-input> -->
  147. </div>
  148. <div class="buttons">
  149. <el-button type="primary" plain size="mini" @click="linkVisible = false">取消</el-button>
  150. <el-button type="primary" size="mini" @click="linkDefine">确定</el-button>
  151. </div>
  152. </el-dialog>
  153. <!-- 小程序 -->
  154. <el-dialog title="添加小程序" append-to-body :visible.sync="miniprogramVisible" width="650px" center
  155. :close-on-click-modal="false">
  156. <div style="padding:0 15px;">
  157. <div class="self-hint" style="margin-bottom:20px;border:none">
  158. <i class="el-icon-message-solid"></i>
  159. <span>请填写企业微信后台绑定的小程序id和路径,否则会造成发送失败</span>
  160. </div>
  161. <div class="lineItem">
  162. <label><em>*</em>小程序标题:</label>
  163. <div class="input">
  164. <div class="flex">
  165. <el-input class="input" type="textarea" size="small" placeholder="请输入小程序标题" v-model="miniprogram.title"
  166. clearable></el-input>
  167. <span class="font_zj">{{ $getStrBytes(miniprogram.title) }}/64字节</span>
  168. </div>
  169. <div class="warning_hint f12" style="margin-left:0" v-if="$getStrBytes(miniprogram.title) > 64"> <i
  170. class="el-icon-warning-outline"></i> 小程序标题,最多64个字节,已超出!</div>
  171. </div>
  172. <!-- <el-input class="input" size="small" placeholder="请输入小程序标题" v-model="miniprogram.title" clearable></el-input> -->
  173. </div>
  174. <div class="lineItem">
  175. <label><em>*</em>小程序appID:</label>
  176. <div style="flex:1">
  177. <el-input class="input" size="small" placeholder="请输入小程序appID" v-model="miniprogram.appid" clearable>
  178. </el-input>
  179. <p class="otherHint" style="color:#f9a527">*小程序appID<a
  180. href="https://docs.qq.com/doc/p/cb25fa9e1aba98ce5f8b942f2900f0247b9e5dc6?dver=2.1.27292865"
  181. target="_blank">(如何获取小程序appID)</a>,必须是关联到企业的小程序应用。</p>
  182. </div>
  183. </div>
  184. <div class="lineItem">
  185. <label><em>*</em>小程序路径:</label>
  186. <div style="flex:1">
  187. <el-input class="input" size="small" placeholder="请输入小程序路径" v-model="miniprogram.page" clearable></el-input>
  188. <p class="otherHint"><a
  189. href="https://docs.qq.com/doc/p/16fa15eeb1fc21849904a0a82ebda04732e3bc16?dver=2.1.27292865"
  190. target="_blank">如何获取小程序路径?</a></p>
  191. </div>
  192. </div>
  193. <div class="lineItem">
  194. <label><em>*</em>小程序封面:</label>
  195. <el-upload class="avatar-uploader" :action="URL.BASEURL + URL.material_upload" name="material_file"
  196. :show-file-list="false" :data="fileData2" :on-success="uploadSuccess" :on-progress='beforeUploadUpload'
  197. :on-error='uploadFail' accept=".jpg,.jpeg,.png">
  198. <img v-if="miniprogram.pic_url" :src="miniprogram.pic_url" class="fm_img">
  199. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  200. </el-upload>
  201. </div>
  202. <p class="uploadImgHint" style="margin-left:20px;">*图片仅支持png或jpg格式,且文件大小不得超过10M。封面图建议尺寸为520*416。</p>
  203. <div class="buttons">
  204. <el-button type="primary" plain size="mini" @click="miniprogramVisible = false">取消</el-button>
  205. <el-button type="primary" size="mini" @click="miniprogramDefine">确定</el-button>
  206. </div>
  207. </div>
  208. </el-dialog>
  209. <!-- 智能雷达 -->
  210. <radarEntrance ref="radarEntranceRef" @getRadarAttach="(val) => { radarDefine(val) }" :ids_comeBack="radarIds"
  211. :has_attachLen="has_attachLen"></radarEntrance>
  212. <!-- 推广链接 -->
  213. <el-dialog title="添加H5推广" append-to-body :visible.sync="linkExtendVisible" width="500px" center
  214. :close-on-click-modal="false">
  215. <div class="lineItem">
  216. <label><em>*</em>链接标题:</label>
  217. <div class="input">
  218. <div class="flex">
  219. <el-input class="input" type="textarea" size="small" placeholder="请输入链接标题" v-model="linkExtend.title"
  220. clearable></el-input>
  221. <span class="font_zj">{{ $getStrBytes(linkExtend.title) }}/128字节</span>
  222. </div>
  223. <div class="warning_hint f12" style="margin-left:0" v-if="$getStrBytes(linkExtend.title) > 128"> <i
  224. class="el-icon-warning-outline"></i> 链接标题,最多128个字节,已超出!</div>
  225. </div>
  226. </div>
  227. <div class="lineItem">
  228. <label><em>*</em>链接地址:</label>
  229. <div class="input">
  230. <div class="flex">
  231. <el-input class="input" type="textarea" size="small" placeholder="请输入链接地址" v-model="linkExtend.jump_url"
  232. clearable></el-input>
  233. <span class="font_zj">{{ $getStrBytes(linkExtend.jump_url) }}/2048字节</span>
  234. </div>
  235. <div class="warning_hint f12" style="margin-left:0" v-if="$getStrBytes(linkExtend.jump_url) > 2048"> <i
  236. class="el-icon-warning-outline"></i> 链接地址,最多2048个字节,已超出!</div>
  237. </div>
  238. </div>
  239. <div class="lineItem">
  240. <label>图文封面:</label>
  241. <el-upload class="avatar-uploader" :action="URL.BASEURL + URL.material_upload" name="material_file"
  242. :show-file-list="false" :data="fileData" :on-success="uploadSuccess" :on-progress='beforeUploadUpload'
  243. :on-error='uploadFail' accept=".jpg,.jpeg,.png">
  244. <img v-if="linkExtend.picurl" :src="linkExtend.picurl" class="fm_img">
  245. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  246. </el-upload>
  247. </div>
  248. <p class="uploadImgHint" style="margin-left:40px;">*图片仅支持png或jpg格式,且文件大小不得超过10M。</p>
  249. <div class="lineItem">
  250. <label>封面描述:</label>
  251. <div class="input">
  252. <div class="flex">
  253. <el-input class="input" type="textarea" size="small" placeholder="请输入封面描述" v-model="linkExtend.desc"
  254. clearable></el-input>
  255. <span class="font_zj">{{ $getStrBytes(linkExtend.desc) }}/512字节</span>
  256. </div>
  257. <div class="warning_hint f12" style="margin-left:0" v-if="$getStrBytes(linkExtend.desc) > 512"> <i
  258. class="el-icon-warning-outline"></i> 封面描述,最多512个字节,已超出!</div>
  259. </div>
  260. </div>
  261. <div class="buttons">
  262. <el-button type="primary" plain size="mini" @click="linkExtendVisible = false">取消</el-button>
  263. <el-button type="primary" size="mini" @click="linkExtendDefine">确定</el-button>
  264. </div>
  265. </el-dialog>
  266. </div>
  267. </template>
  268. <script>
  269. import draggable from "vuedraggable"
  270. import phonePreview from './phonePreview.vue'
  271. import radarEntrance from './radarEntrance.vue'
  272. export default {
  273. components: { draggable, phonePreview, radarEntrance },
  274. props: {
  275. disabled: {
  276. type: Boolean,
  277. default: false
  278. },
  279. afferent_attachments: {
  280. default: []
  281. },
  282. afferent_content: {
  283. type: String,
  284. default: ''
  285. },
  286. source: {
  287. type: String,
  288. default: 'qun'
  289. },
  290. phone_width: {
  291. type: String,
  292. default: ''
  293. }
  294. },
  295. data () {
  296. return {
  297. fileData: {
  298. admin_id: this.$cookie.getCookie('admin_id'),
  299. ttl: this.$cookie.getCookie('ttl'),
  300. sign: this.$cookie.getCookie('sign'),
  301. corpid: this.$localSelfStore.getLocal('defaultCorp') && this.$localSelfStore.getLocal('defaultCorp') != 'undefined' ? JSON.parse(this.$localSelfStore.getLocal('defaultCorp')).corpid : '',
  302. type: 1,//素材类型。1图片 2语音 3视频
  303. need_media_id: 0,
  304. },
  305. fileData2: {
  306. admin_id: this.$cookie.getCookie('admin_id'),
  307. ttl: this.$cookie.getCookie('ttl'),
  308. sign: this.$cookie.getCookie('sign'),
  309. corpid: this.$localSelfStore.getLocal('defaultCorp') && this.$localSelfStore.getLocal('defaultCorp') != 'undefined' ? JSON.parse(this.$localSelfStore.getLocal('defaultCorp')).corpid : '',
  310. type: 1,//素材类型。1图片 2语音 3视频
  311. need_media_id: 1,//是否需要返回media_id.0否 1是
  312. },
  313. content: this.afferent_content,
  314. imgVisible: false,
  315. linkVisible: false,
  316. linkExtendVisible: false,
  317. miniprogramVisible: false,
  318. miniprogram: {
  319. title: '',
  320. appid: '',
  321. page: '',
  322. pic_media_id: '',
  323. pic_url: ''
  324. },
  325. image: {
  326. media_id: '',
  327. pic_url: '',
  328. },
  329. link: {
  330. title: '',
  331. picurl: '',
  332. desc: '',
  333. url: '',
  334. },
  335. linkExtend: {
  336. title: '',
  337. jump_url: '',
  338. picurl: '',
  339. desc: '',
  340. },
  341. attachments: [],
  342. edit_index: '',
  343. radarAttach: [],
  344. radarIds: [],
  345. attachments_idx: 0,
  346. has_attachLen: 0,//除雷达外,附件的长度
  347. }
  348. },
  349. created () {
  350. if (this.afferent_attachments && this.afferent_attachments != '') {
  351. this.attachments = this.afferent_attachments
  352. this.radarids_reset()
  353. }
  354. },
  355. methods: {
  356. radarids_reset () { //雷达id回显
  357. this.has_attachLen = 0
  358. this.radarIds = []
  359. this.attachments.forEach(item => {
  360. if (item.msgtype == 'radar') {
  361. this.radarIds.push(item.radar.radar_id)
  362. } else {
  363. this.has_attachLen += 1
  364. }
  365. })
  366. this.$nextTick(() => {
  367. this.$refs.radarEntranceRef.radar_checked = []
  368. })
  369. },
  370. async insertAtCursor () {//插入昵称
  371. let myValue = '「客户昵称」'
  372. const myField = this.$refs.textarea;
  373. if (myField.selectionStart || myField.selectionStart === 0) {
  374. var startPos = myField.selectionStart
  375. var endPos = myField.selectionEnd
  376. this.content = myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length)
  377. await this.$nextTick() // 这句是重点, 圈起来
  378. myField.focus()
  379. myField.setSelectionRange(endPos + myValue.length, endPos + myValue.length)
  380. } else {
  381. this.content += myValue
  382. }
  383. // 子组件更新后 => 触发父组件更新content内容
  384. this.$emit('editContent', this.content)
  385. },
  386. radarDefine (val) { //雷达确定
  387. let now_rew = this.attachments
  388. for (let i = 0; i < now_rew.length; i++) {
  389. if (now_rew[i].msgtype == "radar") {
  390. now_rew.splice(i, 1)
  391. i -= 1 //每删除一个项就让a减少一个 保持a和长度同步
  392. }
  393. }
  394. this.attachments = [...this.attachments, ...val]
  395. this.$emit('changeAttachment', this.attachments)
  396. },
  397. editAttachment (item, index) {
  398. this.edit_index = index
  399. if (item.msgtype == 'image') {
  400. this.image = item.image;
  401. this.imgVisible = true
  402. }
  403. if (item.msgtype == 'link') {
  404. this.link = item.link
  405. this.linkVisible = true
  406. }
  407. if (item.msgtype == 'miniprogram') {
  408. this.miniprogram = item.miniprogram
  409. this.miniprogramVisible = true
  410. }
  411. if (item.msgtype == 'radar') {
  412. this.$nextTick(() => {
  413. this.radarids_reset()
  414. this.$refs.radarEntranceRef.dialogVisible = true
  415. })
  416. }
  417. if (item.msgtype == 'promote') {
  418. this.linkExtend = item.promote;
  419. this.linkExtendVisible = true;
  420. }
  421. },
  422. deleteAttachment (index) {
  423. this.attachments.splice(index, 1)
  424. this.attachments_idx++
  425. this.$emit('changeAttachment', this.attachments)
  426. },
  427. imageDefine () {//图片确定
  428. if (this.image.pic_url == '') {
  429. this.$message({
  430. message: '请选择图片',
  431. type: "warning"
  432. })
  433. return
  434. }
  435. let obj = {
  436. "msgtype": "image",
  437. "image": this.image
  438. }
  439. if (this.edit_index != -1) {
  440. this.$set(this.attachments, this.edit_index, obj)
  441. this.edit_index = -1
  442. } else {
  443. this.attachments.push(obj)
  444. }
  445. this.$emit('changeAttachment', this.attachments)
  446. this.imgVisible = false;
  447. },
  448. linkExtendDefine () {//推广链接
  449. if (this.linkExtend.title == '' || this.$getStrBytes(this.linkExtend.title) > 128) {
  450. this.$message({
  451. message: '请正确输入链接标题',
  452. type: "warning"
  453. })
  454. return
  455. }
  456. if (!(/^http[s]?:\/\/([\w-]+\.)+([\w-]+)/i.test(this.linkExtend.jump_url))) {
  457. this.$message({
  458. message: '请正确输入链接地址',
  459. type: "warning"
  460. })
  461. return
  462. }
  463. if (this.linkExtend && this.linkExtend.jump_url != '' && this.$getStrBytes(this.linkExtend.jump_url) > 2048) {
  464. this.$message({
  465. message: '请正确输入链接地址',
  466. type: "warning"
  467. })
  468. return
  469. }
  470. if (this.linkExtend && this.linkExtend.desc != '' && this.$getStrBytes(this.linkExtend.desc) > 512) {
  471. this.$message({
  472. message: '请正确输入封面描述',
  473. type: "warning"
  474. })
  475. return
  476. }
  477. let obj = {
  478. "msgtype": "promote",
  479. "promote": this.linkExtend
  480. }
  481. if (this.edit_index != -1) {
  482. this.$set(this.attachments, this.edit_index, obj)
  483. this.edit_index = -1
  484. } else {
  485. this.attachments.push(obj)
  486. }
  487. this.$emit('changeAttachment', this.attachments)
  488. this.linkExtendVisible = false;
  489. },
  490. linkDefine () {//链接确定
  491. if (this.link.title == '' || this.$getStrBytes(this.link.title) > 128) {
  492. this.$message({
  493. message: '请正确输入链接标题',
  494. type: "warning"
  495. })
  496. return
  497. }
  498. if (!(/^http[s]?:\/\/([\w-]+\.)+([\w-]+)/i.test(this.link.url))) {
  499. this.$message({
  500. message: '请正确输入链接地址',
  501. type: "warning"
  502. })
  503. return
  504. }
  505. if (this.link && this.link.url != '' && this.$getStrBytes(this.link.url) > 2048) {
  506. this.$message({
  507. message: '请正确输入链接地址',
  508. type: "warning"
  509. })
  510. return
  511. }
  512. if (this.link && this.link.desc != '' && this.$getStrBytes(this.link.desc) > 512) {
  513. this.$message({
  514. message: '请正确输入封面描述',
  515. type: "warning"
  516. })
  517. return
  518. }
  519. let obj = {
  520. "msgtype": "link",
  521. "link": this.link
  522. }
  523. if (this.edit_index != -1) {
  524. this.$set(this.attachments, this.edit_index, obj)
  525. this.edit_index = -1
  526. } else {
  527. this.attachments.push(obj)
  528. }
  529. this.$emit('changeAttachment', this.attachments)
  530. this.linkVisible = false;
  531. },
  532. miniprogramDefine () {//小程序确定
  533. if (this.miniprogram.title == '' || this.$getStrBytes(this.miniprogram.title) > 64) {
  534. this.$message({
  535. message: '请正确输入小程序标题',
  536. type: "warning"
  537. })
  538. return
  539. }
  540. if (!(/^wx(?=.*\d)(?=.*[a-z])[\da-z]{16}$/.test(this.miniprogram.appid))) {
  541. this.$message({
  542. message: '请正确输入小程序appID',
  543. type: "warning"
  544. })
  545. return
  546. }
  547. if (this.miniprogram.page == '') {
  548. this.$message({
  549. message: '请输入小程序路径',
  550. type: "warning"
  551. })
  552. return
  553. }
  554. if (this.miniprogram.pic_url == '') {
  555. this.$message({
  556. message: '请选择小程序封面',
  557. type: "warning"
  558. })
  559. return
  560. }
  561. let obj = {
  562. "msgtype": "miniprogram",
  563. "miniprogram": this.miniprogram
  564. }
  565. if (this.edit_index != -1) {
  566. this.$set(this.attachments, this.edit_index, obj)
  567. this.edit_index = -1
  568. } else {
  569. this.attachments.push(obj)
  570. }
  571. this.$emit('changeAttachment', this.attachments)
  572. this.miniprogramVisible = false
  573. },
  574. contentChange (val) {
  575. // if (val.inputType == 'insertText') {
  576. // this.content += val.data;
  577. // }
  578. // if (val.inputType == 'deleteContentBackward') {
  579. // this.content = this.content.slice(0, this.content.length - 1)
  580. // }
  581. this.$emit('editContent', this.content)
  582. },
  583. fileEvent (type) {
  584. this.edit_index = -1;
  585. if (this.attachments && this.attachments.length >= 9) {
  586. this.$message({
  587. message: '最多支持添加9个附件',
  588. type: "warning"
  589. })
  590. return
  591. }
  592. if (type == 'img') {
  593. this.image = {
  594. media_id: '',
  595. pic_url: '',
  596. }
  597. this.imgVisible = true
  598. }
  599. if (type == 'link') {
  600. this.link = {
  601. title: '',
  602. picurl: '',
  603. desc: '',
  604. url: '',
  605. }
  606. this.linkVisible = true
  607. }
  608. if (type == 'miniprogram') {
  609. this.miniprogram = {
  610. title: '',
  611. appid: '',
  612. page: '',
  613. pic_media_id: '',
  614. pic_url: ''
  615. }
  616. this.miniprogramVisible = true
  617. }
  618. if (type == 'radar') {
  619. this.$nextTick(() => {
  620. this.radarids_reset()
  621. this.$refs.radarEntranceRef.dialogVisible = true
  622. })
  623. }
  624. if (type == 'linkExtend') {
  625. this.linkExtend = {
  626. title: '',
  627. jump_url: '',
  628. picurl: '',
  629. desc: '',
  630. }
  631. this.linkExtendVisible = true
  632. }
  633. },
  634. uploadSuccess (res, file) {
  635. this.$loading(this.$loadingConfig).close();
  636. if (res.errno == 0) {
  637. if (this.imgVisible) {//图片
  638. this.image.pic_url = res.rst.url;
  639. this.image.media_id = res.rst.material_id;
  640. }
  641. if (this.linkVisible) {//链接
  642. this.link.picurl = res.rst.url;
  643. }
  644. if (this.miniprogramVisible) {//小程序
  645. this.miniprogram.pic_media_id = res.rst.material_id;
  646. this.miniprogram.pic_url = res.rst.url;
  647. }
  648. if (this.linkExtendVisible) {//推广链接
  649. this.linkExtend.picurl = res.rst.url;
  650. }
  651. } else {
  652. this.$message({
  653. message: res.err,
  654. type: 'warning'
  655. })
  656. }
  657. },
  658. beforeUploadUpload (file) {
  659. this.$loading(this.$loadingConfig);
  660. },
  661. uploadFail () {
  662. this.$loading(this.$loadingConfig).close();
  663. this.$message({
  664. message: '上传失败',
  665. type: 'fail'
  666. })
  667. }
  668. }
  669. }
  670. </script>
  671. <style lang="scss" scoped>
  672. #textarea:empty:before {
  673. content: attr(placeholder);
  674. color: #c0c4cc;
  675. }
  676. #textarea:focus:before {
  677. content: none;
  678. }
  679. .insert {
  680. padding: 10px;
  681. border-bottom: 1px solid #e9e9e9;
  682. span {
  683. color: #fbae16;
  684. font-size: 14px;
  685. font-weight: bold;
  686. cursor: pointer;
  687. }
  688. }
  689. .container {
  690. position: relative;
  691. .phonePreviewBox {
  692. position: absolute;
  693. right: -360px;
  694. top: -200px;
  695. }
  696. }
  697. .editCon {
  698. width: 710px;
  699. background: #fafafa;
  700. border: 1px solid #e9e9e9;
  701. position: relative;
  702. padding-bottom: 40px;
  703. .textarea {
  704. height: 200px;
  705. background: transparent;
  706. border: none;
  707. width: 100%;
  708. padding: 10px;
  709. resize: none;
  710. color: #333333;
  711. font-size: 14px;
  712. line-height: 20px;
  713. }
  714. .maxFont {
  715. text-align: right;
  716. color: #787878;
  717. font-size: 13px;
  718. line-height: 18px;
  719. padding: 6px 10px;
  720. }
  721. .addFileBox {
  722. width: 100%;
  723. padding: 10px;
  724. color: #00b38a;
  725. font-size: 13px;
  726. line-height: 18px;
  727. border-top: 1px solid #e9e9e9;
  728. position: absolute;
  729. bottom: 0;
  730. left: 0;
  731. }
  732. }
  733. .propoverItem {
  734. display: flex;
  735. align-items: center;
  736. color: #333333;
  737. font-size: 14px;
  738. line-height: 20px;
  739. margin: 8px 0;
  740. cursor: pointer;
  741. &:last-of-type {
  742. margin-bottom: 0;
  743. }
  744. &:hover {
  745. color: #00b38a;
  746. }
  747. img {
  748. width: 15px;
  749. margin: 0 8px;
  750. }
  751. }
  752. .lineItem {
  753. display: flex;
  754. font-size: 14px;
  755. margin-bottom: 15px;
  756. label {
  757. width: 110px;
  758. line-height: 30px;
  759. color: #666666;
  760. text-align: right;
  761. em {
  762. color: #ff0000;
  763. }
  764. }
  765. .input {
  766. flex: 1;
  767. }
  768. .avatar-uploader .el-upload .avatar-uploader-icon {
  769. font-size: 28px;
  770. color: #8c939d;
  771. width: 110px;
  772. height: 110px;
  773. line-height: 110px;
  774. text-align: center;
  775. border: 1px dashed #d9d9d9;
  776. border-radius: 4px;
  777. &:hover {
  778. border-color: #00b38a;
  779. }
  780. }
  781. }
  782. .buttons {
  783. text-align: right;
  784. padding: 20px 0 10px;
  785. }
  786. .otherHint {
  787. font-size: 13px;
  788. line-height: 20px;
  789. margin-top: 6px;
  790. a {
  791. color: #00b38a;
  792. cursor: pointer;
  793. }
  794. text-align: right;
  795. }
  796. .fujian {
  797. border-top: 1px solid #e9e9e9;
  798. .fujianItem {
  799. display: flex;
  800. align-items: center;
  801. justify-content: space-between;
  802. padding: 6px 10px;
  803. color: #757171;
  804. font-size: 13px;
  805. cursor: grabbing;
  806. i {
  807. font-size: 16px;
  808. cursor: pointer;
  809. }
  810. .left {
  811. display: flex;
  812. align-items: center;
  813. }
  814. .right {
  815. i {
  816. margin-left: 10px;
  817. }
  818. }
  819. }
  820. }
  821. .fm_img {
  822. width: 100px;
  823. height: 100px;
  824. background: #f4f4f4;
  825. }
  826. .uploadImgHint {
  827. font-size: 13px;
  828. line-height: 30px;
  829. color: #f9a527;
  830. margin-left: 60px;
  831. margin-top: -10px;
  832. margin-bottom: 10px;
  833. }
  834. .warning_hint {
  835. color: red;
  836. font-size: 13px;
  837. margin-left: 10px;
  838. line-height: 20px;
  839. }
  840. .font_zj {
  841. font-size: 12px;
  842. width: 96px;
  843. line-height: 20px;
  844. padding-left: 6px;
  845. }
  846. </style>