index.vue 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649
  1. <template>
  2. <div>
  3. <div class="app-container">
  4. <el-alert
  5. title="注意事项"
  6. type="warning"
  7. description="1、因企业微信接口限制,提醒成员完成群发任务,24小时内每个群发最多触发三次提醒,多点无效噢。2、客户每个月最多接收来自同一企业的管理员的30条群发消息,每位客户每日可收到1次群发内容"
  8. :closable="false"
  9. show-icon>
  10. </el-alert>
  11. </div>
  12. <div class="app-container">
  13. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  14. <el-form-item label="企微公司" prop="corpId">
  15. <el-select v-model="queryParams.corpId" placeholder="企微公司" size="small" @change="updateCorpId()">
  16. <el-option
  17. v-for="dict in myQwCompanyList"
  18. :key="dict.dictValue"
  19. :label="dict.dictLabel"
  20. :value="dict.dictValue"
  21. />
  22. </el-select>
  23. </el-form-item>
  24. <el-form-item label="消息文本" prop="textContent">
  25. <el-input
  26. v-model="queryParams.textContent"
  27. placeholder="请输入想查询的消息文本内容"
  28. clearable
  29. size="small"
  30. @keyup.enter.native="handleQuery"
  31. />
  32. </el-form-item>
  33. <el-form-item>
  34. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  35. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置/刷新页面</el-button>
  36. <el-button type="primary" size="mini" @click="handleAdd()">新建群发</el-button>
  37. </el-form-item>
  38. </el-form>
  39. <el-row :gutter="10" class="mb8">
  40. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  41. </el-row>
  42. <el-table v-loading="loading" :data="groupMsgList" @selection-change="handleSelectionChange" border>
  43. <el-table-column label="消息文本内容" align="left" prop="textContent" width="350px">
  44. <template slot-scope="scope">
  45. <el-tooltip class="item" effect="dark" :content="scope.row.textContent" placement="top">
  46. <div style="display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; text-overflow: ellipsis;">
  47. <span>{{ scope.row.textContent }}</span>
  48. </div>
  49. </el-tooltip>
  50. </template>
  51. </el-table-column>
  52. <el-table-column label="群发任务的类型" align="center" prop="chatType">
  53. <template slot-scope="scope">
  54. <span v-for="it in groupMsgChatType" v-if="it.dictValue==scope.row.chatType">{{it.dictLabel}}</span>
  55. </template>
  56. </el-table-column>
  57. <el-table-column label="发送类型" align="center" prop="isTimerSend">
  58. <template slot-scope="scope">
  59. <span v-for="it in groupMsgTimerType" v-if="it.dictValue==scope.row.isTimerSend">{{it.dictLabel}}</span>
  60. </template>
  61. </el-table-column>
  62. <el-table-column label="消息类型" align="center" prop="msgType" >
  63. <template slot-scope="scope">
  64. <span v-for="(item, index) in msgTypeOptions" v-if="scope.row.msgType==item.dictValue">{{item.dictLabel}}</span>
  65. </template>
  66. </el-table-column>
  67. <el-table-column label="发送时间" align="center">
  68. <template slot-scope="scope">
  69. <span v-if="scope.row.isTimerSend==2">{{scope.row.createTime}}</span>
  70. <span v-else>{{ scope.row.timerSend }}</span>
  71. </template>
  72. </el-table-column>
  73. <el-table-column label="发送状态" align="center" width="110px">
  74. <template slot-scope="scope">
  75. <el-tag
  76. v-if="scope.row.isSend==1"
  77. type="success"
  78. size="mini"
  79. plain>
  80. 发送成功
  81. </el-tag >
  82. <el-tag
  83. v-else-if="scope.row.isSend==0"
  84. type="danger"
  85. size="mini"
  86. plain>
  87. 发送失败
  88. </el-tag >
  89. <el-tag
  90. v-else-if="scope.row.isSend==2"
  91. type="primary"
  92. size="mini"
  93. plain>
  94. 发送成功待录入详细信息
  95. </el-tag >
  96. <el-tag
  97. v-else-if="scope.row.isSend==3"
  98. type="warning"
  99. size="mini"
  100. plain>
  101. 待发送
  102. </el-tag >
  103. </template>
  104. </el-table-column>
  105. <el-table-column label="已发送成员数" align="center" prop="fromUserCount" />
  106. <el-table-column label="送达客户数" align="center" prop="toUserCount" />
  107. <el-table-column label="未发送成员数" align="center" prop="fromUserNum" />
  108. <el-table-column label="未送达客户数" align="center" prop="toUserNum" />
  109. <el-table-column label="创建人" align="center" prop="createName" width="120px" />
  110. <el-table-column label="创建时间" align="center" prop="createTime" width="160px"/>
  111. <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
  112. <template slot-scope="scope">
  113. <el-button
  114. size="mini"
  115. type="text"
  116. icon="el-icon-message-solid"
  117. @click="triggerRemindGroupMsg(scope.row)"
  118. >提醒成员群发</el-button>
  119. <el-button
  120. size="mini"
  121. type="text"
  122. icon="el-icon-notebook-2"
  123. @click="hangdleDitels(scope.row)"
  124. v-hasPermi="['qw:groupMsg:query']"
  125. >详情</el-button>
  126. <el-button
  127. size="mini"
  128. type="text"
  129. icon="el-icon-delete"
  130. @click="handleDelete(scope.row)"
  131. v-hasPermi="['qw:groupMsg:remove']"
  132. >删除</el-button>
  133. </template>
  134. </el-table-column>
  135. </el-table>
  136. <pagination
  137. v-show="total>0"
  138. :total="total"
  139. :page.sync="queryParams.pageNum"
  140. :limit.sync="queryParams.pageSize"
  141. @pagination="getList"
  142. />
  143. <!-- 添加客户群发记录主对话框 -->
  144. <el-dialog v-loading="loading" :title="title" :visible.sync="open" width="1500px" @close="closeData" style="font-weight: bold;font-size: 20px" append-to-body>
  145. <div style="display: flex;flex-wrap: wrap">
  146. <div style="width: 1000px;">
  147. <el-form ref="form" :model="form" :rules="rules" label-width="160px" size="medium" style="font-size: 20px" >
  148. <div>
  149. <span style="font-size: 20px">基础信息</span>
  150. <el-divider></el-divider>
  151. </div>
  152. <el-form-item label="选择群发成员账号:" prop="userIdsSelectList" style="font-size: 30px">
  153. <div>
  154. <div>
  155. <el-button
  156. size="medium"
  157. icon="el-icon-circle-plus-outline"
  158. plain
  159. @click="handlelistUser">请选择群发账号</el-button>
  160. </div>
  161. <div>
  162. <el-tag
  163. style="margin-left: 5px"
  164. size="medium"
  165. :key="list.id"
  166. v-for="list in userSelectList"
  167. closable
  168. :disable-transitions="false"
  169. @close="handleClosegroupUser(list)">
  170. {{list.qwUserName}}({{list.nickName}})
  171. </el-tag>
  172. <!-- <span v-for="item in userSelectList" class="user-box">{{item.nickName}}</span>-->
  173. </div>
  174. </div>
  175. <el-alert
  176. title="系统会推送任务给最后跟客户进行聊天互动的企业成员"
  177. type="warning"
  178. style="font-size: 15px;margin-top: 2%"
  179. :closable="false"
  180. show-icon>
  181. </el-alert>
  182. </el-form-item>
  183. <el-form-item label="选择客户:">
  184. <el-radio-group v-model="form.selectType" @input="clearExpectCountCustomer" size="medium ">
  185. <el-radio :label="item.dictValue" v-for="item in groupMsgTypeOptions" >{{item.dictLabel}}</el-radio>
  186. </el-radio-group>
  187. <div style="background-color:#ecf8fe;width: 100%;margin-top: 1%" v-if="form.selectType==1">
  188. <span style="padding: 3%;font-size: 15px" >查看该消息预计送达人数:</span>
  189. <el-link style="color: #1aa4ff;" v-if="this.expectCountCustomer==null" @click="viewReceiveNum">点我查看
  190. </el-link>
  191. <span style="color: #d440ec;margin-left: 2%" v-if="this.expectCountCustomer!=null">{{this.expectCountCustomer}} 人</span>
  192. </div>
  193. <div v-if="form.selectType==2" style="padding-top: 1%;background-color: #fbfbfb">
  194. <el-form-item label="按性别筛选客户:" class="elFormItemClass">
  195. <el-radio-group v-model="form.gender" @input="clearExpectCountCustomer">
  196. <el-radio v-for="item in sysUserSex" :label="item.dictValue">{{item.dictLabel}}</el-radio>
  197. </el-radio-group>
  198. </el-form-item>
  199. <el-form-item label="按所在群聊筛选:" class="elFormItemClass">
  200. <div>
  201. <div>
  202. <el-button
  203. icon="el-icon-s-comment"
  204. plain
  205. @click="handleGroupChatList">请选择群聊</el-button>
  206. </div>
  207. <div>
  208. <div>
  209. <el-tag
  210. style="margin-left: 5px"
  211. size="medium"
  212. :key="list.chatId"
  213. v-for="list in groupChatList"
  214. closable
  215. :disable-transitions="false"
  216. @close="handleClosegroupChat(list)">
  217. {{list.name}}
  218. </el-tag>
  219. </div>
  220. <!-- <span v-for="item in groupChatList" class="user-box">{{item.name}}</span>-->
  221. </div>
  222. </div>
  223. </el-form-item>
  224. <el-form-item label="按添加时间筛选" class="elFormItemClass">
  225. <div style="width: 100%;display: flex">
  226. <el-date-picker
  227. v-model="form.timeScreenCharge"
  228. @change="clearExpectCountCustomer"
  229. type="daterange"
  230. align="right"
  231. unlink-panels
  232. range-separator="至"
  233. start-placeholder="开始日期"
  234. end-placeholder="结束日期"
  235. :picker-options="pickerOptions"
  236. :default-time="['00:00:00', '23:59:59']">
  237. </el-date-picker>
  238. </div>
  239. </el-form-item>
  240. <el-form-item label="按客户标签筛选:" class="elFormItemClass">
  241. <div>
  242. <div>
  243. <el-button icon="el-icon-s-check" plain @click="hangleChangeTags">请选择标签</el-button>
  244. </div>
  245. <el-tag type="success"
  246. closable
  247. :disable-transitions="false"
  248. v-for="list in tagsIdsChangeSelectList"
  249. :key="list.tagId"
  250. @close="handleCloseTags(list)"
  251. style="margin: 3px;"
  252. >{{list.name}}
  253. </el-tag>
  254. <!-- <div>-->
  255. <!-- <el-tag-->
  256. <!-- style="margin-left: 5px"-->
  257. <!-- size="medium"-->
  258. <!-- :key="tag[0]"-->
  259. <!-- v-for="(tag,index) in tagsIdsChangeSelectList"-->
  260. <!-- closable-->
  261. <!-- :disable-transitions="false"-->
  262. <!-- @close="handleCloseTags(tag)">-->
  263. <!-- {{tag[1]}}-->
  264. <!-- </el-tag>-->
  265. <!-- </div>-->
  266. </div>
  267. </el-form-item>
  268. <el-form-item label="排除标签筛选" class="elFormItemClass">
  269. <div>
  270. <div>
  271. <el-button icon="el-icon-s-check" plain @click="hangleChangeOutTags">请选择排除的标签</el-button>
  272. </div>
  273. <div>
  274. <el-tag type="success"
  275. closable
  276. :disable-transitions="false"
  277. v-for="list in outTagsIdsChangeSelectList"
  278. :key="list.tagId"
  279. @close="handleCloseOutTags(list)"
  280. style="margin: 3px;"
  281. >{{list.name}}
  282. </el-tag>
  283. <!-- <el-tag-->
  284. <!-- style="margin-left: 5px"-->
  285. <!-- size="medium"-->
  286. <!-- :key="tag[0]"-->
  287. <!-- v-for="(tag,index) in outTagsIdsChangeSelectList"-->
  288. <!-- closable-->
  289. <!-- :disable-transitions="false"-->
  290. <!-- @close="handleCloseOutTags(tag)">-->
  291. <!-- {{tag[1]}}-->
  292. <!-- </el-tag>-->
  293. </div>
  294. </div>
  295. </el-form-item>
  296. <div style="background-color:#ecf8fe;width: 100%;height: 10%;margin-top: 3%">
  297. <span style="margin-left: 2%;font-size: 15px" v-if="this.expectCountGroupChat==null">查看该消息预计送达人数:</span>
  298. <el-link style="color: #1aa4ff;margin-left: 3%" v-if="this.expectCountGroupChat==null" @click="viewReceiveGroupChatNum">点我查看
  299. </el-link>
  300. <span style="color: #d440ec;margin-left: 2%" v-if="this.expectCountGroupChat!=null">{{this.expectCountGroupChat}} 人</span>
  301. </div>
  302. </div>
  303. </el-form-item>
  304. <div v-if="form.chatType=='group'">
  305. <el-form-item label="客户群名:" prop="groupChatNames">
  306. <el-input v-model="form.groupChatNamesList" placeholder="请输入客户群名" />
  307. </el-form-item>
  308. </div>
  309. <div>
  310. <span>编辑群发信息</span>
  311. <el-divider></el-divider>
  312. </div>
  313. </el-form>
  314. </div>
  315. </div>
  316. <WelComeAdd ref="WelComeAdd"></WelComeAdd>
  317. <div slot="footer" class="dialog-footer" style="display: flex;justify-content: center">
  318. <el-button type="primary" @click="submitForm">确定</el-button>
  319. <el-button @click="cancel">取 消</el-button>
  320. </div>
  321. </el-dialog>
  322. <!-- 选择群发账号弹窗 -->
  323. <el-dialog :title="listUser.title" :visible.sync="listUser.open" width="1000" append-to-body>
  324. <qwUserList ref="qwUserList" @selectUserList="selectUserList"></qwUserList>
  325. </el-dialog>
  326. <!-- 选择群聊 -->
  327. <el-dialog :title="groupChart.title" :visible.sync="groupChart.open" width="1300" append-to-body>
  328. <group-chat ref="GroupChat" @selectGroupChatList="selectGroupChatList"></group-chat>
  329. </el-dialog>
  330. <!-- 选择的标签 -->
  331. <el-dialog :title="changeTagDialog.title" :visible.sync="changeTagDialog.open" width="700" append-to-body>
  332. <div>搜索标签:
  333. <el-input v-model="tagChange.tagName" placeholder="请输入标签名称" clearable size="small" style="width: 200px;margin-right: 10px" />
  334. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(tagChange.tagName)">搜索</el-button>
  335. <el-button type="primary" icon="el-icon-plus" size="mini" @click="cancelSearchTags">重置</el-button>
  336. </div>
  337. <div v-for="item in tagGroupList" :key="item.id" >
  338. <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
  339. <span class="name-background">{{ item.name }}</span>
  340. </div>
  341. <!-- 添加外层滚动容器 -->
  342. <div class="scroll-wrapper">
  343. <div class="tag-container">
  344. <a
  345. v-for="tagItem in item.tag"
  346. class="tag-box"
  347. @click="tagSelection(tagItem)"
  348. :class="{ 'tag-selected': tagItem.isSelected }"
  349. >
  350. {{ tagItem.name }}
  351. </a>
  352. </div>
  353. </div>
  354. </div>
  355. <pagination
  356. v-show="tagTotal>0"
  357. :total="tagTotal"
  358. :page.sync="queryTagParams.pageNum"
  359. :limit.sync="queryTagParams.pageSize"
  360. @pagination="getPageListTagGroup"
  361. />
  362. <div slot="footer" class="dialog-footer">
  363. <el-button type="primary" @click="tagSubmitForm(changeTagDialog.type)">确 定</el-button>
  364. <el-button @click="tagCancel(changeTagDialog.type)">取消</el-button>
  365. </div>
  366. </el-dialog>
  367. <!-- 详情 -->
  368. <el-drawer :title="detailsDialog.title" :visible.sync="detailsDialog.open" size="75%" style="font-weight: bolder">
  369. <div style="background-color: rgb(240 242 245)">
  370. <div style="display: flex;flex-wrap: nowrap;background-color: rgb(240 242 245);height: 850px;margin: 15px;padding-top: 15px" >
  371. <el-card class="box-card" style="width: 700px" >
  372. <el-descriptions :column="1" border :labelStyle="{width: '150px'}">
  373. <el-descriptions-item label="群发选择类型:">
  374. <template v-for="item in groupMsgTypeOptions" v-if="item.dictValue == formDetails.selectType">
  375. <span>{{item.dictLabel}}</span>
  376. </template>
  377. </el-descriptions-item>
  378. <el-descriptions-item label="消息文本内容:" >
  379. <span class="custom-span">{{formDetails.textContent}}</span>
  380. </el-descriptions-item>
  381. <el-descriptions-item label="图片" v-if="formDetails.msgType=='1'">
  382. <el-image
  383. v-if="formDetails.mediaPicUrl"
  384. style="width: 100px; height: 100px"
  385. :src="formDetails.mediaPicUrl"
  386. fit="contain"
  387. @click="openImageViewer(formDetails.mediaPicUrl)"/>
  388. </el-descriptions-item>
  389. <el-descriptions-item label="图文标题:" v-if="formDetails.msgType=='2'">
  390. <span class="custom-span-title">{{formDetails.title}}</span>
  391. </el-descriptions-item>
  392. <el-descriptions-item label="图文封面:" v-if="formDetails.msgType=='2'">
  393. <el-image
  394. v-if="formDetails.picurl"
  395. style="width: 100px; height: 100px"
  396. :src="formDetails.picurl"
  397. fit="contain"
  398. @click="openImageViewer(formDetails.picurl)"/>
  399. </el-descriptions-item>
  400. <el-descriptions-item label="图文的描述:" v-if="formDetails.msgType=='2'">
  401. <span class="custom-span-description">{{formDetails.description}}</span>
  402. </el-descriptions-item>
  403. <el-descriptions-item label="图文的链接:" v-if="formDetails.msgType=='2'">
  404. <el-link :href="formDetails.url" target="_blank">{{ formDetails.url }}</el-link>
  405. <!-- <el-image-->
  406. <!-- v-if="formDetails.url"-->
  407. <!-- style="width: 100px; height: 100px"-->
  408. <!-- :src="formDetails.url"-->
  409. <!-- fit="contain"-->
  410. <!-- @click="openImageViewer(formDetails.url)"/>-->
  411. </el-descriptions-item>
  412. <el-descriptions-item label="小程序标题:" v-if="formDetails.msgType=='3'">{{formDetails.miniprogramTitle}}</el-descriptions-item>
  413. <el-descriptions-item label="小程序封面:" v-if="formDetails.msgType=='3'">
  414. <el-image
  415. v-if="formDetails.miniprogramPicUrl"
  416. style="width: 100px; height: 100px"
  417. :src="formDetails.miniprogramPicUrl"
  418. fit="contain"
  419. @click="openImageViewer(formDetails.miniprogramPicUrl)"/>
  420. </el-descriptions-item>
  421. <!-- <el-descriptions-item label="小程序appid:" v-if="formDetails.msgType=='3'">{{formDetails.miniprogramAppid}}</el-descriptions-item>-->
  422. <!-- <el-descriptions-item label="小程序page路径:" v-if="formDetails.msgType=='3'">{{formDetails.miniprogramPage}}</el-descriptions-item>-->
  423. <el-descriptions-item label="企微临时文件mediaId:" v-if="formDetails.msgType=='4'">{{formDetails.fileMediaId}}</el-descriptions-item>
  424. <el-descriptions-item label="文件:" v-if="formDetails.msgType=='4'">
  425. <el-link v-if="formDetails.fileUrl" type="primary" :href="formDetails.fileUrl" download>
  426. {{formDetails.fileUrl}}
  427. </el-link>
  428. </el-descriptions-item>
  429. <el-descriptions-item label="视频临时文件mediaId:" v-if="formDetails.msgType=='5'">{{formDetails.videoMediaId}}</el-descriptions-item>
  430. <el-descriptions-item label="视频:" v-if="formDetails.msgType=='5'">
  431. <video v-if="formDetails.videoUrl"
  432. :src="formDetails.videoUrl"
  433. controls style="width: 200px;height: 100px">
  434. </video>
  435. </el-descriptions-item>
  436. <el-descriptions-item label="是否允许成员分配:" >
  437. <span v-for="dict in allowSelectOptions" v-if="dict.dictValue==formDetails.allowSelect">{{dict.dictLabel}}</span>
  438. </el-descriptions-item>
  439. <el-descriptions-item label="创建人:">{{formDetails.createName}}</el-descriptions-item>
  440. <el-descriptions-item label="创建时间:">{{formDetails.createTime}}</el-descriptions-item>
  441. </el-descriptions>
  442. </el-card>
  443. <div style="width: 700px;background-color:rgb(255 255 255); display: flex;justify-content: center;align-items: center">
  444. <div class="container">
  445. <div class="phone">
  446. <div class="chat-interface">
  447. <div class="header">
  448. <span class="back">
  449. <img src="../../../assets/image/return.png" class="back">
  450. </span>
  451. <span class="title">客服账号</span>
  452. <span class="menu">
  453. <img src="../../../assets/image/more.png" class="menu">
  454. </span>
  455. </div>
  456. <div class="message-area">
  457. <div v-if="formDetails.textContent" class="message-stayle">
  458. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  459. <div style="background-color:rgb(255 255 255); padding: 10px;">
  460. <span>{{ formDetails.textContent }}</span>
  461. </div>
  462. </div>
  463. <div v-if="formDetails.mediaPicUrl" class="message-stayle">
  464. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  465. <el-image
  466. style="width: 100px; height: 100px"
  467. :src="formDetails.mediaPicUrl"
  468. fit="contain"
  469. @click="openImageViewer(formDetails.mediaPicUrl)"/>
  470. </div>
  471. <div v-if="formDetails.title" class="message-stayle" @click="openImageViewer(formDetails.url)">
  472. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  473. <div style="background-color: white;padding: 10px;width: 100%">
  474. <span>{{formDetails.title}}</span>
  475. <div style="display: flex;justify-content:space-between;width: 100%">
  476. <span style="font-size: 13px;flex: 1">{{formDetails.description}}</span>
  477. <el-image
  478. style="width: 50px; height: 50px;flex-shrink: 0"
  479. :src="formDetails.picurl"
  480. fit="contain"
  481. @click="openImageViewer(formDetails.picurl)"/>
  482. </div>
  483. </div>
  484. </div>
  485. <div v-if="formDetails.fileUrl" class="message-stayle" >
  486. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  487. <el-link type="primary" :href="formDetails.fileUrl" download style="padding: 10px" >
  488. {{formDetails.fileUrl}}
  489. </el-link>
  490. </div>
  491. <div v-if="formDetails.videoUrl" class="message-stayle">
  492. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  493. <video
  494. :src="formDetails.videoUrl"
  495. controls style="width: 200px;height: 100px">
  496. </video>
  497. </div>
  498. </div>
  499. <div class="footer">
  500. <span class="voice-button">
  501. <img src="../../../assets/image/voice.png" class="voice-button">
  502. </span>
  503. <input type="text" class="input-box" placeholder="">
  504. <span class="emoji-button">
  505. <img src="../../../assets/image/smilingface.png" class="emoji-button">
  506. </span>
  507. <span class="add-button">
  508. <img src="../../../assets/image/plus.png" class="add-button">
  509. </span>
  510. </div>
  511. </div>
  512. </div>
  513. </div>
  514. </div>
  515. </div>
  516. <div style="width: 100%">
  517. <customer-group-details ref="customerGroupDetails" :rowDetailFrom="formDetails"></customer-group-details>
  518. </div>
  519. </div>
  520. </el-drawer>
  521. <!-- 大图预览对话框 -->
  522. <el-dialog
  523. :visible.sync="dialogVisible"
  524. :modal="false"
  525. width="1200px"
  526. append-to-body>
  527. <img
  528. :src="this.dialogImageUrl"
  529. style="display: block; max-width: 100%; margin: 0 auto"
  530. />
  531. </el-dialog>
  532. </div>
  533. </div>
  534. </template>
  535. <script>
  536. import {
  537. listGroupMsg,
  538. getGroupMsg,
  539. delGroupMsg,
  540. addGroupMsg, remindGroupMsg
  541. } from '@/api/qw/groupMsg'
  542. import GroupMsgUser from '@/views/qw/groupMsgUser/groupMsg'
  543. import ImageUpload from "@/views/qw/material/ImageUpload";
  544. import qwUserList from "@/views/qw/user/qwUserList"
  545. import { selectCountCustomer } from '@/api/qw/externalContact'
  546. import GroupChat from '@/views/qw/groupChat/groupChat'
  547. import WelComeAdd from '@/views/qw/welcome/welComeAdd'
  548. import CustomerGroupDetails from '@/views/qw/groupMsg/customerGroupDetails'
  549. import source from 'echarts/src/data/Source'
  550. import { getMyQwUserList,getMyQwCompanyList } from "@/api/qw/user";
  551. import {allListTagGroup} from "@/api/qw/tagGroup";
  552. import {listTag, searchTags} from "@/api/qw/tag";
  553. import MaterialQw from "@/views/qw/materialQw/index.vue";
  554. export default {
  555. name: "GroupMsg",
  556. components: { CustomerGroupDetails, GroupChat, GroupMsgUser,ImageUpload,qwUserList,WelComeAdd,MaterialQw},
  557. data() {
  558. return {
  559. imageArr:[],
  560. // 遮罩层
  561. loading: true,
  562. // 导出遮罩层
  563. exportLoading: false,
  564. // 选中数组
  565. ids: [],
  566. // 非单个禁用
  567. single: true,
  568. // 非多个禁用
  569. multiple: true,
  570. myQwCompanyList:[],
  571. // 显示搜索条件
  572. showSearch: true,
  573. // 总条数
  574. total: 0,
  575. dialogImageUrl:null,
  576. dialogVisible:false,
  577. // 客户群发记录主表格数据
  578. groupMsgList: [],
  579. //任务类型
  580. groupMsgChatType:[],
  581. //发送类型
  582. groupMsgTimerType:[],
  583. //选择客户类型
  584. groupMsgTypeOptions:[],
  585. //是否允许成员在待发送列表中再次选择
  586. allowSelectOptions:[],
  587. //消息类型
  588. msgTypeOptions:[],
  589. //客户性别
  590. sysUserSex:[],
  591. genderSex:null,
  592. //预期发送客户人数
  593. expectCountCustomer:null,
  594. //部分客户预期发送客户人数
  595. expectCountGroupChat:null,
  596. //客户群选择列表
  597. groupChatList:[],
  598. //成员选择列表
  599. userSelectList:[],
  600. //查询预计通知人数
  601. countList:{
  602. //根据成员查
  603. userIds:{},
  604. //根据筛选客户条件查
  605. //1.群聊
  606. chartIds:{},
  607. },
  608. //选择的标签
  609. tagsIdsChangeSelectList:null,
  610. //排除的标签
  611. outTagsIdsChangeSelectList:null,
  612. //选择群发账号列表
  613. listUser:{
  614. title:"",
  615. open:false
  616. },
  617. //选择所在群聊里的人
  618. groupChart:{
  619. title:"",
  620. open:false,
  621. },
  622. tagTotal:0,
  623. //标签弹窗选择
  624. tagChange:{
  625. open:false,
  626. index:null,
  627. },
  628. queryTagParams:{
  629. pageNum: 1,
  630. pageSize: 5,
  631. total:0,
  632. name:null,
  633. corpId:null,
  634. },
  635. //选择标签
  636. changeTagDialog:{
  637. title:"",
  638. open:false,
  639. type:null,
  640. },
  641. detailsDialog:{
  642. title:"",
  643. open:false,
  644. type:null,
  645. },
  646. //标签组
  647. tagGroupList:[],
  648. //所有标签
  649. tagList:[],
  650. // 弹出层标题
  651. title: "",
  652. // 是否显示弹出层
  653. open: false,
  654. // 查询参数
  655. queryParams: {
  656. pageNum: 1,
  657. pageSize: 10,
  658. chatType: "single",
  659. sender: null,
  660. allowSelect: null,
  661. textContent: null,
  662. msgid: null,
  663. qwMsgId:null,
  664. corpId: null,
  665. companyId: null,
  666. tagNames: null,
  667. groupChatNames: null,
  668. fromUserCount: null,
  669. toUserCount: null,
  670. fromUserNum: null,
  671. toUserNum: null,
  672. },
  673. // 表单参数
  674. form: {},
  675. //详情
  676. formDetails:{},
  677. // 表单校验
  678. rules: {
  679. chatType: [
  680. { required: true, message: "群发任务的类型,默认为single,表示发送给客户,group表示发送给客户群不能为空", trigger: "change" }
  681. ],
  682. userIdsSelectList: [
  683. { required: true, message: "发送企业群发消息的成员账号不能为空", trigger: "blur" }
  684. ],
  685. allowSelect: [
  686. { required: true, message: "是否允许成员在待发送客户列表中重新进行选择,默认为true", trigger: "blur" }
  687. ],
  688. textContent:[
  689. { required: true, message: "消息文本不能为空噢", trigger: "blur" }
  690. ],
  691. createName:[
  692. { required: true, message: "创建人不能为空", trigger: "blur" }
  693. ]
  694. },
  695. //日期快捷选择
  696. pickerOptions: {
  697. shortcuts: [
  698. {
  699. text: '最近三天',
  700. onClick(picker) {
  701. const end = new Date();
  702. const start = new Date();
  703. start.setTime(start.getTime() - 3600 * 1000 * 24 * 3);
  704. picker.$emit('pick', [start, end]);
  705. }
  706. },{
  707. text: '最近一周',
  708. onClick(picker) {
  709. const end = new Date();
  710. const start = new Date();
  711. start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
  712. picker.$emit('pick', [start, end]);
  713. }
  714. }, {
  715. text: '最近一个月',
  716. onClick(picker) {
  717. const end = new Date();
  718. const start = new Date();
  719. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
  720. picker.$emit('pick', [start, end]);
  721. }
  722. }, {
  723. text: '最近三个月',
  724. onClick(picker) {
  725. const end = new Date();
  726. const start = new Date();
  727. start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
  728. picker.$emit('pick', [start, end]);
  729. }
  730. }]
  731. },
  732. };
  733. },
  734. created() {
  735. getMyQwCompanyList().then(response => {
  736. this.myQwCompanyList = response.data;
  737. if(this.myQwCompanyList!=null){
  738. this.queryParams.corpId=this.myQwCompanyList[0].dictValue;
  739. this.getList();
  740. }
  741. });
  742. //全部客户还是部分客户
  743. this.getDicts("sys_qw_groupMsg_type").then(response => {
  744. this.groupMsgTypeOptions = response.data;
  745. });
  746. //文本类型字典(复用)
  747. this.getDicts("sys_qw_welcome_type").then(response => {
  748. this.msgTypeOptions = response.data;
  749. });
  750. this.getDicts("sys_qw_group_msg_chat_type").then(response => {
  751. this.groupMsgChatType = response.data;
  752. });
  753. //发送类型
  754. this.getDicts("sys_qw_group_msg_timer_type").then(response => {
  755. this.groupMsgTimerType = response.data;
  756. });
  757. //客户性别
  758. this.getDicts("sys_qw_external_contact_gender").then(response => {
  759. this.sysUserSex = response.data;
  760. // 要添加的新对象数据
  761. let newUserData = {
  762. dictValue: "99",
  763. dictLabel: '全部',
  764. };
  765. // 添加对象到数组
  766. this.sysUserSex.push(newUserData);
  767. });
  768. //是否允许成员在待发送列表中再次选择
  769. this.getDicts("sys_qw_allow_select").then(response => {
  770. this.allowSelectOptions = response.data;
  771. });
  772. },
  773. watch:{
  774. // 监听 userSelectList 的变化,并同步更新 form.userIdsSelectList
  775. userSelectList(newList) {
  776. this.form.userIdsSelectList = newList.map(item => item.qwUserId);
  777. },
  778. groupChatList(newList){
  779. this.form.groupChatSelectList=newList.map(item=>item.chatId)
  780. },
  781. },
  782. methods: {
  783. updateCorpId(){
  784. this.getList();
  785. },
  786. //关闭弹窗-清空页面
  787. closeData(){
  788. this.reset();
  789. },
  790. /** 查询客户群发记录主列表 */
  791. getList() {
  792. this.loading = true;
  793. listGroupMsg(this.queryParams).then(response => {
  794. this.groupMsgList = response.rows;
  795. this.total = response.total;
  796. this.loading = false;
  797. });
  798. },
  799. // 取消按钮
  800. cancel() {
  801. this.open = false;
  802. this.reset();
  803. },
  804. //标签的选择
  805. tagSelection(row){
  806. row.isSelected= !row.isSelected;
  807. this.$forceUpdate();
  808. },
  809. /** 提醒成员群发 */
  810. triggerRemindGroupMsg(row){
  811. this.queryParams.qwMsgId=row.msgId
  812. remindGroupMsg(this.queryParams).then(res=>{
  813. if (res.code==200){
  814. if (res.data.errcode==0){
  815. return this.msgSuccess("提醒成员群发成功")
  816. }else if (res.data.errcode==41094){
  817. return this.msgWarning("此条记录的每日提醒次数超过限制了噢")
  818. }else {
  819. return this.msgError(res.data.errmsg)
  820. }
  821. }else {
  822. return this.msgError(res.msg)
  823. }
  824. })
  825. },
  826. getPageListTagGroup(){
  827. this.queryTagParams.corpId=this.queryParams.corpId
  828. allListTagGroup(this.queryTagParams).then(response => {
  829. this.tagGroupList = response.rows;
  830. this.tagTotal = response.total;
  831. });
  832. },
  833. handleSearchTags(name){
  834. if (!name){
  835. return this.$message.error("请输入要搜索的标签")
  836. }
  837. this.queryTagParams.name=name;
  838. this.queryTagParams.corpId=this.queryParams.corpId;
  839. searchTags(this.queryTagParams).then(response => {
  840. this.tagGroupList = response.rows;
  841. });
  842. // searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
  843. // this.tagGroupList = response.rows;
  844. // });
  845. },
  846. cancelSearchTags(){
  847. this.afreshData()
  848. },
  849. //清除点我查看
  850. clearExpectCountCustomer(){
  851. //选择全部客户的统计
  852. this.expectCountCustomer=null;
  853. //选择部分客户的统计
  854. this.expectCountGroupChat=null;
  855. },
  856. //查看预计接收人数
  857. viewReceiveNum(){
  858. if (this.userSelectList.length==0){
  859. return this.msgError("请选择群发成员账号");
  860. }else {
  861. this.form.corpId=this.queryParams.corpId;
  862. selectCountCustomer(this.form).then(res=>{
  863. this.expectCountCustomer=res.data;
  864. })
  865. }
  866. },
  867. //查看部分客户预计接收人数
  868. viewReceiveGroupChatNum(){
  869. if (this.userSelectList.length==0){
  870. return this.msgError("请选择群发成员账号");
  871. }else {
  872. // 使用 map 方法和解构赋值提取每个子数组的第一个元素
  873. // 选择的标签
  874. if (this.tagsIdsChangeSelectList!=null){
  875. this.form.tagsIdsSelectList=this.tagsIdsChangeSelectList.map(item => item.tagId);
  876. }
  877. //排除的标签
  878. if (this.outTagsIdsChangeSelectList!=null){
  879. this.form.outTagsIdsSelectList = this.outTagsIdsChangeSelectList.map(item => item.tagId);
  880. }
  881. this.form.corpId=this.queryParams.corpId;
  882. selectCountCustomer(this.form).then(res=>{
  883. this.expectCountGroupChat=res.data;
  884. })
  885. }
  886. },
  887. //选择的成员账号列表
  888. selectUserList(list){
  889. this.listUser.open=false;
  890. //用于显示
  891. this.userSelectList=list;
  892. // //用于查询
  893. // this.form.userIdsSelectList= this.userSelectList.map(item => item.id);
  894. },
  895. //选择的部分客户时,选择的群聊里的
  896. selectGroupChatList(list){
  897. this.groupChart.open=false;
  898. //用于显示
  899. this.groupChatList=list;
  900. // //用于查询
  901. // this.form.groupChatSelectList=this.groupChatList.map(item=>item.chatId);
  902. },
  903. //确定选择标签
  904. tagSubmitForm(type){
  905. //制空选项
  906. // for (let i = 0; i < this.tagGroupList.length; i++) {
  907. // for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  908. // this.tagGroupList[i].tag[x].isSelected=false;
  909. // }
  910. // }
  911. if (type==1){
  912. for (let i = 0; i < this.tagGroupList.length; i++) {
  913. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  914. if (this.tagGroupList[i].tag[x].isSelected === true) {
  915. if (!this.tagsIdsChangeSelectList) {
  916. this.tagsIdsChangeSelectList = [];
  917. }
  918. // 检查当前 tag 是否已经存在于 tagListFormIndex[index] 中
  919. let tagExists = this.tagsIdsChangeSelectList.some(
  920. tag => tag.id === this.tagGroupList[i].tag[x].id
  921. );
  922. // 如果 tag 不存在于 tagListFormIndex[index] 中,则新增
  923. if (!tagExists) {
  924. this.tagsIdsChangeSelectList.push(this.tagGroupList[i].tag[x]);
  925. }
  926. }
  927. }
  928. }
  929. if (!this.tagsIdsChangeSelectList || this.tagsIdsChangeSelectList.length === 0) {
  930. return this.$message('请选择标签');
  931. }
  932. }else if (type==2){
  933. for (let i = 0; i < this.tagGroupList.length; i++) {
  934. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  935. if (this.tagGroupList[i].tag[x].isSelected === true) {
  936. if (!this.outTagsIdsChangeSelectList) {
  937. this.outTagsIdsChangeSelectList = [];
  938. }
  939. // 检查当前 tag 是否已经存在于 tagListFormIndex[index] 中
  940. let tagExists = this.outTagsIdsChangeSelectList.some(
  941. tag => tag.id === this.tagGroupList[i].tag[x].id
  942. );
  943. // 如果 tag 不存在于 tagListFormIndex[index] 中,则新增
  944. if (!tagExists) {
  945. this.outTagsIdsChangeSelectList.push(this.tagGroupList[i].tag[x]);
  946. }
  947. }
  948. }
  949. }
  950. if (!this.outTagsIdsChangeSelectList || this.outTagsIdsChangeSelectList.length === 0) {
  951. return this.$message('请选择标签');
  952. }
  953. }
  954. this.changeTagDialog.open = false;
  955. },
  956. //取消选择标签
  957. tagCancel(){
  958. this.changeTagDialog.open = false;
  959. },
  960. // //选择的标签
  961. // selectTagsList(list,type){
  962. //
  963. // const result = list.flatMap(item => {
  964. // return item.tag.map(tag => [tag.tagId, tag.name]);
  965. // });
  966. //
  967. // //获取到选择的标签列表
  968. // const uniqueResult = Array.from(new Set(result.map(JSON.stringify)), JSON.parse);
  969. // this.changeTagDialog.open=false
  970. //
  971. // if (type==1){
  972. // this.tagsIdsChangeSelectList=uniqueResult;
  973. // }else if (type==2){
  974. // this.outTagsIdsChangeSelectList=uniqueResult;
  975. // }
  976. //
  977. // },
  978. //删除一些选择了的账号
  979. handleClosegroupUser(list){
  980. // 假设 list 对象具有一个 id 属性
  981. const index = this.userSelectList.findIndex(t => t.id === list.id);
  982. if (index !== -1) {
  983. this.userSelectList.splice(index, 1);
  984. }
  985. //表单同时清除
  986. // this.form.userIdsSelectList= this.userSelectList.map(item => item.id);
  987. },
  988. //删除一些选择了的群聊
  989. handleClosegroupChat(list){
  990. // 假设 list 对象具有一个 id 属性
  991. const index = this.groupChatList.findIndex(t => t.chatId === list.chatId);
  992. if (index !== -1) {
  993. this.groupChatList.splice(index, 1);
  994. }
  995. // //表单同时清除
  996. // this.form.groupChatSelectList=this.groupChatList.map(item=>item.chatId);
  997. },
  998. //删除一些选择的标签
  999. handleCloseTags(list){
  1000. // 假设 list 对象具有一个 id 属性
  1001. const ls = this.tagsIdsChangeSelectList.findIndex(t => t.tagId === list.tagId);
  1002. if (ls !== -1) {
  1003. this.tagsIdsChangeSelectList.splice(ls, 1);
  1004. this.tagsIdsChangeSelectList = [...this.tagsIdsChangeSelectList];
  1005. }
  1006. },
  1007. //删除一些排除的标签
  1008. handleCloseOutTags(list){
  1009. // const index = this.outTagsIdsChangeSelectList.findIndex(t => t[0] === tag[0]);
  1010. // if (index !== -1) {
  1011. // this.outTagsIdsChangeSelectList.splice(index, 1);
  1012. // }
  1013. // 假设 list 对象具有一个 id 属性
  1014. const ls = this.outTagsIdsChangeSelectList.findIndex(t => t.tagId === list.tagId);
  1015. if (ls !== -1) {
  1016. this.outTagsIdsChangeSelectList.splice(ls, 1);
  1017. this.outTagsIdsChangeSelectList = [...this.outTagsIdsChangeSelectList];
  1018. }
  1019. },
  1020. //选择群发的企业成员账号
  1021. handlelistUser(){
  1022. this.listUser.title="选择企业成员"
  1023. this.listUser.open=true;
  1024. setTimeout(() => {
  1025. this.$refs.qwUserList.getDetails(this.queryParams.corpId)
  1026. }, 200);
  1027. //预计人数制空
  1028. this.expectCountCustomer=null;
  1029. },
  1030. //选择群聊
  1031. handleGroupChatList(){
  1032. this.groupChart.title="选择所在群聊里的客户"
  1033. this.groupChart.open=true;
  1034. setTimeout(() => {
  1035. this.$refs.GroupChat.getDetailsList(this.queryParams.corpId)
  1036. }, 200);
  1037. //预计人数制空
  1038. this.expectCountGroupChat=null;
  1039. },
  1040. //选择标签
  1041. hangleChangeTags(){
  1042. this.changeTagDialog.title="选择标签"
  1043. this.changeTagDialog.open=true;
  1044. this.changeTagDialog.type=1;
  1045. // 获取 tagListFormIndex 中的所有 tagId,用于快速查找
  1046. const selectedTagIds = new Set(this.tagsIdsChangeSelectList.map(tagItem => tagItem.tagId));
  1047. for (let i = 0; i < this.tagGroupList.length; i++) {
  1048. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  1049. this.tagGroupList[i].tag[x].isSelected = selectedTagIds.has(this.tagGroupList[i].tag[x].tagId);
  1050. }
  1051. }
  1052. // setTimeout(() => {
  1053. // this.$refs.TagGroupList.getTagGroupList(this.queryParams.corpId)
  1054. // }, 200);
  1055. //预计人数制空
  1056. this.expectCountGroupChat=null;
  1057. },
  1058. //选择排除标签
  1059. hangleChangeOutTags(){
  1060. this.changeTagDialog.title="选择排除的标签"
  1061. this.changeTagDialog.open=true;
  1062. this.changeTagDialog.type=2;
  1063. // 获取 tagListFormIndex 中的所有 tagId,用于快速查找
  1064. const selectedTagIds = new Set(this.outTagsIdsChangeSelectList.map(tagItem => tagItem.tagId));
  1065. for (let i = 0; i < this.tagGroupList.length; i++) {
  1066. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  1067. this.tagGroupList[i].tag[x].isSelected = selectedTagIds.has(this.tagGroupList[i].tag[x].tagId);
  1068. }
  1069. }
  1070. // setTimeout(() => {
  1071. // this.$refs.TagGroupList.getTagGroupList(this.queryParams.corpId)
  1072. // }, 200);
  1073. //
  1074. //预计人数制空
  1075. this.expectCountGroupChat=null;
  1076. },
  1077. // 表单重置
  1078. reset() {
  1079. this.form = {
  1080. id: null,
  1081. chatType: "single",
  1082. sender: null,
  1083. gender:"99",
  1084. allowSelect: "Y",
  1085. textContent: null,
  1086. msgid: null,
  1087. corpId: null,
  1088. companyId: null,
  1089. tagNames: null,
  1090. groupChatNamesList: [],
  1091. fromUserCount: null,
  1092. toUserCount: null,
  1093. fromUserNum: null,
  1094. toUserNum: null,
  1095. createTime: null,
  1096. updateTime: null,
  1097. msgType:null,
  1098. mediaId: null,
  1099. mediaPicUrl: null,
  1100. title: null,
  1101. picurl: null,
  1102. description: null,
  1103. url: null,
  1104. miniprogramTitle: null,
  1105. miniprogramPicMediaId: null,
  1106. miniprogramPicUrl: null,
  1107. miniprogramAppid: null,
  1108. miniprogramPage: null,
  1109. fileMediaId: null,
  1110. fileUrl: null,
  1111. videoMediaId: null,
  1112. videoUrl: null,
  1113. //选择的成员账号
  1114. userIdsSelectList:[],
  1115. //选择的群聊
  1116. groupChatSelectList:[],
  1117. //选择的时间
  1118. timeScreenCharge:[],
  1119. //全部客户还是部分客户
  1120. selectType:'1',
  1121. //选择的标签列表
  1122. tagsIdsSelectList:[],
  1123. //排除的标签
  1124. outTagsIdsSelectList:[],
  1125. };
  1126. this.userSelectList=[];
  1127. this.expectCountCustomer=null;
  1128. this.groupChatList=[];
  1129. this.tagsIdsChangeSelectList=[];
  1130. this.outTagsIdsChangeSelectList=[];
  1131. this.expectCountGroupChat=[];
  1132. this.resetForm("form");
  1133. },
  1134. /** 搜索按钮操作 */
  1135. handleQuery() {
  1136. this.queryParams.pageNum = 1;
  1137. this.getList();
  1138. },
  1139. hangdleDitels(row){
  1140. this.reset();
  1141. const id = row.id || this.ids
  1142. getGroupMsg(id).then(response => {
  1143. this.formDetails = response.data;
  1144. this.detailsDialog.open = true;
  1145. this.detailsDialog.title = "客户群发记录详情";
  1146. });
  1147. },
  1148. /** 重置按钮操作 */
  1149. resetQuery() {
  1150. this.resetForm("queryForm");
  1151. this.handleQuery();
  1152. },
  1153. // 多选框选中数据
  1154. handleSelectionChange(selection) {
  1155. this.ids = selection.map(item => item.id)
  1156. this.single = selection.length!==1
  1157. this.multiple = !selection.length
  1158. },
  1159. /** 新增按钮操作 */
  1160. handleAdd() {
  1161. this.reset();
  1162. this.open = true;
  1163. this.form.msgType="1"
  1164. this.title = "新建群发";
  1165. this.afreshData();
  1166. // //所有的标签组
  1167. // allListTagGroup({corpId:this.queryParams.corpId}).then(response => {
  1168. // this.tagGroupList = response.rows;
  1169. // });
  1170. //
  1171. // //所有的标签
  1172. // listTag({corpId:this.queryParams.corpId}).then(response => {
  1173. // this.tagList = response.rows;
  1174. // });
  1175. },
  1176. /**
  1177. * 重新获取 部分数据
  1178. */
  1179. afreshData(){
  1180. //所有的标签组
  1181. allListTagGroup({corpId:this.queryParams.corpId}).then(response => {
  1182. this.tagGroupList = response.rows;
  1183. });
  1184. //所有的标签
  1185. listTag({corpId:this.queryParams.corpId}).then(response => {
  1186. this.tagList = response.rows;
  1187. });
  1188. },
  1189. /** 获取企业员工列表 */
  1190. // getUserList(){
  1191. // //获取企业员工
  1192. // listUser(this.queryParams).then(response => {
  1193. // this.userList = response.rows;
  1194. // this.total = response.total;
  1195. // this.loading = false;
  1196. // });
  1197. // },
  1198. /** 修改按钮操作 */
  1199. handleUpdate(row) {
  1200. this.reset();
  1201. const id = row.id || this.ids
  1202. getGroupMsg(id).then(response => {
  1203. this.form = response.data;
  1204. this.open = true;
  1205. this.title = "修改客户群发记录主";
  1206. });
  1207. },
  1208. openImageViewer(url) {
  1209. // 打开大图预览对话框
  1210. this.dialogImageUrl=url
  1211. this.dialogVisible = true;
  1212. },
  1213. /** 提交按钮 */
  1214. async submitForm() {
  1215. // 选择的标签
  1216. if (this.tagsIdsChangeSelectList!=null){
  1217. this.form.tagsIdsSelectList=this.tagsIdsChangeSelectList.map(item => item.tagId);
  1218. }
  1219. //排除的标签
  1220. if (this.outTagsIdsChangeSelectList!=null){
  1221. this.form.outTagsIdsSelectList = this.outTagsIdsChangeSelectList.map(item => item.tagId);
  1222. }
  1223. this.form.corpId=this.queryParams.corpId;
  1224. try {
  1225. // 验证子组件表单
  1226. await this.$refs.WelComeAdd.validateChildForm();
  1227. // 父组件表单验证逻辑
  1228. await this.$refs["form"].validate(valid => {
  1229. if (valid) {
  1230. if (this.form.id != null) {
  1231. return this.msgError("没有修改选项");
  1232. } else {
  1233. this.loading=true;
  1234. Object.assign(this.form, this.$refs.WelComeAdd.form);
  1235. this.form.chatType="single";
  1236. addGroupMsg(this.form).then(response => {
  1237. this.msgSuccess("创建成功");
  1238. this.open = false;
  1239. this.loading = false;
  1240. this.getList();
  1241. }).catch(error => {
  1242. this.open=true;
  1243. this.loading = false;
  1244. }).finally(
  1245. () => {
  1246. this.$refs["form"].resetFields();
  1247. this.$refs.WelComeAdd.reset();
  1248. this.userSelectList=[];
  1249. this.reset();
  1250. }
  1251. );
  1252. }
  1253. }
  1254. });
  1255. } catch (error) {
  1256. console.error('表单编辑群发信息验证不用过:', error.message);
  1257. }
  1258. },
  1259. /** 删除按钮操作 */
  1260. handleDelete(row) {
  1261. const ids = row.id || this.ids;
  1262. this.$confirm('是否确认删除客户群发记录主编号为"' + ids + '"的数据项?', "警告", {
  1263. confirmButtonText: "确定",
  1264. cancelButtonText: "取消",
  1265. type: "warning"
  1266. }).then(function() {
  1267. return delGroupMsg(ids);
  1268. }).then(() => {
  1269. this.getList();
  1270. this.msgSuccess("删除成功");
  1271. }).catch(() => {});
  1272. },
  1273. }
  1274. };
  1275. </script>
  1276. <style scoped>
  1277. .user-box {
  1278. width: 50px; /* 盒子宽度 */
  1279. height: 30px; /* 盒子高度 */
  1280. padding: 5px 10px; /* 内边距 */
  1281. border: 1px solid #d5d1d1;/* 边框 */
  1282. margin: 3px; /* 外边距 */
  1283. background-color: #f9f9f9;/* 背景颜色 */
  1284. color: #333; /* 文本颜色 */
  1285. font-size: 14px; /* 字体大小 */
  1286. text-align: center; /* 文本居中 */
  1287. }
  1288. .elFormItemClass{
  1289. margin: 20px 0px
  1290. }
  1291. .message-stayle{
  1292. display: flex;
  1293. justify-content: normal;
  1294. align-items: center;
  1295. margin-top: 10px;
  1296. }
  1297. .message-stayle .el-link {
  1298. white-space: normal; /* 允许换行 */
  1299. word-break: break-all; /* 单词中间断行 */
  1300. overflow-wrap: break-word; /* 允许在单词内换行 */
  1301. }
  1302. .message-stayle span {
  1303. word-break: break-all;
  1304. }
  1305. .container {
  1306. position: relative; /* 使 phone div 的 absolute 定位基于这个容器 */
  1307. width: 100%;
  1308. height: 100%;
  1309. }
  1310. .phone {
  1311. position: absolute; /* 定位到容器内 */
  1312. top: 5%;
  1313. left: 50%;
  1314. transform: translateX(-50%);
  1315. width: 100%;
  1316. max-width: 375px;
  1317. height: 100%;
  1318. max-height: 90%;
  1319. border: 8px solid #ccc;
  1320. border-radius: 36px;
  1321. box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  1322. background-color: #fff;
  1323. overflow: hidden;
  1324. }
  1325. .phone::before {
  1326. content: '';
  1327. position: absolute;
  1328. top: 0;
  1329. left: 50%;
  1330. width: 60px;
  1331. height: 5px;
  1332. background-color: #ccc;
  1333. border-radius: 10px;
  1334. transform: translateX(-50%);
  1335. }
  1336. .chat-interface {
  1337. display: flex;
  1338. flex-direction: column;
  1339. height: 100%;
  1340. background-color: #fff;
  1341. }
  1342. .header {
  1343. display: flex;
  1344. justify-content: space-between;
  1345. align-items: center;
  1346. height: 50px;
  1347. padding: 0 15px;
  1348. background-color: #fff;
  1349. border-bottom: 1px solid #e0e0e0;
  1350. }
  1351. .header .back,
  1352. .header .menu {
  1353. height: 25px;
  1354. width: 25px;
  1355. }
  1356. .header .title{
  1357. font-size: 16px;
  1358. margin: auto;
  1359. }
  1360. .message-area {
  1361. flex: 1;
  1362. background-color: rgb(240, 242, 245);
  1363. padding: 10px;
  1364. overflow-y: auto;
  1365. }
  1366. .footer {
  1367. display: flex;
  1368. align-items: center;
  1369. padding: 10px;
  1370. background-color: #fff;
  1371. border-top: 1px solid #e0e0e0;
  1372. }
  1373. .footer .voice-button,
  1374. .footer .emoji-button,
  1375. .footer .add-button {
  1376. width: 25px;
  1377. height: 25px;
  1378. border: none;
  1379. cursor: pointer;
  1380. flex-shrink: 0; /* 不允许缩小 */
  1381. }
  1382. .footer .emoji-button,
  1383. .footer .add-button {
  1384. margin: 0px 5px;
  1385. }
  1386. .footer .input-box {
  1387. flex: 1;
  1388. border: 1px solid #e0e0e0;
  1389. margin-left: 5px;
  1390. }
  1391. .text-container {
  1392. max-height: 7.5em; /* 设置最大高度为6行,根据字体大小调整 */
  1393. overflow-y: auto; /* 内容超出时显示滚动条 */
  1394. line-height: 1.5em; /* 行高设置,确保每行高度一致 */
  1395. }
  1396. .el-form-item {
  1397. margin-bottom: 30px;
  1398. }
  1399. .custom-span {
  1400. display: block; /* 确保元素是块级元素 */
  1401. height: 110px; /* 设置固定高度 */
  1402. overflow-y: auto; /* 超出高度时显示滚动条 */
  1403. word-wrap: break-word; /* 自动换行 */
  1404. word-break: break-all; /* 在必要时进行换行 */
  1405. }
  1406. .custom-span-description{
  1407. display: block; /* 确保元素是块级元素 */
  1408. height: 110px; /* 设置固定高度 */
  1409. overflow-y: auto; /* 超出高度时显示滚动条 */
  1410. word-wrap: break-word; /* 自动换行 */
  1411. word-break: break-all; /* 在必要时进行换行 */
  1412. }
  1413. .custom-span-title {
  1414. display: block; /* 确保元素是块级元素 */
  1415. height: 45px; /* 设置固定高度 */
  1416. overflow-y: auto; /* 超出高度时显示滚动条 */
  1417. word-wrap: break-word; /* 自动换行 */
  1418. word-break: break-all; /* 在必要时进行换行 */
  1419. }
  1420. /* CSS 样式 */
  1421. .tag-container {
  1422. display: flex;
  1423. flex-wrap: wrap; /* 超出宽度时自动换行 */
  1424. gap: 8px; /* 设置标签之间的间距 */
  1425. }
  1426. .name-background {
  1427. display: inline-block;
  1428. background-color: #abece6; /* 背景颜色 */
  1429. padding: 4px 8px; /* 调整内边距,让背景包裹文字 */
  1430. border-radius: 4px; /* 可选:设置圆角 */
  1431. }
  1432. .tag-box {
  1433. padding: 8px 12px;
  1434. border: 1px solid #989797;
  1435. border-radius: 4px;
  1436. cursor: pointer;
  1437. display: inline-block;
  1438. }
  1439. .tag-selected {
  1440. background-color: #00bc98;
  1441. color: #fff;
  1442. border-color: #00bc98;
  1443. }
  1444. .el-tag + .el-tag {
  1445. margin-left: 10px;
  1446. }
  1447. .button-new-tag {
  1448. margin-left: 10px;
  1449. height: 32px;
  1450. line-height: 30px;
  1451. padding-top: 0;
  1452. padding-bottom: 0;
  1453. }
  1454. .input-new-tag {
  1455. width: 90px;
  1456. margin-left: 10px;
  1457. vertical-align: bottom;
  1458. }
  1459. .text-container {
  1460. max-height: 5em; /* 设置最大高度为6行,根据字体大小调整 */
  1461. overflow-y: auto; /* 内容超出时显示滚动条 */
  1462. line-height: 1.5em; /* 行高设置,确保每行高度一致 */
  1463. }
  1464. /* 新增的滚动容器样式(不影响原有样式) */
  1465. .scroll-wrapper {
  1466. max-height: 130px; /* 大约三行的高度 */
  1467. overflow-y: auto; /* 垂直滚动 */
  1468. padding-right: 5px; /* 为滚动条留出空间 */
  1469. }
  1470. /* 美化滚动条(可选) */
  1471. .scroll-wrapper::-webkit-scrollbar {
  1472. width: 6px;
  1473. }
  1474. .scroll-wrapper::-webkit-scrollbar-thumb {
  1475. background: rgba(0, 0, 0, 0.2);
  1476. border-radius: 3px;
  1477. }
  1478. </style>