You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

471 lines
14 KiB

5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
  1. <template>
  2. <div>
  3. <div class="container">
  4. <div class="item">
  5. <div class="left">短信模板名称</div>
  6. <div style="width: 70%;">
  7. <el-select v-model="smsTemplatesSelectValue" placeholder="请选择短信模板" style="width:500px;" @change="smsTemplateSelectChangeMethod">
  8. <el-option v-for="item in smsTemplatesOptions" :key="item.id" :label="item.title" :value="item">
  9. </el-option>
  10. </el-select>
  11. </div>
  12. </div>
  13. <div class="item">
  14. <div class="left">签名名称</div>
  15. <div style="width: 70%;">
  16. <el-select v-model="smsSignsSelectValue" placeholder="请选择签名" style="width:500px;">
  17. <el-option v-for="item in smsSignsOptions" :key="item.id" :label="item.text" :value="item.text">
  18. </el-option>
  19. </el-select>
  20. </div>
  21. </div>
  22. <div class="item">
  23. <div class="left">短信预览</div>
  24. <div style="width: 70%;">
  25. <el-input type="textarea" :rows="5" placeholder="请输入内容" v-model="finallyShowContent" style="width:500px;" disabled>
  26. </el-input><br />
  27. <p class="explain">当前发送内容{{smsTemplatesSelectValue.text?smsPreview?smsPreview.length:smsTemplatesSelectValue.text.length:0}}个字预计发送条数约为
  28. {{smsTemplatesSelectValue.text?Math.ceil(smsPreview?smsPreview.length/67:smsTemplatesSelectValue.text.length/67):0}}条短信</p>
  29. <p class="example">实际发送时如有模板变量会影响计费条数请特别关注</p>
  30. <p style="font-size: 16px;">短信计费的条数计费规则请参考 <a href="https://cloud.tencent.com/document/product/382/18058#.E7.9F.AD.E4.BF.A1.E5.86.85.E5.AE.B9.E9.95.BF.E5.BA.A6.E8.AE.A1.E7.AE.97.E8.A7.84.E5.88.99"
  31. target="_blank" style="color:#00a4ff">国内短信内容长度计算规则</a> <a href="https://cloud.tencent.com/document/product/382/18052#.E5.9B.BD.E9.99.85.E7.9F.AD.E4.BF.A1.E5.86.85.E5.AE.B9.E9.95.BF.E5.BA.A6.E8.AE.A1.E7.AE.97.E8.A7.84.E5.88.99"
  32. target="_blank" style="color:#00a4ff">国际/港澳台短信内容长度计算规则</a></p>
  33. </div>
  34. </div>
  35. <div class="item">
  36. <div class="left">短信模板参数</div>
  37. <div style="width: 70%;">
  38. <el-input type="textarea" :rows="5" placeholder="请输入内容" v-model="templateParams" style="width:500px;" @change="smsPreviewMethod">
  39. </el-input>
  40. <p class="explain">多个参数之间用英文逗号(<span style="color:#e54545">,</span>)隔开例如</p>
  41. <p class="example auto-typing">xx公司,xx元,xx服务器</p>
  42. </div>
  43. </div>
  44. <div class="item">
  45. <div class="left">发送对象</div>
  46. <div style="width: 70%;">
  47. <el-input type="textarea" :rows="5" placeholder="请输入内容" v-model="mobilesStr" style="width:500px;">
  48. </el-input>
  49. <p class="explain">发送的对象不能超过<span style="color:#e54545">10</span>,多个手机号码之间用英文逗号(<span style="color:#e54545">,</span>)隔开例如</p>
  50. <p class="example auto-typing ">135xxxxxxxx,138xxxxxxxx,159xxxxxxxx</p>
  51. </div>
  52. </div>
  53. <div class="item">
  54. <div class="left">用户是否需要回复该短信</div>
  55. <div style="width: 70%;">
  56. <el-radio v-model="userNeedReplySmsRadio" label="0">不需要</el-radio>
  57. <el-radio v-model="userNeedReplySmsRadio" label="1">需要</el-radio>
  58. </div>
  59. </div>
  60. <div class="item" v-if="userNeedReplySmsRadio==='1'">
  61. <div class="left">回复截至天数</div>
  62. <div style="width: 20%;">
  63. <el-input placeholder="请输入天数" v-model="replyEndDay">
  64. <template slot="append">天内</template>
  65. </el-input>
  66. </div>
  67. </div>
  68. </div>
  69. <div style="display:flex; flex-direction:row-reverse">
  70. <el-button @click="handleCancel" style="margin-left:30px;"> </el-button>
  71. <el-button type="primary" @click="sendSmsMethod" v-loading="showSendDialogVisibleLoading"> </el-button>
  72. </div>
  73. <el-dialog title="发送结果" :append-to-body='true' :visible.sync="sendResultVisible" width="30%" :close-on-click-modal="false">
  74. <el-table :data="sendResult" style="width: 100%">
  75. <el-table-column prop="username" label="用户" width="180">
  76. </el-table-column>
  77. <el-table-column prop="mobile" label="手机号" width="180">
  78. </el-table-column>
  79. <el-table-column prop="" label="状态">
  80. <template slot-scope="scope">
  81. <div style="display:flex;align-items: center;">
  82. <el-tag type="success" v-if="scope.row.sendStatus=='0'">成功</el-tag>
  83. <el-tag type="info" v-if="scope.row.sendStatus=='1'">待审核</el-tag>
  84. <el-tag type="danger" v-if="scope.row.sendStatus=='2'">失败</el-tag>
  85. <el-tag type="danger" v-if="scope.row.sendStatus=='3'">发送中</el-tag>
  86. <el-tag type="danger" v-if="scope.row.sendStatus=='4'">结束</el-tag>
  87. </div>
  88. </template>
  89. </el-table-column>
  90. </el-table>
  91. </el-dialog>
  92. </div>
  93. </template>
  94. <script>
  95. import util from '@/common/js/util'; //全局公共库
  96. import Sticky from '@/components/Sticky' // 粘性header组件
  97. import {
  98. mapGetters
  99. } from 'vuex';
  100. import {
  101. listUser
  102. } from '@/api/mdp/sys/user';
  103. import {
  104. listSmsTemplate
  105. } from '@/api/mdp/sms/smsTemplate';
  106. import {
  107. groupSendSmsApi,
  108. listSmsSign
  109. } from '@/api/mdp/sms/smsSign';
  110. export default {
  111. computed: {
  112. ...mapGetters([
  113. 'userInfo'
  114. ])
  115. },
  116. props: ['visible', 'smsBodyParams','smsUserList','loadPhonenoByUserid'],
  117. watch: {
  118. 'visible': function(visible) {
  119. if (visible == true) {
  120. this.getMobilesStr();
  121. this.getSmsTemplates();
  122. this.getSmsSigns();
  123. if(this.smsBodyParams){
  124. this.templateParams=this.smsBodyParams.join(",");
  125. }
  126. }
  127. }
  128. },
  129. data() {
  130. return {
  131. sendResultVisible: false,
  132. sendResult: [],
  133. replyEndDay: '',
  134. userNeedReplySmsRadio: '0',
  135. activeName: 'first',
  136. showSendDialogVisibleLoading: false,
  137. finallyShowContent: '',
  138. smsPreview: '',
  139. templateParams: '',
  140. mobilesStr: '',
  141. smsSignsSelectValue: '',
  142. smsTemplatesSelectValue: '',
  143. smsSignsOptions: [],
  144. smsTemplatesOptions: [],
  145. selectShopVisible: false,
  146. shopId: '',
  147. locationId: '',
  148. branchId: '',
  149. sendSmsVisible: false,
  150. textarea: '',
  151. value: '',
  152. form: {
  153. name: '',
  154. region: '',
  155. date1: '',
  156. date2: '',
  157. delivery: false,
  158. type: [],
  159. resource: '',
  160. desc: ''
  161. }
  162. };
  163. },
  164. methods: {
  165. //展示选择门店的方法
  166. showSelectShopMethod() {
  167. this.selectShopVisible = true;
  168. },
  169. sureMethod(row) {
  170. this.selectShopVisible = false;
  171. this.branchId = row.branchId;
  172. this.shopId = row.shopId;
  173. this.locationId = row.id;
  174. this.getSmsTemplates();
  175. },
  176. showSendDialogVisibleMethod() {
  177. this.shopId = this.userInfo.shopId;
  178. this.locationId = this.userInfo.locationId;
  179. this.branchId = this.userInfo.branchId;
  180. this.sendSmsVisible = true;
  181. //获取短信签名
  182. this.getSmsSigns();
  183. //this.sendSmsVisible=!this.sendSmsVisible;
  184. },
  185. handleCancel:function(){
  186. this.$emit('cancel');
  187. },
  188. sendSmsMethod() {
  189. let that = this;
  190. if (!this.smsTemplatesSelectValue) {
  191. this.$notify({position:'bottom-left',showClose: true,
  192. message: "请选择某个模板",
  193. type: 'error'
  194. });
  195. return;
  196. }
  197. if (!this.smsSignsSelectValue) {
  198. this.$notify({position:'bottom-left',showClose: true,
  199. message: "请选择某个签名",
  200. type: 'error'
  201. });
  202. return;
  203. }
  204. if (!this.mobilesStr) {
  205. this.$notify({position:'bottom-left',showClose: true,
  206. message: "发送对象不能为空",
  207. type: 'error'
  208. });
  209. return;
  210. }
  211. /* var mobilesStr = '';
  212. for (let i = 0; i < this.sels.length; i++) {
  213. if (i != 0) {
  214. mobilesStr = mobilesStr + "," + this.sels[i].phoneno;
  215. } else {
  216. mobilesStr += this.sels[i].phoneno;
  217. }
  218. } */
  219. var mobileArr = this.mobilesStr.split(",");
  220. if (mobileArr.length > 10) {
  221. this.$notify({position:'bottom-left',showClose: true,
  222. message: "发送的对象不能超过10个",
  223. type: 'error'
  224. });
  225. return;
  226. }
  227. for (let i = 0; i < mobileArr.length; i++) {
  228. if (!/^[1](([3][0-9])|([4][5-9])|([5][0-3,5-9])|([6][5,6])|([7][0-8])|([8][0-9])|([9][1,8,9]))[0-9]{8}$/.test(
  229. mobileArr[i])) {
  230. this.$notify({position:'bottom-left',showClose: true,
  231. message: mobileArr[i] + "手机号码不对",
  232. type: 'error'
  233. });
  234. return;
  235. }
  236. if (this.mobilesStr.lastIndexOf(mobileArr[i]) != this.mobilesStr.indexOf(mobileArr[i])) {
  237. this.$notify({position:'bottom-left',showClose: true,
  238. message: "请填写不同的手机号码进行发送",
  239. type: 'error'
  240. });
  241. return;
  242. }
  243. }
  244. var templateParamsArr = this.templateParams.split(",");
  245. //统计短信模板变量出现的次数
  246. var reg = /\{\d\}/;
  247. let smsTemplateVariableCount = this.smsTemplatesSelectValue.text.split(reg).length - 1;
  248. if (templateParamsArr.length != smsTemplateVariableCount) {
  249. this.$notify({position:'bottom-left',showClose: true,
  250. message: "输入的短信模板参数与短信模板的变量的数目不一致",
  251. type: 'error'
  252. });
  253. return;
  254. }
  255. if (this.userNeedReplySmsRadio === '1' && !this.replyEndDay) {
  256. this.$notify({position:'bottom-left',showClose: true,
  257. message: "如果勾选需要用户回复,必须填写天数",
  258. type: 'error'
  259. });
  260. return;
  261. }
  262. if (this.userNeedReplySmsRadio === '1' && !/^\d+$/.test(this.replyEndDay)) {
  263. this.$notify({position:'bottom-left',showClose: true,
  264. message: "天数必须是正整数",
  265. type: 'error'
  266. });
  267. return;
  268. }
  269. let params = {
  270. "smsTemplateParams": this.templateParams,
  271. "mobiles": this.mobilesStr,
  272. "smsSign": this.smsSignsSelectValue,
  273. "smsTemplateId": this.smsTemplatesSelectValue.id,
  274. "smsTtemplateText": this.smsTemplatesSelectValue.text,
  275. "nationCode": "86",
  276. "userid": this.userInfo.userid,
  277. "branchId": this.smsTemplatesSelectValue.branchId,
  278. "shopId": this.smsTemplatesSelectValue.shopId,
  279. "locationId": this.smsTemplatesSelectValue.locationId,
  280. "replyEndDay": this.replyEndDay,
  281. "userNeedReplySms": this.userNeedReplySmsRadio
  282. };
  283. this.showSendDialogVisibleLoading = true;
  284. that.sendResult = [];
  285. groupSendSmsApi(params).then((res) => {
  286. this.showSendDialogVisibleLoading = false;
  287. var tips = res.data.tips;
  288. if (tips.isOk) {
  289. for (let i = 0; i < res.data.data.length; i++) {
  290. for (let j = 0; j < that.sels.length; j++) {
  291. if (res.data.data[i].mobile == that.sels[j].phoneno) {
  292. res.data.data[i].username = that.sels[j].username
  293. }
  294. }
  295. }
  296. this.sendResultVisible = true;
  297. that.sendResult = res.data.data;
  298. };
  299. this.$notify({position:'bottom-left',showClose: true,
  300. message: tips.msg,
  301. type: tips.isOk ? 'success' : 'error'
  302. });
  303. }).catch(err => {
  304. this.sendSmsVisible = false
  305. });
  306. },
  307. //查询短信模板
  308. getSmsTemplates() {
  309. let params = {
  310. "shopId": this.userInfo.shopId,
  311. "locationId": this.userInfo.locationId,
  312. "branchId": this.userInfo.branchId,
  313. "status": "0"
  314. };
  315. this.finallyShowContent = '';
  316. this.smsPreview = '';
  317. this.smsTemplatesSelectValue = '';
  318. this.smsTemplatesOptions = [];
  319. listSmsTemplate(params).then((res) => {
  320. var tips = res.data.tips;
  321. if (tips.isOk) {
  322. this.smsTemplatesOptions = res.data.data;
  323. } else {
  324. this.$notify({position:'bottom-left',showClose: true,
  325. message: tips.msg,
  326. type: 'error'
  327. });
  328. }
  329. }).catch();
  330. },
  331. //查询短信签名
  332. getSmsSigns() {
  333. let params = {
  334. "status": "0",
  335. "shopId": this.userInfo.shopId
  336. };
  337. this.smsSignsOptions = [];
  338. listSmsSign(params).then((res) => {
  339. var tips = res.data.tips;
  340. if (tips.isOk) {
  341. this.smsSignsOptions = res.data.data;
  342. } else {
  343. this.$notify({position:'bottom-left',showClose: true,
  344. message: tips.msg,
  345. type: 'error'
  346. });
  347. }
  348. }).catch();
  349. },
  350. smsTemplateSelectChangeMethod() {
  351. this.finallyShowContent = this.smsTemplatesSelectValue.text;
  352. },
  353. //短信预览的方法
  354. smsPreviewMethod(value) {
  355. //求出模板中的变量的数量
  356. var reg = /\{\d\}/;
  357. this.smsPreview = '';
  358. if (!this.smsTemplatesSelectValue.text) {
  359. return;
  360. }
  361. this.finallyShowContent = this.smsTemplatesSelectValue.text;
  362. let smsTemplateVariableCount = this.smsTemplatesSelectValue.text.split(reg).length - 1;
  363. let valueArr = value.split(",");
  364. let finallyStr = this.smsTemplatesSelectValue.text;
  365. for (let i = 0; i < smsTemplateVariableCount; i++) {
  366. if (i < valueArr.length) {
  367. let k = i + 1;
  368. var regex = new RegExp('\\{' + k + '\\}');
  369. finallyStr = finallyStr.replace(regex, valueArr[i])
  370. }
  371. };
  372. this.smsPreview = finallyStr;
  373. this.finallyShowContent = this.smsPreview;
  374. },
  375. getMobilesStr(){
  376. this.mobilesStr = '';
  377. if(this.loadPhonenoByUserid==true){
  378. let userids=this.smsUserList.map(user=>user.userid);
  379. listUser({userids:userids,branchId:this.userInfo.branchId}).then(res=>{
  380. if(res.data.tips.isOk){
  381. let users=res.data.data;
  382. let phonenoList=users.map(user=>user.phoneno);
  383. this.mobilesStr=phonenoList.join(",");
  384. }
  385. });
  386. }else{
  387. let phonenoList=this.smsUserList.map(user=>user.phoneno);
  388. this.mobilesStr=phonenoList.join(",");
  389. }
  390. },
  391. //初始化数据
  392. initData() {
  393. this.templateParams = '',
  394. this.mobilesStr = '';
  395. this.smsTemplatesSelectValue = '';
  396. this.smsSignsSelectValue = '';
  397. }
  398. },
  399. components: {
  400. },
  401. mounted() {
  402. this.$nextTick(() => {
  403. this.getSmsTemplates();
  404. this.getSmsSigns();
  405. this.getMobilesStr();
  406. if(this.smsBodyParams){
  407. this.templateParams=this.smsBodyParams.join(",");
  408. }
  409. });
  410. }
  411. }
  412. </script>
  413. <style>
  414. .container {
  415. display: flex;
  416. flex-direction: column;
  417. width: 80%;
  418. margin: 0 auto;
  419. }
  420. .item {
  421. display: flex;
  422. flex-direction: row;
  423. align-items: center;
  424. margin-bottom: 30px;
  425. }
  426. .item .left {
  427. width: 200px;
  428. font-size: 20px;
  429. color: #888;
  430. padding-right: 60px;
  431. align-self: flex-start;
  432. margin-top: 10px;
  433. }
  434. .item .explain {
  435. font-size: 16px;
  436. width: 500px;
  437. }
  438. .item .example {
  439. font-size: 16px;
  440. color: #e54545
  441. }
  442. .auto-typing {
  443. font-weight: bold;
  444. overflow: hidden;
  445. width: 53ch;
  446. border-right: 1px solid transparent;
  447. white-space: nowrap;
  448. animation: typing 5s steps(53) 5s forwards;
  449. }
  450. @keyframes typing {
  451. from {
  452. width: 0;
  453. }
  454. }
  455. </style>