index.vue 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599
  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. <div class="tag-container">
  342. <a
  343. v-for="tagItem in item.tag"
  344. class="tag-box"
  345. @click="tagSelection(tagItem)"
  346. :class="{ 'tag-selected': tagItem.isSelected }"
  347. >
  348. {{ tagItem.name }}
  349. </a>
  350. </div>
  351. </div>
  352. <div slot="footer" class="dialog-footer">
  353. <el-button type="primary" @click="tagSubmitForm(changeTagDialog.type)">确 定</el-button>
  354. <el-button @click="tagCancel(changeTagDialog.type)">取消</el-button>
  355. </div>
  356. </el-dialog>
  357. <!-- 详情 -->
  358. <el-drawer :title="detailsDialog.title" :visible.sync="detailsDialog.open" size="75%" style="font-weight: bolder">
  359. <div style="background-color: rgb(240 242 245)">
  360. <div style="display: flex;flex-wrap: nowrap;background-color: rgb(240 242 245);height: 850px;margin: 15px;padding-top: 15px" >
  361. <el-card class="box-card" style="width: 700px" >
  362. <el-descriptions :column="1" border :labelStyle="{width: '150px'}">
  363. <el-descriptions-item label="群发选择类型:">
  364. <template v-for="item in groupMsgTypeOptions" v-if="item.dictValue == formDetails.selectType">
  365. <span>{{item.dictLabel}}</span>
  366. </template>
  367. </el-descriptions-item>
  368. <el-descriptions-item label="消息文本内容:" >
  369. <span class="custom-span">{{formDetails.textContent}}</span>
  370. </el-descriptions-item>
  371. <el-descriptions-item label="图片" v-if="formDetails.msgType=='1'">
  372. <el-image
  373. v-if="formDetails.mediaPicUrl"
  374. style="width: 100px; height: 100px"
  375. :src="formDetails.mediaPicUrl"
  376. fit="contain"
  377. @click="openImageViewer(formDetails.mediaPicUrl)"/>
  378. </el-descriptions-item>
  379. <el-descriptions-item label="图文标题:" v-if="formDetails.msgType=='2'">
  380. <span class="custom-span-title">{{formDetails.title}}</span>
  381. </el-descriptions-item>
  382. <el-descriptions-item label="图文封面:" v-if="formDetails.msgType=='2'">
  383. <el-image
  384. v-if="formDetails.picurl"
  385. style="width: 100px; height: 100px"
  386. :src="formDetails.picurl"
  387. fit="contain"
  388. @click="openImageViewer(formDetails.picurl)"/>
  389. </el-descriptions-item>
  390. <el-descriptions-item label="图文的描述:" v-if="formDetails.msgType=='2'">
  391. <span class="custom-span-description">{{formDetails.description}}</span>
  392. </el-descriptions-item>
  393. <el-descriptions-item label="图文的链接:" v-if="formDetails.msgType=='2'">
  394. <el-link :href="formDetails.url" target="_blank">{{ formDetails.url }}</el-link>
  395. <!-- <el-image-->
  396. <!-- v-if="formDetails.url"-->
  397. <!-- style="width: 100px; height: 100px"-->
  398. <!-- :src="formDetails.url"-->
  399. <!-- fit="contain"-->
  400. <!-- @click="openImageViewer(formDetails.url)"/>-->
  401. </el-descriptions-item>
  402. <el-descriptions-item label="小程序标题:" v-if="formDetails.msgType=='3'">{{formDetails.miniprogramTitle}}</el-descriptions-item>
  403. <el-descriptions-item label="小程序封面:" v-if="formDetails.msgType=='3'">
  404. <el-image
  405. v-if="formDetails.miniprogramPicUrl"
  406. style="width: 100px; height: 100px"
  407. :src="formDetails.miniprogramPicUrl"
  408. fit="contain"
  409. @click="openImageViewer(formDetails.miniprogramPicUrl)"/>
  410. </el-descriptions-item>
  411. <el-descriptions-item label="小程序appid:" v-if="formDetails.msgType=='3'">{{formDetails.miniprogramAppid}}</el-descriptions-item>
  412. <el-descriptions-item label="小程序page路径:" v-if="formDetails.msgType=='3'">{{formDetails.miniprogramPage}}</el-descriptions-item>
  413. <el-descriptions-item label="企微临时文件mediaId:" v-if="formDetails.msgType=='4'">{{formDetails.fileMediaId}}</el-descriptions-item>
  414. <el-descriptions-item label="文件:" v-if="formDetails.msgType=='4'">
  415. <el-link v-if="formDetails.fileUrl" type="primary" :href="formDetails.fileUrl" download>
  416. {{formDetails.fileUrl}}
  417. </el-link>
  418. </el-descriptions-item>
  419. <el-descriptions-item label="视频临时文件mediaId:" v-if="formDetails.msgType=='5'">{{formDetails.videoMediaId}}</el-descriptions-item>
  420. <el-descriptions-item label="视频:" v-if="formDetails.msgType=='5'">
  421. <video v-if="formDetails.videoUrl"
  422. :src="formDetails.videoUrl"
  423. controls style="width: 200px;height: 100px">
  424. </video>
  425. </el-descriptions-item>
  426. <el-descriptions-item label="是否允许成员分配:" >
  427. <span v-for="dict in allowSelectOptions" v-if="dict.dictValue==formDetails.allowSelect">{{dict.dictLabel}}</span>
  428. </el-descriptions-item>
  429. <el-descriptions-item label="创建人:">{{formDetails.createName}}</el-descriptions-item>
  430. <el-descriptions-item label="创建时间:">{{formDetails.createTime}}</el-descriptions-item>
  431. </el-descriptions>
  432. </el-card>
  433. <div style="width: 700px;background-color:rgb(255 255 255); display: flex;justify-content: center;align-items: center">
  434. <div class="container">
  435. <div class="phone">
  436. <div class="chat-interface">
  437. <div class="header">
  438. <span class="back">
  439. <img src="../../../assets/image/return.png" class="back">
  440. </span>
  441. <span class="title">客服账号</span>
  442. <span class="menu">
  443. <img src="../../../assets/image/more.png" class="menu">
  444. </span>
  445. </div>
  446. <div class="message-area">
  447. <div v-if="formDetails.textContent" class="message-stayle">
  448. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  449. <div style="background-color:rgb(255 255 255); padding: 10px;">
  450. <span>{{ formDetails.textContent }}</span>
  451. </div>
  452. </div>
  453. <div v-if="formDetails.mediaPicUrl" class="message-stayle">
  454. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  455. <el-image
  456. style="width: 100px; height: 100px"
  457. :src="formDetails.mediaPicUrl"
  458. fit="contain"
  459. @click="openImageViewer(formDetails.mediaPicUrl)"/>
  460. </div>
  461. <div v-if="formDetails.title" class="message-stayle" @click="openImageViewer(formDetails.url)">
  462. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  463. <div style="background-color: white;padding: 10px;width: 100%">
  464. <span>{{formDetails.title}}</span>
  465. <div style="display: flex;justify-content:space-between;width: 100%">
  466. <span style="font-size: 13px;flex: 1">{{formDetails.description}}</span>
  467. <el-image
  468. style="width: 50px; height: 50px;flex-shrink: 0"
  469. :src="formDetails.picurl"
  470. fit="contain"
  471. @click="openImageViewer(formDetails.picurl)"/>
  472. </div>
  473. </div>
  474. </div>
  475. <div v-if="formDetails.fileUrl" class="message-stayle" >
  476. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  477. <el-link type="primary" :href="formDetails.fileUrl" download style="padding: 10px" >
  478. {{formDetails.fileUrl}}
  479. </el-link>
  480. </div>
  481. <div v-if="formDetails.videoUrl" class="message-stayle">
  482. <img src="../../../assets/image/character.png" style="width: 30px;height: 30px;margin: 5px">
  483. <video
  484. :src="formDetails.videoUrl"
  485. controls style="width: 200px;height: 100px">
  486. </video>
  487. </div>
  488. </div>
  489. <div class="footer">
  490. <span class="voice-button">
  491. <img src="../../../assets/image/voice.png" class="voice-button">
  492. </span>
  493. <input type="text" class="input-box" placeholder="">
  494. <span class="emoji-button">
  495. <img src="../../../assets/image/smilingface.png" class="emoji-button">
  496. </span>
  497. <span class="add-button">
  498. <img src="../../../assets/image/plus.png" class="add-button">
  499. </span>
  500. </div>
  501. </div>
  502. </div>
  503. </div>
  504. </div>
  505. </div>
  506. <div style="width: 100%">
  507. <customer-group-details ref="customerGroupDetails" :rowDetailFrom="formDetails"></customer-group-details>
  508. </div>
  509. </div>
  510. </el-drawer>
  511. <!-- 大图预览对话框 -->
  512. <el-dialog
  513. :visible.sync="dialogVisible"
  514. :modal="false"
  515. width="1200px"
  516. append-to-body>
  517. <img
  518. :src="this.dialogImageUrl"
  519. style="display: block; max-width: 100%; margin: 0 auto"
  520. />
  521. </el-dialog>
  522. </div>
  523. </div>
  524. </template>
  525. <script>
  526. import {
  527. listGroupMsg,
  528. getGroupMsg,
  529. delGroupMsg,
  530. addGroupMsg, remindGroupMsg
  531. } from '@/api/qw/groupMsg'
  532. import GroupMsgUser from '@/views/qw/groupMsgUser/groupMsg'
  533. import ImageUpload from "@/views/qw/material/ImageUpload";
  534. import qwUserList from "@/views/qw/user/qwUserList"
  535. import { selectCountCustomer } from '@/api/qw/externalContact'
  536. import GroupChat from '@/views/qw/groupChat/groupChat'
  537. import WelComeAdd from '@/views/qw/welcome/welComeAdd'
  538. import CustomerGroupDetails from '@/views/qw/groupMsg/customerGroupDetails'
  539. import source from 'echarts/src/data/Source'
  540. import { getMyQwUserList,getMyQwCompanyList } from "@/api/qw/user";
  541. import {allListTagGroup} from "@/api/qw/tagGroup";
  542. import {listTag, searchTags} from "@/api/qw/tag";
  543. import MaterialQw from "@/views/qw/materialQw/index.vue";
  544. export default {
  545. name: "GroupMsg",
  546. components: { CustomerGroupDetails, GroupChat, GroupMsgUser,ImageUpload,qwUserList,WelComeAdd,MaterialQw},
  547. data() {
  548. return {
  549. imageArr:[],
  550. // 遮罩层
  551. loading: true,
  552. // 导出遮罩层
  553. exportLoading: false,
  554. // 选中数组
  555. ids: [],
  556. // 非单个禁用
  557. single: true,
  558. // 非多个禁用
  559. multiple: true,
  560. myQwCompanyList:[],
  561. // 显示搜索条件
  562. showSearch: true,
  563. // 总条数
  564. total: 0,
  565. dialogImageUrl:null,
  566. dialogVisible:false,
  567. // 客户群发记录主表格数据
  568. groupMsgList: [],
  569. //任务类型
  570. groupMsgChatType:[],
  571. //发送类型
  572. groupMsgTimerType:[],
  573. //选择客户类型
  574. groupMsgTypeOptions:[],
  575. //是否允许成员在待发送列表中再次选择
  576. allowSelectOptions:[],
  577. //消息类型
  578. msgTypeOptions:[],
  579. //客户性别
  580. sysUserSex:[],
  581. genderSex:null,
  582. //预期发送客户人数
  583. expectCountCustomer:null,
  584. //部分客户预期发送客户人数
  585. expectCountGroupChat:null,
  586. //客户群选择列表
  587. groupChatList:[],
  588. //成员选择列表
  589. userSelectList:[],
  590. //查询预计通知人数
  591. countList:{
  592. //根据成员查
  593. userIds:{},
  594. //根据筛选客户条件查
  595. //1.群聊
  596. chartIds:{},
  597. },
  598. //选择的标签
  599. tagsIdsChangeSelectList:null,
  600. //排除的标签
  601. outTagsIdsChangeSelectList:null,
  602. //选择群发账号列表
  603. listUser:{
  604. title:"",
  605. open:false
  606. },
  607. //选择所在群聊里的人
  608. groupChart:{
  609. title:"",
  610. open:false,
  611. },
  612. //标签弹窗选择
  613. tagChange:{
  614. open:false,
  615. index:null,
  616. },
  617. //选择标签
  618. changeTagDialog:{
  619. title:"",
  620. open:false,
  621. type:null,
  622. },
  623. detailsDialog:{
  624. title:"",
  625. open:false,
  626. type:null,
  627. },
  628. //标签组
  629. tagGroupList:[],
  630. //所有标签
  631. tagList:[],
  632. // 弹出层标题
  633. title: "",
  634. // 是否显示弹出层
  635. open: false,
  636. // 查询参数
  637. queryParams: {
  638. pageNum: 1,
  639. pageSize: 10,
  640. chatType: "single",
  641. sender: null,
  642. allowSelect: null,
  643. textContent: null,
  644. msgid: null,
  645. qwMsgId:null,
  646. corpId: null,
  647. companyId: null,
  648. tagNames: null,
  649. groupChatNames: null,
  650. fromUserCount: null,
  651. toUserCount: null,
  652. fromUserNum: null,
  653. toUserNum: null,
  654. },
  655. // 表单参数
  656. form: {},
  657. //详情
  658. formDetails:{},
  659. // 表单校验
  660. rules: {
  661. chatType: [
  662. { required: true, message: "群发任务的类型,默认为single,表示发送给客户,group表示发送给客户群不能为空", trigger: "change" }
  663. ],
  664. userIdsSelectList: [
  665. { required: true, message: "发送企业群发消息的成员账号不能为空", trigger: "blur" }
  666. ],
  667. allowSelect: [
  668. { required: true, message: "是否允许成员在待发送客户列表中重新进行选择,默认为true", trigger: "blur" }
  669. ],
  670. textContent:[
  671. { required: true, message: "消息文本不能为空噢", trigger: "blur" }
  672. ],
  673. createName:[
  674. { required: true, message: "创建人不能为空", trigger: "blur" }
  675. ]
  676. },
  677. //日期快捷选择
  678. pickerOptions: {
  679. shortcuts: [
  680. {
  681. text: '最近三天',
  682. onClick(picker) {
  683. const end = new Date();
  684. const start = new Date();
  685. start.setTime(start.getTime() - 3600 * 1000 * 24 * 3);
  686. picker.$emit('pick', [start, end]);
  687. }
  688. },{
  689. text: '最近一周',
  690. onClick(picker) {
  691. const end = new Date();
  692. const start = new Date();
  693. start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
  694. picker.$emit('pick', [start, end]);
  695. }
  696. }, {
  697. text: '最近一个月',
  698. onClick(picker) {
  699. const end = new Date();
  700. const start = new Date();
  701. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
  702. picker.$emit('pick', [start, end]);
  703. }
  704. }, {
  705. text: '最近三个月',
  706. onClick(picker) {
  707. const end = new Date();
  708. const start = new Date();
  709. start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
  710. picker.$emit('pick', [start, end]);
  711. }
  712. }]
  713. },
  714. };
  715. },
  716. created() {
  717. getMyQwCompanyList().then(response => {
  718. this.myQwCompanyList = response.data;
  719. if(this.myQwCompanyList!=null){
  720. this.queryParams.corpId=this.myQwCompanyList[0].dictValue;
  721. this.getList();
  722. }
  723. });
  724. //全部客户还是部分客户
  725. this.getDicts("sys_qw_groupMsg_type").then(response => {
  726. this.groupMsgTypeOptions = response.data;
  727. });
  728. //文本类型字典(复用)
  729. this.getDicts("sys_qw_welcome_type").then(response => {
  730. this.msgTypeOptions = response.data;
  731. });
  732. this.getDicts("sys_qw_group_msg_chat_type").then(response => {
  733. this.groupMsgChatType = response.data;
  734. });
  735. //发送类型
  736. this.getDicts("sys_qw_group_msg_timer_type").then(response => {
  737. this.groupMsgTimerType = response.data;
  738. });
  739. //客户性别
  740. this.getDicts("sys_qw_external_contact_gender").then(response => {
  741. this.sysUserSex = response.data;
  742. // 要添加的新对象数据
  743. let newUserData = {
  744. dictValue: "99",
  745. dictLabel: '全部',
  746. };
  747. // 添加对象到数组
  748. this.sysUserSex.push(newUserData);
  749. });
  750. //是否允许成员在待发送列表中再次选择
  751. this.getDicts("sys_qw_allow_select").then(response => {
  752. this.allowSelectOptions = response.data;
  753. });
  754. },
  755. watch:{
  756. // 监听 userSelectList 的变化,并同步更新 form.userIdsSelectList
  757. userSelectList(newList) {
  758. this.form.userIdsSelectList = newList.map(item => item.qwUserId);
  759. },
  760. groupChatList(newList){
  761. this.form.groupChatSelectList=newList.map(item=>item.chatId)
  762. },
  763. },
  764. methods: {
  765. updateCorpId(){
  766. this.getList();
  767. },
  768. //关闭弹窗-清空页面
  769. closeData(){
  770. this.reset();
  771. },
  772. /** 查询客户群发记录主列表 */
  773. getList() {
  774. this.loading = true;
  775. listGroupMsg(this.queryParams).then(response => {
  776. this.groupMsgList = response.rows;
  777. this.total = response.total;
  778. this.loading = false;
  779. });
  780. },
  781. // 取消按钮
  782. cancel() {
  783. this.open = false;
  784. this.reset();
  785. },
  786. //标签的选择
  787. tagSelection(row){
  788. row.isSelected= !row.isSelected;
  789. this.$forceUpdate();
  790. },
  791. /** 提醒成员群发 */
  792. triggerRemindGroupMsg(row){
  793. this.queryParams.qwMsgId=row.msgId
  794. remindGroupMsg(this.queryParams).then(res=>{
  795. if (res.code==200){
  796. if (res.data.errcode==0){
  797. return this.msgSuccess("提醒成员群发成功")
  798. }else if (res.data.errcode==41094){
  799. return this.msgWarning("此条记录的每日提醒次数超过限制了噢")
  800. }else {
  801. return this.msgError(res.data.errmsg)
  802. }
  803. }else {
  804. return this.msgError(res.msg)
  805. }
  806. })
  807. },
  808. handleSearchTags(name){
  809. searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
  810. this.tagGroupList = response.rows;
  811. });
  812. },
  813. cancelSearchTags(){
  814. this.afreshData()
  815. },
  816. //清除点我查看
  817. clearExpectCountCustomer(){
  818. //选择全部客户的统计
  819. this.expectCountCustomer=null;
  820. //选择部分客户的统计
  821. this.expectCountGroupChat=null;
  822. },
  823. //查看预计接收人数
  824. viewReceiveNum(){
  825. if (this.userSelectList.length==0){
  826. return this.msgError("请选择群发成员账号");
  827. }else {
  828. this.form.corpId=this.queryParams.corpId;
  829. selectCountCustomer(this.form).then(res=>{
  830. this.expectCountCustomer=res.data;
  831. })
  832. }
  833. },
  834. //查看部分客户预计接收人数
  835. viewReceiveGroupChatNum(){
  836. if (this.userSelectList.length==0){
  837. return this.msgError("请选择群发成员账号");
  838. }else {
  839. // 使用 map 方法和解构赋值提取每个子数组的第一个元素
  840. // 选择的标签
  841. if (this.tagsIdsChangeSelectList!=null){
  842. this.form.tagsIdsSelectList=this.tagsIdsChangeSelectList.map(item => item.tagId);
  843. }
  844. //排除的标签
  845. if (this.outTagsIdsChangeSelectList!=null){
  846. this.form.outTagsIdsSelectList = this.outTagsIdsChangeSelectList.map(item => item.tagId);
  847. }
  848. this.form.corpId=this.queryParams.corpId;
  849. selectCountCustomer(this.form).then(res=>{
  850. this.expectCountGroupChat=res.data;
  851. })
  852. }
  853. },
  854. //选择的成员账号列表
  855. selectUserList(list){
  856. this.listUser.open=false;
  857. //用于显示
  858. this.userSelectList=list;
  859. // //用于查询
  860. // this.form.userIdsSelectList= this.userSelectList.map(item => item.id);
  861. },
  862. //选择的部分客户时,选择的群聊里的
  863. selectGroupChatList(list){
  864. this.groupChart.open=false;
  865. //用于显示
  866. this.groupChatList=list;
  867. // //用于查询
  868. // this.form.groupChatSelectList=this.groupChatList.map(item=>item.chatId);
  869. },
  870. //确定选择标签
  871. tagSubmitForm(type){
  872. //制空选项
  873. // for (let i = 0; i < this.tagGroupList.length; i++) {
  874. // for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  875. // this.tagGroupList[i].tag[x].isSelected=false;
  876. // }
  877. // }
  878. if (type==1){
  879. for (let i = 0; i < this.tagGroupList.length; i++) {
  880. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  881. if (this.tagGroupList[i].tag[x].isSelected === true) {
  882. if (!this.tagsIdsChangeSelectList) {
  883. this.tagsIdsChangeSelectList = [];
  884. }
  885. // 检查当前 tag 是否已经存在于 tagListFormIndex[index] 中
  886. let tagExists = this.tagsIdsChangeSelectList.some(
  887. tag => tag.id === this.tagGroupList[i].tag[x].id
  888. );
  889. // 如果 tag 不存在于 tagListFormIndex[index] 中,则新增
  890. if (!tagExists) {
  891. this.tagsIdsChangeSelectList.push(this.tagGroupList[i].tag[x]);
  892. }
  893. }
  894. }
  895. }
  896. if (!this.tagsIdsChangeSelectList || this.tagsIdsChangeSelectList.length === 0) {
  897. return this.$message('请选择标签');
  898. }
  899. }else if (type==2){
  900. for (let i = 0; i < this.tagGroupList.length; i++) {
  901. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  902. if (this.tagGroupList[i].tag[x].isSelected === true) {
  903. if (!this.outTagsIdsChangeSelectList) {
  904. this.outTagsIdsChangeSelectList = [];
  905. }
  906. // 检查当前 tag 是否已经存在于 tagListFormIndex[index] 中
  907. let tagExists = this.outTagsIdsChangeSelectList.some(
  908. tag => tag.id === this.tagGroupList[i].tag[x].id
  909. );
  910. // 如果 tag 不存在于 tagListFormIndex[index] 中,则新增
  911. if (!tagExists) {
  912. this.outTagsIdsChangeSelectList.push(this.tagGroupList[i].tag[x]);
  913. }
  914. }
  915. }
  916. }
  917. if (!this.outTagsIdsChangeSelectList || this.outTagsIdsChangeSelectList.length === 0) {
  918. return this.$message('请选择标签');
  919. }
  920. }
  921. this.changeTagDialog.open = false;
  922. },
  923. //取消选择标签
  924. tagCancel(){
  925. this.changeTagDialog.open = false;
  926. },
  927. // //选择的标签
  928. // selectTagsList(list,type){
  929. //
  930. // const result = list.flatMap(item => {
  931. // return item.tag.map(tag => [tag.tagId, tag.name]);
  932. // });
  933. //
  934. // //获取到选择的标签列表
  935. // const uniqueResult = Array.from(new Set(result.map(JSON.stringify)), JSON.parse);
  936. // this.changeTagDialog.open=false
  937. //
  938. // if (type==1){
  939. // this.tagsIdsChangeSelectList=uniqueResult;
  940. // }else if (type==2){
  941. // this.outTagsIdsChangeSelectList=uniqueResult;
  942. // }
  943. //
  944. // },
  945. //删除一些选择了的账号
  946. handleClosegroupUser(list){
  947. // 假设 list 对象具有一个 id 属性
  948. const index = this.userSelectList.findIndex(t => t.id === list.id);
  949. if (index !== -1) {
  950. this.userSelectList.splice(index, 1);
  951. }
  952. //表单同时清除
  953. // this.form.userIdsSelectList= this.userSelectList.map(item => item.id);
  954. },
  955. //删除一些选择了的群聊
  956. handleClosegroupChat(list){
  957. // 假设 list 对象具有一个 id 属性
  958. const index = this.groupChatList.findIndex(t => t.chatId === list.chatId);
  959. if (index !== -1) {
  960. this.groupChatList.splice(index, 1);
  961. }
  962. // //表单同时清除
  963. // this.form.groupChatSelectList=this.groupChatList.map(item=>item.chatId);
  964. },
  965. //删除一些选择的标签
  966. handleCloseTags(list){
  967. // 假设 list 对象具有一个 id 属性
  968. const ls = this.tagsIdsChangeSelectList.findIndex(t => t.tagId === list.tagId);
  969. if (ls !== -1) {
  970. this.tagsIdsChangeSelectList.splice(ls, 1);
  971. this.tagsIdsChangeSelectList = [...this.tagsIdsChangeSelectList];
  972. }
  973. },
  974. //删除一些排除的标签
  975. handleCloseOutTags(list){
  976. // const index = this.outTagsIdsChangeSelectList.findIndex(t => t[0] === tag[0]);
  977. // if (index !== -1) {
  978. // this.outTagsIdsChangeSelectList.splice(index, 1);
  979. // }
  980. // 假设 list 对象具有一个 id 属性
  981. const ls = this.outTagsIdsChangeSelectList.findIndex(t => t.tagId === list.tagId);
  982. if (ls !== -1) {
  983. this.outTagsIdsChangeSelectList.splice(ls, 1);
  984. this.outTagsIdsChangeSelectList = [...this.outTagsIdsChangeSelectList];
  985. }
  986. },
  987. //选择群发的企业成员账号
  988. handlelistUser(){
  989. console.log("imageArr",this.imageArr)
  990. this.listUser.title="选择企业成员"
  991. this.listUser.open=true;
  992. setTimeout(() => {
  993. this.$refs.qwUserList.getDetails(this.queryParams.corpId)
  994. }, 200);
  995. //预计人数制空
  996. this.expectCountCustomer=null;
  997. },
  998. //选择群聊
  999. handleGroupChatList(){
  1000. this.groupChart.title="选择所在群聊里的客户"
  1001. this.groupChart.open=true;
  1002. setTimeout(() => {
  1003. this.$refs.GroupChat.getDetailsList(this.queryParams.corpId)
  1004. }, 200);
  1005. //预计人数制空
  1006. this.expectCountGroupChat=null;
  1007. },
  1008. //选择标签
  1009. hangleChangeTags(){
  1010. this.changeTagDialog.title="选择标签"
  1011. this.changeTagDialog.open=true;
  1012. this.changeTagDialog.type=1;
  1013. // 获取 tagListFormIndex 中的所有 tagId,用于快速查找
  1014. const selectedTagIds = new Set(this.tagsIdsChangeSelectList.map(tagItem => tagItem.tagId));
  1015. for (let i = 0; i < this.tagGroupList.length; i++) {
  1016. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  1017. this.tagGroupList[i].tag[x].isSelected = selectedTagIds.has(this.tagGroupList[i].tag[x].tagId);
  1018. }
  1019. }
  1020. // setTimeout(() => {
  1021. // this.$refs.TagGroupList.getTagGroupList(this.queryParams.corpId)
  1022. // }, 200);
  1023. //预计人数制空
  1024. this.expectCountGroupChat=null;
  1025. },
  1026. //选择排除标签
  1027. hangleChangeOutTags(){
  1028. this.changeTagDialog.title="选择排除的标签"
  1029. this.changeTagDialog.open=true;
  1030. this.changeTagDialog.type=2;
  1031. // 获取 tagListFormIndex 中的所有 tagId,用于快速查找
  1032. const selectedTagIds = new Set(this.outTagsIdsChangeSelectList.map(tagItem => tagItem.tagId));
  1033. for (let i = 0; i < this.tagGroupList.length; i++) {
  1034. for (let x = 0; x < this.tagGroupList[i].tag.length; x++) {
  1035. this.tagGroupList[i].tag[x].isSelected = selectedTagIds.has(this.tagGroupList[i].tag[x].tagId);
  1036. }
  1037. }
  1038. // setTimeout(() => {
  1039. // this.$refs.TagGroupList.getTagGroupList(this.queryParams.corpId)
  1040. // }, 200);
  1041. //
  1042. //预计人数制空
  1043. this.expectCountGroupChat=null;
  1044. },
  1045. // 表单重置
  1046. reset() {
  1047. this.form = {
  1048. id: null,
  1049. chatType: "single",
  1050. sender: null,
  1051. gender:"99",
  1052. allowSelect: "Y",
  1053. textContent: null,
  1054. msgid: null,
  1055. corpId: null,
  1056. companyId: null,
  1057. tagNames: null,
  1058. groupChatNamesList: [],
  1059. fromUserCount: null,
  1060. toUserCount: null,
  1061. fromUserNum: null,
  1062. toUserNum: null,
  1063. createTime: null,
  1064. updateTime: null,
  1065. msgType:null,
  1066. mediaId: null,
  1067. mediaPicUrl: null,
  1068. title: null,
  1069. picurl: null,
  1070. description: null,
  1071. url: null,
  1072. miniprogramTitle: null,
  1073. miniprogramPicMediaId: null,
  1074. miniprogramPicUrl: null,
  1075. miniprogramAppid: null,
  1076. miniprogramPage: null,
  1077. fileMediaId: null,
  1078. fileUrl: null,
  1079. videoMediaId: null,
  1080. videoUrl: null,
  1081. //选择的成员账号
  1082. userIdsSelectList:[],
  1083. //选择的群聊
  1084. groupChatSelectList:[],
  1085. //选择的时间
  1086. timeScreenCharge:[],
  1087. //全部客户还是部分客户
  1088. selectType:'1',
  1089. //选择的标签列表
  1090. tagsIdsSelectList:[],
  1091. //排除的标签
  1092. outTagsIdsSelectList:[],
  1093. };
  1094. this.userSelectList=[];
  1095. this.expectCountCustomer=null;
  1096. this.groupChatList=[];
  1097. this.tagsIdsChangeSelectList=[];
  1098. this.outTagsIdsChangeSelectList=[];
  1099. this.expectCountGroupChat=[];
  1100. this.resetForm("form");
  1101. },
  1102. /** 搜索按钮操作 */
  1103. handleQuery() {
  1104. this.queryParams.pageNum = 1;
  1105. this.getList();
  1106. },
  1107. hangdleDitels(row){
  1108. this.reset();
  1109. const id = row.id || this.ids
  1110. getGroupMsg(id).then(response => {
  1111. this.formDetails = response.data;
  1112. this.detailsDialog.open = true;
  1113. this.detailsDialog.title = "客户群发记录详情";
  1114. });
  1115. },
  1116. /** 重置按钮操作 */
  1117. resetQuery() {
  1118. this.resetForm("queryForm");
  1119. this.handleQuery();
  1120. },
  1121. // 多选框选中数据
  1122. handleSelectionChange(selection) {
  1123. this.ids = selection.map(item => item.id)
  1124. this.single = selection.length!==1
  1125. this.multiple = !selection.length
  1126. },
  1127. /** 新增按钮操作 */
  1128. handleAdd() {
  1129. this.reset();
  1130. this.open = true;
  1131. this.form.msgType="1"
  1132. this.title = "新建群发";
  1133. this.afreshData();
  1134. // //所有的标签组
  1135. // allListTagGroup({corpId:this.queryParams.corpId}).then(response => {
  1136. // this.tagGroupList = response.rows;
  1137. // });
  1138. //
  1139. // //所有的标签
  1140. // listTag({corpId:this.queryParams.corpId}).then(response => {
  1141. // this.tagList = response.rows;
  1142. // });
  1143. },
  1144. /**
  1145. * 重新获取 部分数据
  1146. */
  1147. afreshData(){
  1148. //所有的标签组
  1149. allListTagGroup({corpId:this.queryParams.corpId}).then(response => {
  1150. this.tagGroupList = response.rows;
  1151. });
  1152. //所有的标签
  1153. listTag({corpId:this.queryParams.corpId}).then(response => {
  1154. this.tagList = response.rows;
  1155. });
  1156. },
  1157. /** 获取企业员工列表 */
  1158. // getUserList(){
  1159. // //获取企业员工
  1160. // listUser(this.queryParams).then(response => {
  1161. // this.userList = response.rows;
  1162. // this.total = response.total;
  1163. // this.loading = false;
  1164. // });
  1165. // },
  1166. /** 修改按钮操作 */
  1167. handleUpdate(row) {
  1168. this.reset();
  1169. const id = row.id || this.ids
  1170. getGroupMsg(id).then(response => {
  1171. this.form = response.data;
  1172. this.open = true;
  1173. this.title = "修改客户群发记录主";
  1174. });
  1175. },
  1176. openImageViewer(url) {
  1177. // 打开大图预览对话框
  1178. this.dialogImageUrl=url
  1179. this.dialogVisible = true;
  1180. },
  1181. /** 提交按钮 */
  1182. async submitForm() {
  1183. // 选择的标签
  1184. if (this.tagsIdsChangeSelectList!=null){
  1185. this.form.tagsIdsSelectList=this.tagsIdsChangeSelectList.map(item => item.tagId);
  1186. }
  1187. //排除的标签
  1188. if (this.outTagsIdsChangeSelectList!=null){
  1189. this.form.outTagsIdsSelectList = this.outTagsIdsChangeSelectList.map(item => item.tagId);
  1190. }
  1191. this.form.corpId=this.queryParams.corpId;
  1192. try {
  1193. // 验证子组件表单
  1194. await this.$refs.WelComeAdd.validateChildForm();
  1195. // 父组件表单验证逻辑
  1196. await this.$refs["form"].validate(valid => {
  1197. if (valid) {
  1198. if (this.form.id != null) {
  1199. return this.msgError("没有修改选项");
  1200. } else {
  1201. this.loading=true;
  1202. Object.assign(this.form, this.$refs.WelComeAdd.form);
  1203. this.form.chatType="single";
  1204. addGroupMsg(this.form).then(response => {
  1205. this.msgSuccess("创建成功");
  1206. this.open = false;
  1207. this.loading = false;
  1208. this.getList();
  1209. }).catch(error => {
  1210. this.open=true;
  1211. this.loading = false;
  1212. }).finally(
  1213. () => {
  1214. this.$refs["form"].resetFields();
  1215. this.$refs.WelComeAdd.reset();
  1216. this.userSelectList=[];
  1217. this.reset();
  1218. }
  1219. );
  1220. }
  1221. }
  1222. });
  1223. } catch (error) {
  1224. console.error('表单编辑群发信息验证不用过:', error.message);
  1225. }
  1226. },
  1227. /** 删除按钮操作 */
  1228. handleDelete(row) {
  1229. const ids = row.id || this.ids;
  1230. this.$confirm('是否确认删除客户群发记录主编号为"' + ids + '"的数据项?', "警告", {
  1231. confirmButtonText: "确定",
  1232. cancelButtonText: "取消",
  1233. type: "warning"
  1234. }).then(function() {
  1235. return delGroupMsg(ids);
  1236. }).then(() => {
  1237. this.getList();
  1238. this.msgSuccess("删除成功");
  1239. }).catch(() => {});
  1240. },
  1241. }
  1242. };
  1243. </script>
  1244. <style scoped>
  1245. .user-box {
  1246. width: 50px; /* 盒子宽度 */
  1247. height: 30px; /* 盒子高度 */
  1248. padding: 5px 10px; /* 内边距 */
  1249. border: 1px solid #d5d1d1;/* 边框 */
  1250. margin: 3px; /* 外边距 */
  1251. background-color: #f9f9f9;/* 背景颜色 */
  1252. color: #333; /* 文本颜色 */
  1253. font-size: 14px; /* 字体大小 */
  1254. text-align: center; /* 文本居中 */
  1255. }
  1256. .elFormItemClass{
  1257. margin: 20px 0px
  1258. }
  1259. .message-stayle{
  1260. display: flex;
  1261. justify-content: normal;
  1262. align-items: center;
  1263. margin-top: 10px;
  1264. }
  1265. .message-stayle .el-link {
  1266. white-space: normal; /* 允许换行 */
  1267. word-break: break-all; /* 单词中间断行 */
  1268. overflow-wrap: break-word; /* 允许在单词内换行 */
  1269. }
  1270. .message-stayle span {
  1271. word-break: break-all;
  1272. }
  1273. .container {
  1274. position: relative; /* 使 phone div 的 absolute 定位基于这个容器 */
  1275. width: 100%;
  1276. height: 100%;
  1277. }
  1278. .phone {
  1279. position: absolute; /* 定位到容器内 */
  1280. top: 5%;
  1281. left: 50%;
  1282. transform: translateX(-50%);
  1283. width: 100%;
  1284. max-width: 375px;
  1285. height: 100%;
  1286. max-height: 90%;
  1287. border: 8px solid #ccc;
  1288. border-radius: 36px;
  1289. box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  1290. background-color: #fff;
  1291. overflow: hidden;
  1292. }
  1293. .phone::before {
  1294. content: '';
  1295. position: absolute;
  1296. top: 0;
  1297. left: 50%;
  1298. width: 60px;
  1299. height: 5px;
  1300. background-color: #ccc;
  1301. border-radius: 10px;
  1302. transform: translateX(-50%);
  1303. }
  1304. .chat-interface {
  1305. display: flex;
  1306. flex-direction: column;
  1307. height: 100%;
  1308. background-color: #fff;
  1309. }
  1310. .header {
  1311. display: flex;
  1312. justify-content: space-between;
  1313. align-items: center;
  1314. height: 50px;
  1315. padding: 0 15px;
  1316. background-color: #fff;
  1317. border-bottom: 1px solid #e0e0e0;
  1318. }
  1319. .header .back,
  1320. .header .menu {
  1321. height: 25px;
  1322. width: 25px;
  1323. }
  1324. .header .title{
  1325. font-size: 16px;
  1326. margin: auto;
  1327. }
  1328. .message-area {
  1329. flex: 1;
  1330. background-color: rgb(240, 242, 245);
  1331. padding: 10px;
  1332. overflow-y: auto;
  1333. }
  1334. .footer {
  1335. display: flex;
  1336. align-items: center;
  1337. padding: 10px;
  1338. background-color: #fff;
  1339. border-top: 1px solid #e0e0e0;
  1340. }
  1341. .footer .voice-button,
  1342. .footer .emoji-button,
  1343. .footer .add-button {
  1344. width: 25px;
  1345. height: 25px;
  1346. border: none;
  1347. cursor: pointer;
  1348. flex-shrink: 0; /* 不允许缩小 */
  1349. }
  1350. .footer .emoji-button,
  1351. .footer .add-button {
  1352. margin: 0px 5px;
  1353. }
  1354. .footer .input-box {
  1355. flex: 1;
  1356. border: 1px solid #e0e0e0;
  1357. margin-left: 5px;
  1358. }
  1359. .text-container {
  1360. max-height: 7.5em; /* 设置最大高度为6行,根据字体大小调整 */
  1361. overflow-y: auto; /* 内容超出时显示滚动条 */
  1362. line-height: 1.5em; /* 行高设置,确保每行高度一致 */
  1363. }
  1364. .el-form-item {
  1365. margin-bottom: 30px;
  1366. }
  1367. .custom-span {
  1368. display: block; /* 确保元素是块级元素 */
  1369. height: 110px; /* 设置固定高度 */
  1370. overflow-y: auto; /* 超出高度时显示滚动条 */
  1371. word-wrap: break-word; /* 自动换行 */
  1372. word-break: break-all; /* 在必要时进行换行 */
  1373. }
  1374. .custom-span-description{
  1375. display: block; /* 确保元素是块级元素 */
  1376. height: 110px; /* 设置固定高度 */
  1377. overflow-y: auto; /* 超出高度时显示滚动条 */
  1378. word-wrap: break-word; /* 自动换行 */
  1379. word-break: break-all; /* 在必要时进行换行 */
  1380. }
  1381. .custom-span-title {
  1382. display: block; /* 确保元素是块级元素 */
  1383. height: 45px; /* 设置固定高度 */
  1384. overflow-y: auto; /* 超出高度时显示滚动条 */
  1385. word-wrap: break-word; /* 自动换行 */
  1386. word-break: break-all; /* 在必要时进行换行 */
  1387. }
  1388. /* CSS 样式 */
  1389. .tag-container {
  1390. display: flex;
  1391. flex-wrap: wrap; /* 超出宽度时自动换行 */
  1392. gap: 8px; /* 设置标签之间的间距 */
  1393. }
  1394. .name-background {
  1395. display: inline-block;
  1396. background-color: #abece6; /* 背景颜色 */
  1397. padding: 4px 8px; /* 调整内边距,让背景包裹文字 */
  1398. border-radius: 4px; /* 可选:设置圆角 */
  1399. }
  1400. .tag-box {
  1401. padding: 8px 12px;
  1402. border: 1px solid #989797;
  1403. border-radius: 4px;
  1404. cursor: pointer;
  1405. display: inline-block;
  1406. }
  1407. .tag-selected {
  1408. background-color: #00bc98;
  1409. color: #fff;
  1410. border-color: #00bc98;
  1411. }
  1412. .el-tag + .el-tag {
  1413. margin-left: 10px;
  1414. }
  1415. .button-new-tag {
  1416. margin-left: 10px;
  1417. height: 32px;
  1418. line-height: 30px;
  1419. padding-top: 0;
  1420. padding-bottom: 0;
  1421. }
  1422. .input-new-tag {
  1423. width: 90px;
  1424. margin-left: 10px;
  1425. vertical-align: bottom;
  1426. }
  1427. .text-container {
  1428. max-height: 5em; /* 设置最大高度为6行,根据字体大小调整 */
  1429. overflow-y: auto; /* 内容超出时显示滚动条 */
  1430. line-height: 1.5em; /* 行高设置,确保每行高度一致 */
  1431. }
  1432. </style>