Browse Source

feat: 企微助手 - 群活码 - 新建页面&选择群聊组件&新建接口联调

zhengxy 2 years ago
parent
commit
010451937e

+ 4 - 0
project/src/assets/config/interface_api.js

@@ -182,6 +182,10 @@ var api = {
182 182
   channel_trend_staffList: '/api/sq/staffList',
183 183
 
184 184
   groupCode_ruleList: '/api/qrcodeChatGroup/ruleList',
185
+  groupCode_setRule: '/api/qrcodeChatGroup/setRule',
186
+  groupCode_editRule: '/api/qrcodeChatGroup/editRule',
187
+  groupCode_ruleDetail: '/api/qrcodeChatGroup/ruleDetail',
188
+  groupCode_chatGroupList: '/api/chatGroup/chatGroupList',
185 189
 
186 190
   radar_addGroup: '/api/radar/radarGroupCreate',
187 191
   radar_groupList: '/api/radar/radarGroupList',

+ 390 - 0
project/src/components/groupCode/components/chatGroupOptions.vue

@@ -0,0 +1,390 @@
1
+<template>
2
+  <div class="common-screen-item">
3
+    <el-popover append-to-body placement="bottom" trigger="click" v-model="dialogVisible">
4
+      <div
5
+        slot="reference"
6
+        :style="width ? 'width:' + width : ''"
7
+        :class="['common-screen-self-box', 'common-input-select', chatListResult.length ? 'common-input-select-hover' : '']"
8
+      >
9
+        <div :class="['common-screen-self-con', chatListResult.length ? '' : 'common-screen-self-placeholder']">
10
+          <div class="common-screen-self-con-div">
11
+            <span v-if="chatListResult.length">{{ chatListResultName }}</span>
12
+            <span v-else>请选择群聊</span>
13
+          </div>
14
+        </div>
15
+        <div class="common-screen-self-icon"><i class="el-icon-arrow-down" /></div>
16
+      </div>
17
+
18
+      <div class="flex" style="padding:10px" v-loading="loading">
19
+        <div class="propoverItem">
20
+          <self-input :reset="reset" :hasLabel="false" label_name="群名称" width="270px" style="margin-top: 0;" @inputChange="onChangeKeyword" />
21
+          <div class="allMember">全部群聊({{ chatList && chatList.length }}):</div>
22
+          <div class="memberBoxBig self-scrollbar-3">
23
+            <div class="memberBox" v-for="(item, idx) in chatList" :key="item.chat_id">
24
+              <div class="meberList">
25
+                <div class="memberItem" @click="handleSwitchChatItem(item, idx)">
26
+                  <div class="flex" style="flex:1">
27
+                    <i class="el-icon-chat-dot-round chat-icon" />
28
+                    <div class="memberInfo">
29
+                      <div class="name">{{ item.name }}</div>
30
+                      <!-- <div class="other">公告:{{ item.notice }}</div> -->
31
+                    </div>
32
+                  </div>
33
+                  <div :class="['checkbox', item.isSelected ? 'checkbox_active' : '']">
34
+                    <i class="el-icon-check" />
35
+                  </div>
36
+                </div>
37
+              </div>
38
+            </div>
39
+          </div>
40
+        </div>
41
+
42
+        <div class="line" />
43
+
44
+        <div class="propoverItem" style="padding-left:20px">
45
+          <div class="title">已选择的群聊</div>
46
+          <div class="choice_result_top">
47
+            <div class="clear" @click="handleDelAllSelectedChat">全部清空</div>
48
+            <div class="result_num">已选择<span>{{ chatListSelected.length }}</span>个群</div>
49
+          </div>
50
+          <div class="member_result self-scrollbar-3">
51
+            <div class="memberItem" v-for="(item, idx) in chatListSelected" :key="item.chat_id">
52
+              <div class="flex" style="flex:1">
53
+                <i class="el-icon-chat-dot-round chat-icon" />
54
+                <div class="memberInfo">
55
+                  <div class="name">{{ item.name }}</div>
56
+                  <!-- <div class="other">公告:{{ item.notice }}</div> -->
57
+                </div>
58
+              </div>
59
+              <i class="el-icon-close" style="margin-left:10px" @click="handleDelSelectedChat(idx)" />
60
+            </div>
61
+          </div>
62
+          <div class="buttons">
63
+            <el-button type="primary" plain size="mini" @click="dialogVisible = false">取消</el-button>
64
+            <el-button type="primary" size="mini" @click="onClickConfirm">确定</el-button>
65
+          </div>
66
+        </div>
67
+      </div>
68
+    </el-popover>
69
+  </div>
70
+</template>
71
+
72
+<script>
73
+import _lodash from 'lodash'
74
+import selfInput from '@/components/assembly/screen/input.vue'
75
+export default {
76
+  name: "chatGroupOptions",
77
+  components: {
78
+    selfInput,
79
+  },
80
+  props: {
81
+    width: {
82
+      type: String,
83
+      default: () => ''
84
+    },
85
+    chatListResult: { // 最终确认选择的群列表
86
+      type: Array,
87
+      default: () => []
88
+    },
89
+  },
90
+  data() {
91
+    return {
92
+      reset: false,
93
+      loading: false,
94
+      dialogVisible: false, // 控制弹框显示
95
+      keyword: '',
96
+      chatList: [], // 可选择客户群列表
97
+      chatListSelected: [], // 已选择的群列表
98
+    }
99
+  },
100
+  computed: {
101
+    chatListResultName() {
102
+      const arr = this.chatListResult.map(c => c.name)
103
+      return arr.join(',')
104
+    },
105
+  },
106
+  watch: {
107
+    dialogVisible(isShow) {
108
+      if (isShow) {
109
+        this.handleGetChatList()
110
+      } else { // 清空搜索关键字
111
+        this.keyword = ''
112
+        this.reset = !this.reset
113
+      }
114
+    },
115
+  },
116
+  methods: {
117
+    // 获取"可选择客户群列表"
118
+    async handleGetChatList() {
119
+      console.log('handleGetChatList => ', )
120
+      try {
121
+        this.loading = true
122
+        this.chatList = []
123
+        const { data: res = {} } = await this.$axios.get(this.URL.BASEURL + this.URL.groupCode_chatGroupList, {
124
+          params: { keyword: this.keyword }
125
+        })
126
+        if (res && res.errno == 0) {
127
+          this.chatList = res.rst.map(item => ({
128
+            ...item,
129
+            isSelected: false
130
+          }))
131
+
132
+          // 如果父组件已有选择的结果 => 根据"最终确认选择的群列表"获取"已选列表"
133
+          if (this.chatListResult.length) {
134
+            this.handleGetChatListSelected()
135
+          }
136
+          // 根据"已选列表" => 回显"可选列表"的已选状态
137
+          this.handleGetIsSelectedChatStatus()
138
+        } else if (res.errno != 4002) {
139
+          this.$message.warning(res.err)
140
+        }
141
+      } catch (error) {
142
+        console.log('error => ', error)
143
+      } finally {
144
+        this.loading = false
145
+      }
146
+    },
147
+    onChangeKeyword(val) {
148
+      this.keyword = val
149
+      this.handleGetChatList()
150
+    },
151
+    // 取消可选列表中所有的已选状态
152
+    handleCloseAllChatList() {
153
+      this.chatList.forEach(c => {
154
+        c.isSelected = false
155
+      })
156
+    },
157
+    // 根据"最终确认选择的群列表"获取"已选列表"
158
+    handleGetChatListSelected() {
159
+      this.chatListResult.forEach(item => {
160
+        const isFound = this.chatList.find(c => c.chat_id === item.chat_id)
161
+        if (isFound) {
162
+          const isHas = this.chatListSelected.find(c => c.chat_id === isFound.chat_id)
163
+          !isHas && this.chatListSelected.push(isFound)
164
+        }
165
+      })
166
+    },
167
+    // 根据"已选列表" => 回显"可选列表"的已选状态
168
+    handleGetIsSelectedChatStatus() {
169
+      this.handleCloseAllChatList()
170
+      this.chatListSelected.forEach(item => {
171
+        // 查找当前已选的索引
172
+        const idx = this.chatList.findIndex(chat => chat.chat_id === item.chat_id)
173
+        if (idx !== -1) this.chatList[idx].isSelected = true
174
+      })
175
+    },
176
+    // 监听点击"可选列表 - 项" => 切换已选状态
177
+    handleSwitchChatItem(currentChat, currentIdx) {
178
+      if (currentChat.isSelected) {
179
+        // 已选 => 取消 & 从 chatListSelected 列表中移除
180
+        this.chatList[currentIdx].isSelected = false
181
+        const delIdx = this.chatListSelected.findIndex(chat => chat.chat_id === currentChat.chat_id)
182
+        if (delIdx !== -1) this.chatListSelected.splice(delIdx, 1)
183
+      } else {
184
+        // 未选 => 选择 & 添加到 chatListSelected 列表
185
+        this.chatList[currentIdx].isSelected = true
186
+        this.chatListSelected = [...this.chatListSelected, currentChat]
187
+      }
188
+    },
189
+    // 监听点击"已选列表 - 项" => 删除 & 回显"可选列表"的已选状态
190
+    handleDelSelectedChat(currentDelIdx) {
191
+      this.chatListSelected.splice(currentDelIdx, 1)
192
+      this.handleGetIsSelectedChatStatus()
193
+    },
194
+    // 监听点击"全部清空" => 删除全部 & 回显"可选列表"的已选状态
195
+    handleDelAllSelectedChat() {
196
+      this.chatListSelected = []
197
+      this.handleGetIsSelectedChatStatus()
198
+    },
199
+    // 监听点击"确定"
200
+    onClickConfirm() {
201
+      if (!this.chatListSelected.length) {
202
+        this.$message.warning('请选择群聊')
203
+        return
204
+      }
205
+      this.$emit('change', _lodash.cloneDeep(this.chatListSelected))
206
+      this.dialogVisible = false
207
+    },
208
+  },
209
+};
210
+</script>
211
+
212
+<style lang="scss" scoped>
213
+.propoverItem {
214
+  width: 300px;
215
+  flex: 1;
216
+  height: 100%;
217
+
218
+  .allMember {
219
+    color: #666666;
220
+    font-size: 14px;
221
+    line-height: 20px;
222
+    margin-top: 17px;
223
+  }
224
+
225
+  .title {
226
+    color: #383e47;
227
+    font-size: 14px;
228
+    line-height: 20px;
229
+    font-weight: bold;
230
+  }
231
+
232
+  .choice_result_top {
233
+    display: flex;
234
+    align-items: center;
235
+    justify-content: space-between;
236
+    margin: 7px 0;
237
+
238
+    .clear {
239
+      color: #00b38a;
240
+      font-size: 13px;
241
+      line-height: 18px;
242
+      cursor: pointer;
243
+      font-weight: bold;
244
+    }
245
+
246
+    .result_num {
247
+      color: #333333;
248
+      font-size: 13px;
249
+      line-height: 18px;
250
+
251
+      span {
252
+        color: #00b38a;
253
+        font-weight: bold;
254
+      }
255
+    }
256
+  }
257
+
258
+  .member_result {
259
+    height: 380px;
260
+    overflow-y: auto;
261
+    padding-right: 15px;
262
+    .memberItem {
263
+      margin: 20px 0;
264
+    }
265
+  }
266
+}
267
+
268
+.line {
269
+  width: 0.5px;
270
+  background: #c3cbd6;
271
+}
272
+
273
+.propoverItem,
274
+.line {
275
+  height: 478px;
276
+}
277
+
278
+.memberBoxBig {
279
+  height: 400px;
280
+  overflow-y: auto;
281
+}
282
+
283
+.memberBox {
284
+  display: flex;
285
+  margin-top: 10px;
286
+
287
+  .el-icon-caret-bottom {
288
+    color: #46a7ff;
289
+    cursor: pointer;
290
+    margin-right: 7px;
291
+    margin-top: 2px;
292
+    transition: all 0.3s;
293
+    display: block;
294
+    height: 14px;
295
+  }
296
+
297
+  .meberList {
298
+    flex: 1;
299
+    margin-right: 15px;
300
+
301
+    .department {
302
+      i {
303
+        color: #46a7ff;
304
+      }
305
+
306
+      span {
307
+        color: #383e47;
308
+        font-size: 14px;
309
+        line-height: 20px;
310
+        margin-left: 5px;
311
+        font-weight: bold;
312
+      }
313
+    }
314
+
315
+    .checkbox {
316
+      width: 15px;
317
+      height: 15px;
318
+      border: 1px solid #979797;
319
+      border-radius: 50%;
320
+      display: flex;
321
+      align-items: center;
322
+      justify-content: center;
323
+      font-size: 12px;
324
+      margin-left: 10px;
325
+
326
+      i {
327
+        color: transparent;
328
+      }
329
+
330
+      &.checkbox_active {
331
+        i {
332
+          color: #ffffff;
333
+        }
334
+
335
+        background: #00b38a;
336
+        border-color: #00b38a;
337
+      }
338
+    }
339
+  }
340
+}
341
+
342
+.memberItem,
343
+.department {
344
+  display: flex;
345
+  align-items: center;
346
+  justify-content: space-between;
347
+  cursor: pointer;
348
+}
349
+
350
+.memberItem {
351
+  margin: 4px 0;
352
+
353
+  .memberImg {
354
+    width: 38px;
355
+    height: 38px;
356
+    border-radius: 4px;
357
+  }
358
+
359
+  .chat-icon {
360
+    font-size: 26px;
361
+  }
362
+
363
+  .memberInfo {
364
+    margin-left: 7px;
365
+    flex: 1;
366
+
367
+    .name {
368
+      color: #333333;
369
+      font-size: 13px;
370
+      line-height: 18px;
371
+    }
372
+
373
+    .other {
374
+      color: #898d92;
375
+      font-size: 12px;
376
+      line-height: 18px;
377
+    }
378
+  }
379
+}
380
+
381
+.reversalAnimation {
382
+  transform: rotate(-90deg);
383
+}
384
+
385
+.buttons {
386
+  text-align: right;
387
+  padding: 20px 0 10px;
388
+}
389
+</style>
390
+

+ 429 - 7
project/src/components/groupCode/createGroupCode.vue

@@ -1,18 +1,349 @@
1 1
 <template>
2
-  <div>
3
-    新建群活码
2
+  <div class="create-wrap">
3
+    <!-- S 返回 -->
4
+    <div class="backBox" @click="$router.go(-1)">
5
+      <div class="back">
6
+        <i class="el-icon-back" />
7
+        <span>返回</span>
8
+      </div>
9
+    </div>
10
+    <!-- E 返回 -->
11
+    <!-- S 表单内容 -->
12
+    <div v-loading="loading" class="bg-ffffff createMassMsg" style="padding: 15px 30px;">
13
+      <!-- S 基础信息 -->
14
+      <h3 class="bigTitle">基础信息</h3>
15
+      <div class="regulations">
16
+        <label><em>*</em>渠道名称</label>
17
+        <el-input
18
+          v-model.trim="groupForm.name"
19
+          placeholder="请输入渠道名称"
20
+          style="width:300px"
21
+          maxlength="32"
22
+          size="small"
23
+          show-word-limit
24
+          clearable
25
+        />
26
+      </div>
27
+      <div class="regulations" style="align-items: center">
28
+        <label><em style="opacity: 0;">*</em>选择分组</label>
29
+        <el-select
30
+          v-model="groupForm.group_id"
31
+          size="small"
32
+          clearable
33
+          filterable
34
+          placeholder="请选择分组"
35
+          style="width: 300px"
36
+        >
37
+          <el-option v-for="item in groupOptions" :key="item.id" :label="item.name" :value="item.id" />
38
+        </el-select>
39
+        <div class="newGroupCss" @click="$refs.dialogGroupRef.dialogVisible = true">新建分组</div>
40
+      </div>
41
+      <div class="regulations">
42
+        <label><em>*</em>选择群聊</label>
43
+        <chatGroupOptions
44
+          ref="chatGroupOptions"
45
+          style="margin: 0;"
46
+          width="300px"
47
+          :chatListResult="groupForm.chat_id_list"
48
+          @change="onChangeChatGroup"
49
+        />
50
+      </div>
51
+      <div class="regulations">
52
+        <label><em style="opacity: 0;">*</em>进群方式</label>
53
+        <el-radio-group v-model="groupForm.join_type">
54
+          <el-radio :label="1">顺序进群</el-radio>
55
+          <el-radio :label="2">随机进群</el-radio>
56
+        </el-radio-group>
57
+      </div>
58
+      <div class="regulations" style="align-items: center">
59
+        <label>渠道群管理</label>
60
+        <div @click="handleShowLimitTips" class="limitBox">
61
+          <el-switch
62
+            v-model="groupForm.is_limit"
63
+            :disabled="!groupForm.chat_id_list.length"
64
+            active-color="#13ce66"
65
+            inactive-color="#ddd"
66
+            :active-value="1"
67
+            :inactive-value="0"
68
+            @change="onChangeSwitchLimit"
69
+          />
70
+        </div>
71
+      </div>
72
+      <div v-show="groupForm.is_limit" class="listBox">
73
+        <el-table border :data="groupForm.chat_id_list" tooltip-effect="dark" :header-cell-style="()=>{return { backgroundColor: '#f9f9f9 !important' }}" style="width: 100%">
74
+          <el-table-column label="群名称" align="center" prop="name" />
75
+          <el-table-column label="人数上限" align="center">
76
+            <template slot="header" slot-scope="scope">
77
+              <em style="color: #ff0000;">*</em>人数上限
78
+            </template>
79
+            <template slot-scope="{ row }">
80
+              <el-input size="mini" v-model="row.user_limit" />
81
+            </template>
82
+          </el-table-column>
83
+          <el-table-column label="状态" align="center">
84
+            <template slot-scope="{ row }">
85
+              <el-switch
86
+                v-model="row.status"
87
+                :active-value="1"
88
+                :inactive-value="0"
89
+                active-color="#13ce66"
90
+                inactive-color="#ddd"
91
+              />
92
+            </template>
93
+          </el-table-column>
94
+          <el-table-column label="操作" align="center" width="80px">
95
+            <template slot-scope="{ row, $index }">
96
+              <div class="c-00B38A pointer lMar8" @click="onClickDelChat(row, $index)">删除</div>
97
+            </template>
98
+          </el-table-column>
99
+        </el-table>
100
+      </div>
101
+      <!-- E 基础信息 -->
102
+
103
+      <!-- S 客服设置 -->
104
+      <div class="line" style="margin-top:20px"></div>
105
+      <h3 class="bigTitle">客服设置</h3>
106
+      <div class="regulations" style="align-items: center">
107
+        <label><em>*</em>生效成员</label>
108
+        <self-customerservice
109
+          title=''
110
+          width="300px"
111
+          source="channelCode"
112
+          ref="selfKefu"
113
+          style="margin:0;"
114
+          :afferent_users="groupForm.user_list"
115
+          @customerDefine="onChangeUserList"
116
+        />
117
+        <div class="user-tips">当客户点击客服时,会引导客户随机添加一名客服成员的企业微信</div>
118
+      </div>
119
+      <div class="regulations">
120
+        <label><em>*</em>引导话术</label>
121
+        <el-input
122
+          v-model.trim="groupForm.leading_words"
123
+          placeholder="请输入引导话术"
124
+          style="width:300px"
125
+          maxlength="20"
126
+          size="small"
127
+          show-word-limit
128
+          clearable
129
+        />
130
+      </div>
131
+      <!-- E 客服设置 -->
132
+
133
+
134
+      <!-- S 按钮 -->
135
+      <div class="line" style="margin-top:20px" />
136
+      <div style="margin-top: 20px"><el-button type="primary" @click="onClickSave">保存</el-button></div>
137
+      <!-- E 按钮 -->
138
+    </div>
139
+    <!-- E 表单内容 -->
140
+
141
+    <!-- S 新建分组 - 弹框 -->
142
+    <dialogGroup
143
+      ref="dialogGroupRef"
144
+      :propsData="{ dialogTitle:'新建' }"
145
+      @init="handleGetGroupOptions"
146
+    />
147
+    <!-- E 新建分组 - 弹框 -->
4 148
   </div>
5 149
 </template>
6 150
 
7 151
 <script>
152
+import dialogGroup from './components/dialogGroup.vue'
153
+import chatGroupOptions from './components/chatGroupOptions.vue'
154
+import selfCustomerservice from '@/components/assembly/screen/customerService.vue'
155
+import Sortable from 'sortablejs'
156
+
8 157
 export default {
9 158
   name: "createGroupCode",
10
-  components: {},
159
+  components: {
160
+    dialogGroup,
161
+    chatGroupOptions,
162
+    selfCustomerservice,
163
+  },
11 164
   data() {
12
-    return {}
165
+    return {
166
+      loading: false,
167
+      groupOptions: [], // 分组选项
168
+      groupForm: {
169
+        name: '', // 渠道名称
170
+        group_id: '', // 分组id
171
+        chat_id_list: [], // 客户群列表
172
+        join_type: 1, // 进群方式
173
+        is_limit: 0, // 渠道群管理(是否设置群上限)
174
+        user_list: [], // 客服(生效成员) 数组回显 'a,b' => ['a', 'b']
175
+        leading_words: '', // 引导话术
176
+      }
177
+    }
178
+  },
179
+  computed: {
180
+    isEdit() {
181
+      const { id = '', type = '' } = this.$route.query
182
+      return id && type === 'edit'
183
+    },
184
+    isCopy() {
185
+      const { id = '', type = '' } = this.$route.query
186
+      return id && type === 'copy'
187
+    },
188
+  },
189
+  created() {
190
+    // 获取分组列表
191
+    this.handleGetGroupOptions()
192
+  },
193
+  mounted() {
194
+    // 表格行拖拽
195
+	  this.handleRowDrop()
196
+  },
197
+  methods: {
198
+    // 注册表格行拖拽事件
199
+    handleRowDrop() {
200
+      const tbody = document.querySelector('.el-table__body-wrapper tbody')
201
+      const _this = this
202
+      Sortable.create(tbody, {
203
+        onEnd({ newIndex, oldIndex }) {
204
+          if (newIndex == oldIndex) return
205
+          _this.groupForm.chat_id_list.splice(
206
+            newIndex,
207
+            0,
208
+            _this.groupForm.chat_id_list.splice(oldIndex, 1)[0]
209
+          )
210
+          const newArray = _this.groupForm.chat_id_list.slice(0)
211
+          _this.groupForm.chat_id_list = []
212
+          _this.$nextTick(() => {
213
+            _this.groupForm.chat_id_list = newArray
214
+            _this.$refs.chatGroupOptions.chatListSelected = [] // 重置群聊组件"已选列表"
215
+          })
216
+        }
217
+      })
218
+    },
219
+    // 点击保存按钮
220
+    async onClickSave() {
221
+      console.log('onClickSave this.groupForm => ', JSON.parse(JSON.stringify(this.groupForm)))
222
+      try {
223
+        // 表单判空校验
224
+        await this.handleFormValidate()
225
+        // 获取请求地址 & 参数
226
+        const { url, params } = this.handleGetParams()
227
+
228
+        console.log('params => ', JSON.parse(JSON.stringify(params)))
229
+        console.log('url => ', url)
230
+
231
+        this.loading = true
232
+        const { data: res } = await this.$axios.post(url, params)
233
+        console.log('res => ', res)
234
+        if (res && res.errno == 0) {
235
+          this.$message.success('保存成功')
236
+          this.$router.go(-1)
237
+        } else if (res.errno != 4002) {
238
+          this.$message.warning(res.err || '操作失败')
239
+        }
240
+      } catch (error) {
241
+        console.log('error => ', error)
242
+      } finally {
243
+        this.loading = false
244
+      }
245
+    },
246
+    // 表单校验
247
+    handleFormValidate() {
248
+      const { name, chat_id_list, is_limit, user_list, leading_words } = this.groupForm
249
+      const isEmpty = chat_id_list.some(chat => Number(chat.user_limit) === 0)
250
+      return new Promise((resolve, reject) => {
251
+        if (!name) {
252
+          this.$message.warning('请输入渠道名称')
253
+          reject('表单校验未通过')
254
+        } else if (!chat_id_list.length) {
255
+          this.$message.warning('请选择群聊')
256
+          reject('表单校验未通过')
257
+        } else if (is_limit === 1 && isEmpty) {
258
+          this.$message.warning('请输入人数上限')
259
+          reject('表单校验未通过')
260
+        } else if (!user_list.length) {
261
+          this.$message.warning('请选择生效成员')
262
+          reject('表单校验未通过')
263
+        } else if (!leading_words) {
264
+          this.$message.warning('请输入引导话术')
265
+          reject('表单校验未通过')
266
+        } else {
267
+          resolve('表单校验通过')
268
+        }
269
+      })
270
+    },
271
+    // 整理请求参数
272
+    handleGetParams() {
273
+      const url = `${this.URL.BASEURL}${this.URL[this.isEdit ? 'groupCode_editRule' : 'groupCode_setRule']}`
274
+      const { name, group_id, join_type, is_limit, user_list, leading_words, chat_id_list } = this.groupForm
275
+      const params = {
276
+        name,
277
+        group_id,
278
+        join_type,
279
+        is_limit,
280
+        user_list: user_list.join(','),
281
+        leading_words,
282
+        chat_id_list: JSON.stringify(chat_id_list),
283
+      }
284
+
285
+      return { url, params }
286
+    },
287
+    // 获取分组列表
288
+    async handleGetGroupOptions() {
289
+      const { data: res = {} } = await this.$axios.get(this.URL.BASEURL + this.URL.channel_groupList, {
290
+        params: {
291
+          type: 2, // 1:渠道活码 2:群活码
292
+          page: 1,
293
+          pagesize: 500,
294
+        }
295
+      })
296
+      if (res && res.errno == 0) {
297
+        this.groupOptions = res.rst.data
298
+      } else if (res.errno != 4002) {
299
+        this.$message.warning(res.err)
300
+      }
301
+    },
302
+    // 渠道群管理提示
303
+    handleShowLimitTips() {
304
+      if (!this.groupForm.chat_id_list.length) {
305
+        this.$message.error('请先选择群聊')
306
+      }
307
+    },
308
+    onChangeSwitchLimit(){
309
+      if (!this.groupForm.chat_id_list.length) {
310
+        this.$message.error('请先选择群聊')
311
+        return
312
+      }
313
+    },
314
+    // 渠道群管理列表 - 删除
315
+    onClickDelChat(row, idx) {
316
+      this.groupForm.chat_id_list.splice(idx, 1)
317
+      this.$refs.chatGroupOptions.chatListSelected = [] // 重置群聊组件"已选列表"
318
+      // 列表为空 => 关闭"渠道群管理"按钮
319
+      if (!this.groupForm.chat_id_list.length) {
320
+        this.groupForm.is_limit = 0
321
+      }
322
+    },
323
+    // 监听"选择客服"(生效成员)变化
324
+    onChangeUserList(val) {
325
+      this.groupForm.user_list = Array.isArray(val) && val.length ? val : []
326
+    },
327
+    // 监听"选择群聊"变化
328
+    onChangeChatGroup(selectedChat) {
329
+      const { chat_id_list: currentChats } = this.groupForm
330
+      // 整理数据结构 => 初始化新选择的群聊数据
331
+      const newChats = selectedChat.map(s => ({
332
+        chat_id: s.chat_id,
333
+        name: s.name,
334
+        user_limit: 0,
335
+        enable: 1,
336
+        status: 1,
337
+      }))
338
+      // 在"当前页面的群聊列表"中查找是否已存在 => 去重后得到当前页面新群聊列表
339
+      newChats.forEach((newChat, idx) => {
340
+        const isFoundChat = currentChats.find(c => newChat.chat_id === c.chat_id)
341
+        if (isFoundChat) newChats.splice(idx, 1, isFoundChat)
342
+      })
343
+      this.groupForm.chat_id_list = [...newChats]
344
+      console.log('this.groupForm.chat_id_list => ', this.groupForm.chat_id_list)
345
+    },
13 346
   },
14
-  created(){},
15
-  methods:{},
16 347
 }
17 348
 </script>
18 349
 <style lang="scss">
@@ -28,7 +359,98 @@ export default {
28 359
 }
29 360
 </style>
30 361
 <style lang="scss" scoped>
31
-@import "../customOperate/create.scss";
362
+.backBox {
363
+  background: #ffffff;
364
+  padding: 15px;
365
+  margin-bottom: 10px;
366
+  .back {
367
+    font-size: 16px;
368
+    font-weight: bold;
369
+    color: #333333;
370
+    cursor: pointer;
371
+    display: inline-block;
372
+  }
373
+}
374
+.bigTitle {
375
+  color: #333333;
376
+  font-size: 16px;
377
+  line-height: 22px;
378
+  font-weight: bold;
379
+}
380
+.createMassMsg{
381
+  width: 100%;
382
+  min-height: 400px;
383
+
384
+  .line {
385
+    width: 730px;
386
+    height: 1px;
387
+    background: #e9e9e9;
388
+    margin: 40px 0 20px;
389
+  }
390
+  .regulations {
391
+    display: flex;
392
+    align-items: flex-start;
393
+    margin-top: 28px;
394
+    label {
395
+      width: 100px;
396
+      color: #333333;
397
+      font-size: 14px;
398
+      line-height: 28px;
399
+      em {
400
+        color: #ff0000;
401
+      }
402
+    }
403
+    .user-tips {
404
+      color: #AAAAAA;
405
+      font-size: 13px;
406
+      margin-left: 20px;
407
+    }
408
+  }
409
+  .regulations2 {
410
+    label {
411
+      width: 70px;
412
+      line-height: 30px;
413
+    }
414
+  }
415
+}
416
+.detail_status{
417
+  line-height: 30px;
418
+  height: 30px;
419
+  padding: 3px 10px;
420
+  border-radius: 21px;
421
+  font-size: 12px;
422
+  margin-left: 20px;
423
+}
424
+.status_wait{
425
+  background: #FFF2ED;
426
+  border: 1px solid #FF864F;
427
+  color: #FF864F;
428
+}
429
+.status_del{
430
+  background: #FFF5F5;
431
+  border: 1px solid #FF604D;
432
+  color: #FF604D;
433
+}
434
+.status_fail{
435
+  background: #F4F4F4;
436
+  border: 1px solid #ADADAD;
437
+  color: #ADADAD;
438
+}
439
+.status_ing{
440
+  background: #F4FAFF;
441
+  border: 1px solid #007AFE;
442
+  color: #007AFE;
443
+}
444
+.status_success{
445
+  background: #EEFFF3;
446
+  border: 1px solid #00B38A;
447
+  color: #00B38A;
448
+}
449
+.splitLine {
450
+  width: 100%;
451
+  height: 10px;
452
+  background: #f5f6f8;
453
+}
32 454
 .listBox{
33 455
   margin-left: 90px;
34 456
   width: 730px;