Browse Source

feat: 客户群数据 - 企微主体相关逻辑

zhengxy 11 months ago
parent
commit
bbaa90f06f

+ 17 - 0
project/src/components/assembly/screen/channel.vue

@@ -230,11 +230,28 @@ export default {
230 230
     } else if (this.type == 'groupUserStatus') { // 客户群详情-客户状态
231 231
       this.options = [...groupUserStatus]
232 232
       this.placeholderVal = '客户状态'
233
+    } else if (this.type == 'corpAll') { // 企微主体
234
+      this.getCorpAll()
235
+      this.placeholderVal = '企微主体'
233 236
     } else {
234 237
       this.init()
235 238
     }
236 239
   },
237 240
   methods: {
241
+    async getCorpAll() {
242
+      const url = `${this.URL.BASEURL}${this.URL.warn_djuserList}`
243
+      const params = {
244
+        sys_group_id: this.$cookie.getCookie('isSuperManage') == 1 ? sessionStorage.getItem('company_session_defaultCorp_level_1').toString() : '',
245
+      }
246
+      const { data: res = {} } = await this.$axios.get(url, { params })
247
+      if (res && res.errno == 0) {
248
+        this.options = Array.isArray(res.rst) ? res.rst : []
249
+        this.options.forEach(item => {
250
+          item.val = item.corp_name;
251
+          item.key = item.corpid
252
+        })
253
+      }
254
+    },
238 255
     onVisibleChange(val) {
239 256
       this.$emit('visible-change', val)
240 257
     },

+ 17 - 0
project/src/components/assembly/screen/channelMultiple.vue

@@ -210,11 +210,28 @@ export default {
210 210
     } else if (this.type == 'groupUserStatus') { // 客户群详情-客户状态
211 211
       this.options = [...groupUserStatus]
212 212
       this.placeholderVal = '客户状态'
213
+    } else if (this.type == 'corpAll') { // 企微主体
214
+      this.getCorpAll()
215
+      this.placeholderVal = '企微主体'
213 216
     } else {
214 217
       this.init()
215 218
     }
216 219
   },
217 220
   methods: {
221
+    async getCorpAll() {
222
+      const url = `${this.URL.BASEURL}${this.URL.warn_djuserList}`
223
+      const params = {
224
+        sys_group_id: this.$cookie.getCookie('isSuperManage') == 1 ? sessionStorage.getItem('company_session_defaultCorp_level_1').toString() : '',
225
+      }
226
+      const { data: res = {} } = await this.$axios.get(url, { params })
227
+      if (res && res.errno == 0) {
228
+        this.options = Array.isArray(res.rst) ? res.rst : []
229
+        this.options.forEach(item => {
230
+          item.val = item.corp_name;
231
+          item.key = item.corpid
232
+        })
233
+      }
234
+    },
218 235
     onVisibleChange(val) {
219 236
       this.$emit('visible-change', val)
220 237
     },

+ 17 - 0
project/src/components/assembly/screen/channelV2.vue

@@ -362,6 +362,20 @@ export default {
362 362
         })
363 363
       }
364 364
     },
365
+    async getCorpAll() {
366
+      const url = `${this.URL.BASEURL}${this.URL.warn_djuserList}`
367
+      const params = {
368
+        sys_group_id: this.$cookie.getCookie('isSuperManage') == 1 ? sessionStorage.getItem('company_session_defaultCorp_level_1').toString() : '',
369
+      }
370
+      const { data: res = {} } = await this.$axios.get(url, { params })
371
+      if (res && res.errno == 0) {
372
+        this.options = Array.isArray(res.rst) ? res.rst : []
373
+        this.options.forEach(item => {
374
+          item.val = item.corp_name;
375
+          item.key = item.corpid
376
+        })
377
+      }
378
+    },
365 379
     handleGetOptions() {
366 380
       if (this.type == 'assignment_status') {
367 381
         this.options = [...assignment_status]
@@ -473,6 +487,9 @@ export default {
473 487
       } else if (this.type == 'groupUserStatus') { // 客户群详情-客户状态
474 488
         this.options = [...groupUserStatus]
475 489
         this.placeholderVal = '客户状态'
490
+      } else if (this.type == 'corpAll') { // 企微主体
491
+        this.getCorpAll()
492
+        this.placeholderVal = '企微主体'
476 493
       } else {
477 494
         this.init()
478 495
       }

+ 6 - 2
project/src/components/assembly/screen/customerServiceCorpV2.vue

@@ -30,12 +30,12 @@
30 30
               <div class="memberBox" :key="index + 'userList1' + item.corpid">
31 31
                 <i :class="['el-icon-caret-bottom',item.is_open?'reversalAnimation':'']" @click="openEvent(index)"></i>
32 32
                 <div class="meberList">
33
-                  <div class="department" @click="selectUserEvent('all',index)">
33
+                  <div class="department">
34 34
                     <div class="flex" style="align-items: flex-start;">
35 35
                       <i class="el-icon-s-cooperation" style="margin-top:3px"></i>
36 36
                       <span>{{item.corp_name?item.corp_name:'主体'+(index+1)}}</span>
37 37
                     </div>
38
-                    <div :class="['checkbox',item.is_select?'checkbox_active':'']"><i class="el-icon-check"></i></div>
38
+                    <div v-if="!isDisableSelectAllCorp" :class="['checkbox',item.is_select?'checkbox_active':'']" @click="selectUserEvent('all',index)"><i class="el-icon-check"></i></div>
39 39
                   </div>
40 40
                   <div class="memberItem" :style="item.is_open?'display:none':''" v-for="(item1,user_index) in item.user_list" :key="item1.user_id+'-'+user_index" @click="selectUserEvent('user',index,user_index)">
41 41
                     <div class="flex" style="flex:1">
@@ -154,6 +154,10 @@ export default {
154 154
       type: String,
155 155
       default: () => 'operation'   // operation 客服   chatGroup 群主
156 156
     },
157
+    isDisableSelectAllCorp: { // 是否禁用全选企微按钮
158
+      type: Boolean,
159
+      default: () => false,
160
+    },
157 161
   },
158 162
   watch: {
159 163
     reset () {

+ 734 - 0
project/src/components/assembly/screen/customerServiceCorpV3.vue

@@ -0,0 +1,734 @@
1
+<template>
2
+  <div class="common-screen-item" v-loading="loading">
3
+    <label class="common-screen-label" v-if="title&&title!=''" :style="labelWidth ? 'width:' + labelWidth : ''">{{title}}</label>
4
+    <el-popover append-to-body placement="bottom" trigger="click" v-model="visible" :disabled="disabled">
5
+      <div :style="width?'width:'+width:''" :class="['common-screen-self-box',
6
+           'common-input-select',
7
+           final_result&&final_result.length!=0&&clearable&&!disabled?'common-input-select-hover':'',
8
+           disabled?'pointer-drop':'']" slot="reference">
9
+        <div :class="['common-screen-self-con',
10
+        !final_result||final_result.length==0?'common-screen-self-placeholder':'']">
11
+          <div class="common-screen-self-con-div">
12
+            <span v-if="!final_result||final_result.length==0">{{placeholder || '请选择'}}</span>
13
+            <template v-else>
14
+              <!-- <span v-for="(item,index) in final_result" :key="index">{{item.name}}{{index==final_result.length-1?'':','}}</span> -->
15
+              <span v-for="(item,idx) in rtSelectedCorpList" :key="item.corpid + '-' + idx">{{item.corp_name}}{{idx==rtSelectedCorpList.length-1?'':','}}</span>
16
+              <span v-if="rtSelectedCorpList.length && rtSelectedUserList.length">,</span>
17
+              <span v-for="(item,index) in rtSelectedUserList" :key="item.corpid + '-' + index">{{item.user_name}}{{index==rtSelectedUserList.length-1?'':','}}</span>
18
+            </template>
19
+          </div>
20
+          <i class="el-icon-circle-close other-icon" @click.stop="clear"></i>
21
+        </div>
22
+        <div class="common-screen-self-icon" :style="!icon_arrow_bg?'background: none;border: none;color:#c2c6cd':''">
23
+          <i class="el-icon-arrow-down"></i>
24
+        </div>
25
+      </div>
26
+      <div class="flex" style="padding:10px">
27
+        <div class="propoverItem">
28
+          <selfInput :reset='resetFlag' :hasLabel="false" :inputFlag='true' @inputChange='(val)=>{input_keyword = val;userSearch()}' width="270px" style="margin-top:0;margin-bottom:4px" :label_name="source == 'chatGroup' ? '企微主体或群主昵称' : '企微主体或成员昵称'" />
29
+            <div style="font-size:12px;color:#f9a527;">添加 空格 可进行多成员搜索</div>
30
+          <div class="allMember">全部企微主体({{corpTotal}}):</div>
31
+          <div class="memberBoxBig self-scrollbar-3">
32
+            <template v-for="(item,index) in userList">
33
+              <div class="memberBox" :key="index + 'userList1' + item.corpid">
34
+                <i :class="['el-icon-caret-bottom',item.is_open?'reversalAnimation':'']" @click="openEvent(index)"></i>
35
+                <div class="meberList">
36
+                  <div class="department">
37
+                    <div class="flex" style="align-items: flex-start;">
38
+                      <i class="el-icon-s-cooperation" style="margin-top:3px"></i>
39
+                      <span>{{item.corp_name?item.corp_name:'主体'+(index+1)}}</span>
40
+                    </div>
41
+                    <div v-if="!input_keyword" :class="['checkbox',item.is_select?'checkbox_active':'']" @click="selectUserEvent('all',index)"><i class="el-icon-check"></i></div>
42
+                  </div>
43
+                  <div class="memberItem" :style="item.is_open?'display:none':''" v-for="(item1,user_index) in item.user_list" :key="item1.user_id+'-'+user_index" @click="selectUserEvent('user',index,user_index)">
44
+                    <div class="flex" style="flex:1">
45
+                      <img class="memberImg" :src="item1.avatar" alt="">
46
+                      <div class="memberInfo">
47
+                        <div class="name">
48
+                          {{item1.name}}
49
+                          <span :class="['status-tag', item1.is_active == 0 ? 'disabled' : '']">{{ item1.is_active == 1 ? '已激活' : '未激活' }}</span>
50
+                        </div>
51
+                        <div class="other">部门:{{ item1.corp_name }}</div>
52
+                        <div v-if="item1.active_desc === '即将过期'" class="other">
53
+                          <span>{{ item1.active_desc }}</span>
54
+                          <span v-if="item1.expire_time">({{ item1.expire_time.slice(0, 10) }})</span>
55
+                        </div>
56
+                      </div>
57
+                    </div>
58
+                    <div :class="['checkbox',item1.is_select?'checkbox_active':'']"><i class="el-icon-check"></i></div>
59
+                  </div>
60
+                </div>
61
+              </div>
62
+            </template>
63
+          </div>
64
+        </div>
65
+        <div class="line"></div>
66
+        <div class="propoverItem" style="padding-left:20px">
67
+          <div class="title">已选择的{{source == 'chatGroup' ? '群主' : '成员'}}</div>
68
+          <div class="choice_result_top">
69
+            <div class="clear" @click="closeUser(-1)">全部清空</div>
70
+            <div class="result_num">已选择<span>{{rtSelectedCorpList&&rtSelectedCorpList.length}}</span>个主体和<span>{{rtSelectedUserList&&rtSelectedUserList.length}}</span>名{{source == 'chatGroup' ? '群主' : '成员'}}</div>
71
+          </div>
72
+          <div class="member_result self-scrollbar-3">
73
+
74
+            <!-- <div v-for='(corp, corpIdx) in selectedCorpList' :key="corp.corpid">
75
+              <div class="corp-wrap">
76
+                <div class="corp-info">
77
+                  <i class="el-icon-s-cooperation c-46a7ff"></i>
78
+                  <span>{{corp.corp_name}}</span>
79
+                </div>
80
+                <i class="el-icon-close pointer" @click="onClickDelSelectedCorp(corp)"></i>
81
+              </div>
82
+
83
+              <div class="memberItem" v-for="(item,index) in corp.user_list" :key="item.user_id">
84
+                <div class="flex" style="flex:1">
85
+                  <img class="memberImg" :src="item.avatar" alt="">
86
+                  <div class="memberInfo">
87
+                    <div class="name">
88
+                      {{item.user_name}}
89
+                      <span :class="['status-tag', item.is_active == 0 ? 'disabled' : '']">{{ item.is_active == 1 ? '已激活' : '未激活' }}</span>
90
+                    </div>
91
+                    <div class="other">部门:{{item.corp_name}}</div>
92
+                    <div v-if="item.active_desc === '即将过期'" class="other">
93
+                      <span>{{ item.active_desc }}</span>
94
+                      <span v-if="item.expire_time">({{ item.expire_time.slice(0, 10) }})</span>
95
+                    </div>
96
+                  </div>
97
+                </div>
98
+                <i class="el-icon-close" style="margin-left:10px" @click="closeUser(item)"></i>
99
+              </div>
100
+            </div> -->
101
+
102
+            <!-- S 全选企微数据 -->
103
+            <div v-for='(corp, corpIdx) in rtSelectedCorpList' :key="corp.corpid">
104
+              <div class="corp-wrap">
105
+                <div class="corp-info">
106
+                  <i class="el-icon-s-cooperation c-46a7ff"></i>
107
+                  <span>{{corp.corp_name}}</span>
108
+                </div>
109
+                <i class="el-icon-close pointer" @click="onClickDelSelectedCorp(corp)"></i>
110
+              </div>
111
+            </div>
112
+            <!-- E 全选企微数据 -->
113
+
114
+            <!-- S 非全选企微状态下的客服 -->
115
+            <div class="memberItem" v-for="(item,index) in rtSelectedUserList" :key="item.user_id+'-'+item.corpid">
116
+              <div class="flex" style="flex:1">
117
+                <img class="memberImg" :src="item.avatar" alt="">
118
+                <div class="memberInfo">
119
+                  <div class="name">
120
+                    {{item.user_name}}
121
+                    <span :class="['status-tag', item.is_active == 0 ? 'disabled' : '']">{{ item.is_active == 1 ? '已激活' : '未激活' }}</span>
122
+                  </div>
123
+                  <div class="other">部门:{{item.corp_name}}</div>
124
+                  <div v-if="item.active_desc === '即将过期'" class="other">
125
+                    <span>{{ item.active_desc }}</span>
126
+                    <span v-if="item.expire_time">({{ item.expire_time.slice(0, 10) }})</span>
127
+                  </div>
128
+                </div>
129
+              </div>
130
+              <i class="el-icon-close" style="margin-left:10px" @click="closeUser(item)"></i>
131
+            </div>
132
+            <!-- E 非全选企微状态下的客服 -->
133
+
134
+          </div>
135
+          <div class="buttons">
136
+            <el-button type="primary" plain size="mini" @click="visible = false">取消</el-button>
137
+            <el-button type="primary" size="mini" @click="defineEvent">确定</el-button>
138
+          </div>
139
+        </div>
140
+      </div>
141
+    </el-popover>
142
+  </div>
143
+</template>
144
+<script>
145
+// 此组件是按照企业
146
+import selfInput from '@/components/assembly/screen/input.vue'
147
+import _lodash from 'lodash'
148
+
149
+export default {
150
+  components: { selfInput },
151
+  props: {
152
+    title: {
153
+      type: String,
154
+      default: '所属客服'
155
+    },
156
+    clearable: {
157
+      type: Boolean,
158
+      default: true
159
+    },
160
+    reset: {
161
+      type: Boolean,
162
+      default: false
163
+    },
164
+    width: {
165
+      type: String
166
+    },
167
+    labelWidth: {
168
+      type: String
169
+    },
170
+    afferent_users: {//传入格式 [{ user_id: xxx, corpid: xxx }]
171
+      type: Array
172
+    },
173
+    disabled: {
174
+      type: Boolean,
175
+      default: false
176
+    },
177
+    icon_arrow_bg: {
178
+      type: Boolean,
179
+      default: true
180
+    },
181
+    isRequired: {
182
+      type: Boolean,
183
+      default: () => true,
184
+    },
185
+    placeholder: {
186
+      type: String,
187
+      default: () => '请选择'
188
+    },
189
+    source: {
190
+      type: String,
191
+      default: () => 'operation'   // operation 客服   chatGroup 群主
192
+    },
193
+  },
194
+  watch: {
195
+    reset () {
196
+      this.selectUser = [];
197
+      this.final_result = [];
198
+      this.changeSelect()
199
+    },
200
+    afferent_users () {
201
+      this.page_init()
202
+    }
203
+  },
204
+  data () {
205
+    return {
206
+      input_keyword: '',
207
+      visible: false,
208
+      resetFlag: false,
209
+      loading: false,
210
+      userList: [],
211
+      old_user_list: [],
212
+      userTotal: 0,
213
+      selectUser: [],
214
+      final_result: []
215
+    }
216
+  },
217
+  computed: {
218
+    corpTotal() { // 企微主体数量
219
+      return (this.userList && this.userList.length) ? this.userList.length : 0
220
+    },
221
+    selectedCorpList() { // 已选成员 数据格式化
222
+      let res = []
223
+      if (this.selectUser && this.selectUser.length) {
224
+        this.selectUser.forEach(currentUser => {
225
+          const userInfo = {
226
+            user_id: currentUser.user_id,
227
+            user_name: currentUser.name,
228
+            avatar: currentUser.avatar,
229
+            corp_name: currentUser.corp_name,
230
+            corpid: currentUser.corpid,
231
+            active_desc: currentUser.active_desc,
232
+            expire_time: currentUser.expire_time,
233
+            is_active: currentUser.is_active,
234
+          }
235
+          if (res && !res.length) { // 构造第一条数据 => 插入res中
236
+            res.push({
237
+              corpid: currentUser.corpid,
238
+              corp_name: currentUser.corp_name,
239
+              user_list: [userInfo]
240
+            })
241
+          } else { // 查询当前用户的企微在res中是否已存在
242
+            const isFoundIdx = res.findIndex(r => r.corpid === currentUser.corpid)
243
+            if (isFoundIdx === -1) { // 不存在 => 写入企微&用户列表
244
+              res.push({
245
+                corpid: currentUser.corpid,
246
+                corp_name: currentUser.corp_name,
247
+                user_list: [userInfo]
248
+              })
249
+            } else { // 已存在 => 插入用户信息
250
+              res[isFoundIdx].user_list.push(userInfo)
251
+            }
252
+          }
253
+        })
254
+      }
255
+      return res
256
+    },
257
+    rtSelectedCorpList() {
258
+      let res = []
259
+      if (this.selectedCorpList && this.selectedCorpList.length) {
260
+        this.selectedCorpList.forEach(s => {
261
+          const crtCorpOptions = this.old_user_list.find(o => o.corpid === s.corpid)
262
+          if (crtCorpOptions && crtCorpOptions.user_list.length === s.user_list.length) {
263
+            res.push({
264
+              corp_name: crtCorpOptions.corp_name,
265
+              corpid: crtCorpOptions.corpid,
266
+            })
267
+          }
268
+        })
269
+      }
270
+      return res
271
+    },
272
+    rtSelectedUserList() {
273
+      let res = []
274
+      if (this.selectedCorpList && this.selectedCorpList.length) {
275
+        this.selectedCorpList.forEach(s => {
276
+          const crtCorpOptions = this.old_user_list.find(o => o.corpid === s.corpid)
277
+          if (crtCorpOptions && crtCorpOptions.user_list.length !== s.user_list.length) {
278
+            res = [...res, ...s.user_list]
279
+          }
280
+        })
281
+      }
282
+      return res
283
+    },
284
+  },
285
+  created () {
286
+    this.page_init()
287
+  },
288
+  methods: {
289
+    page_init () {
290
+      if (this.userList.length == 0) {
291
+        this.init()
292
+      } else {
293
+        this.selectUser = JSON.parse(JSON.stringify(this.final_result));
294
+        this.changeSelect()
295
+        this.afferent_init()
296
+      }
297
+    },
298
+    afferent_init () {//从外面传入
299
+      let selectUser = [];
300
+      if (this.afferent_users && this.afferent_users.length >= 0) {
301
+        let self_afferent_users = this.afferent_users.map((v) => {
302
+          return v.corpid + '-' + v.user_id
303
+        })
304
+        this.userList.forEach((item1) => {
305
+          item1.user_list.forEach((item) => {
306
+            let of_str = item.corpid + '-' + item.user_id
307
+            if (self_afferent_users.indexOf(of_str) != -1) {
308
+              selectUser.push(item)
309
+            }
310
+          })
311
+        })
312
+        this.selectUser = selectUser;
313
+        //去重
314
+        let final_result = JSON.parse(JSON.stringify(selectUser))
315
+        let tmp = {};
316
+        final_result = final_result.reduce((list, item) => {
317
+          tmp[item.user_id] ? '' : (tmp[item.user_id] = list.push(item));
318
+          return list
319
+        }, []);
320
+        this.final_result = final_result
321
+        this.changeSelect()
322
+      }
323
+    },
324
+    clear () {
325
+      if (this.disabled) return
326
+      if (!this.selectUser || this.selectUser.length == 0) {
327
+        this.visible = !this.visible
328
+        return
329
+      } else {
330
+        this.selectUser = [];
331
+        this.final_result = []
332
+        this.changeSelect()
333
+        this.$emit('customerDefine', {})
334
+        if (this.input_keyword != '') {
335
+          this.input_keyword = '';
336
+          this.resetFlag = !this.resetFlag
337
+          this.init()
338
+        }
339
+
340
+      }
341
+    },
342
+    defineEvent () {
343
+      this.final_result = JSON.parse(JSON.stringify(this.selectUser))
344
+      // let arr = this.selectUser.map((v) => {
345
+      //   return v.user_id
346
+      // })
347
+      if (this.isRequired && this.selectUser.length == 0) {
348
+        this.$message({
349
+          message: `请选择${this.source == 'chatGroup' ? '群主' : '成员'}`,
350
+          type: "warning"
351
+        })
352
+        return
353
+      }
354
+      this.visible = false
355
+      this.$emit('customerDefine', { // 3种数据格式都传给父组件 不同场景选择使用
356
+        res_format_1: this.selectUser,
357
+        res_format_2: this.selectedCorpList,
358
+        res_format_3: {
359
+          corpList: [...this.rtSelectedCorpList],
360
+          userList: [...this.rtSelectedUserList],
361
+        },
362
+      })
363
+    },
364
+    userSearch () {//模糊搜索 空格 可搜索多个结果
365
+      let input_keyword_arr = this.input_keyword.split(' ');
366
+      input_keyword_arr = input_keyword_arr.filter((v)=>{
367
+        return v != ''
368
+      })
369
+      let search_user_list = []
370
+      input_keyword_arr.length == 0 ? input_keyword_arr = [''] : ''
371
+
372
+      this.old_user_list.forEach((item) => {
373
+        let arr = item.user_list.filter((v) => {
374
+          let flag = false
375
+          input_keyword_arr.forEach((s_info)=>{
376
+            if (!flag) {
377
+              flag = (v.name && v.name.indexOf(s_info) != -1) || (v.corp_name && v.corp_name.indexOf(s_info) != -1)
378
+            }
379
+          })
380
+          return flag
381
+        })
382
+        if (arr && arr.length > 0) {
383
+          let self_item = JSON.parse(JSON.stringify(item))
384
+          self_item.user_list = arr;
385
+          search_user_list.push(self_item)
386
+        }
387
+      })
388
+
389
+      this.userList = search_user_list;
390
+      let userTotal = 0;
391
+      this.userList.forEach((item) => {
392
+        if (this.input_keyword === '') {
393
+          item.is_open = true//是否折叠
394
+        } else {
395
+          item.is_open = false//是否折叠
396
+        }
397
+        item.is_select = false//是否选中
398
+        item.user_list.forEach((item1) => {
399
+          item1.is_select = false
400
+        })
401
+        userTotal += item.user_list.length
402
+      });
403
+      this.changeSelect()
404
+      this.userTotal = userTotal
405
+    },
406
+    init (type) {
407
+      this.loading = true
408
+      let url = this.URL.BASEURL + this.URL.warn_djuserList
409
+      let params = {
410
+        sys_group_id: this.$cookie.getCookie('isSuperManage') == 1 ? sessionStorage.getItem('company_session_defaultCorp_level_1').toString() : '',
411
+      }
412
+
413
+      // if (this.source == 'chatGroup') {//群主
414
+      //   url = this.URL.BASEURL + this.URL.inviteRule_ownerListOfCompany
415
+      //   params = {}
416
+      // }
417
+
418
+      this.$axios.get(url, {
419
+        params: params
420
+      }).then((res) => {
421
+        var res = res.data
422
+        this.loading = false
423
+        if (res && res.errno == 0) {
424
+          let arr = res.rst;
425
+          arr.forEach((item) => {
426
+            item.user_list.forEach((item1) => {
427
+              item1.corp_name = item.corp_name;
428
+            })
429
+          });
430
+
431
+          // if (this.source == 'chatGroup') {//群主
432
+          //   arr.forEach((item) => {
433
+          //     item.user_list.forEach(user => {
434
+          //       user.corpid = item.corpid;
435
+          //     })
436
+          //   });
437
+          // }
438
+
439
+          this.userList = arr;
440
+          this.old_user_list = JSON.parse(JSON.stringify(arr))
441
+          let userTotal = 0;
442
+          this.userList.forEach((item) => {
443
+            userTotal += item.user_list.length;
444
+            item.is_open = true//是否折叠   默认收起
445
+            item.is_select = false//是否选中
446
+            item.user_list.forEach((item1) => {
447
+              item1.is_select = false
448
+            })
449
+          });
450
+          if (type != 'userSearch') {//非搜索
451
+            this.selectUser = JSON.parse(JSON.stringify(this.final_result));
452
+            this.afferent_init()
453
+          }
454
+          this.changeSelect()
455
+          this.userTotal = userTotal
456
+        } else if (res.errno != 4002) {
457
+          this.$message({
458
+            message: res.err,
459
+            type: "warning"
460
+          })
461
+        }
462
+      }).catch((err) => {
463
+        this.loading = false
464
+      });
465
+    },
466
+    openEvent (index) {
467
+      let arr = this.userList[index]
468
+      arr.is_open = !arr.is_open
469
+      this.$set(this.userList, index, arr)
470
+    },
471
+    selectUserEvent (type, main_index, user_index) {
472
+      let selectUser = this.selectUser
473
+      let user_arr = this.userList[main_index];
474
+      if (type == 'all') {//点击部门全选时
475
+        if (!user_arr.is_select) {
476
+          selectUser = selectUser.concat(user_arr.user_list)
477
+        } else {
478
+          let arr = user_arr.user_list.map((v) => {
479
+            return v.user_id
480
+          })
481
+          selectUser = selectUser.filter((v) => {
482
+            return arr.indexOf(v.user_id) == -1
483
+          })
484
+        }
485
+      } else {//点击单个客服时
486
+        let brr = user_arr.user_list[user_index]
487
+        if (brr.is_select) {
488
+          selectUser = selectUser.filter((v) => {
489
+            return `${v.corpid}&&&${v.user_id}` != `${brr.corpid}&&&${brr.user_id}`
490
+          })
491
+        } else {
492
+          selectUser.push(brr)
493
+        }
494
+      }
495
+      this.$set(this.userList, main_index, user_arr)
496
+      // 去重
497
+      let tmp = {};
498
+      selectUser = selectUser.reduce((list, item) => {
499
+        // 根据corpid和user_id去重(之前版本只判断user_id去重)
500
+        tmp[`${item.corpid}&&&${item.user_id}`] ? '' : (tmp[`${item.corpid}&&&${item.user_id}`] = list.push(item));
501
+        return list
502
+      }, []);
503
+
504
+      this.selectUser = selectUser
505
+      this.changeSelect()
506
+    },
507
+    changeSelect () {//客服选择发生变化时,部门全选跟着相应的改变
508
+      let self_userList = JSON.parse(JSON.stringify(this.userList))
509
+      let arr_selectUser = this.selectUser.map((v) => { return (v.corpid + '-' + v.user_id) })
510
+      // 全选的改变
511
+      self_userList.forEach((item) => {
512
+        item.user_list = item.user_list.filter((v) => {
513
+          let of_str = v.corpid + '-' + v.user_id
514
+          return arr_selectUser.indexOf(of_str) != -1
515
+        })
516
+        this.userList.forEach((main) => {
517
+          if (main.corpid == item.corpid) {
518
+            if ((item.user_list.length == main.user_list.length) && (item.user_list.length !== 0)) {
519
+              main.is_select = true
520
+            } else {
521
+              main.is_select = false
522
+            }
523
+          }
524
+        })
525
+      })
526
+      // 单个用户的改变
527
+      this.userList.forEach((item) => {
528
+        item.user_list.forEach((item1) => {
529
+          let of_str = item1.corpid + '-' + item1.user_id
530
+          if (arr_selectUser.indexOf(of_str) == -1) {
531
+            item1.is_select = false
532
+          } else {
533
+            item1.is_select = true
534
+          }
535
+        })
536
+      })
537
+    },
538
+    closeUser (item) {
539
+      if (item == -1) {
540
+        this.selectUser = []
541
+      } else {
542
+        const idx = this.selectUser.findIndex(s => (s.corpid === item.corpid) && (s.user_id === item.user_id))
543
+        if (idx !== -1) {
544
+          this.selectUser.splice(idx, 1)
545
+        }
546
+      }
547
+      this.changeSelect()
548
+    },
549
+    onClickDelSelectedCorp(currentCorp) {
550
+      const res = []
551
+      this.selectUser.forEach(s => {
552
+        if (s.corpid !== currentCorp.corpid) res.push(s)
553
+      })
554
+      this.selectUser = [...res]
555
+      this.changeSelect()
556
+    },
557
+    handleCloseAllOpen() {
558
+      this.userList.forEach((item) => {
559
+        item.is_open = true
560
+      });
561
+    },
562
+  }
563
+}
564
+</script>
565
+<style lang="scss" scoped>
566
+.propoverItem {
567
+  width: 330px;
568
+  flex: 1;
569
+  height: 100%;
570
+  .allMember {
571
+    color: #666666;
572
+    font-size: 14px;
573
+    line-height: 20px;
574
+    margin-top: 10px;
575
+  }
576
+  .title {
577
+    color: #383e47;
578
+    font-size: 14px;
579
+    line-height: 20px;
580
+    font-weight: bold;
581
+  }
582
+  .choice_result_top {
583
+    display: flex;
584
+    align-items: center;
585
+    justify-content: space-between;
586
+    margin: 7px 0;
587
+    .clear {
588
+      color: #00b38a;
589
+      font-size: 13px;
590
+      line-height: 18px;
591
+      cursor: pointer;
592
+      font-weight: bold;
593
+    }
594
+    .result_num {
595
+      color: #333333;
596
+      font-size: 13px;
597
+      line-height: 18px;
598
+      span {
599
+        color: #00b38a;
600
+        font-weight: bold;
601
+      }
602
+    }
603
+  }
604
+  .member_result {
605
+    height: 380px;
606
+    overflow-y: auto;
607
+    padding-right: 15px;
608
+  }
609
+}
610
+.line {
611
+  width: 0.5px;
612
+  background: #c3cbd6;
613
+}
614
+.propoverItem,
615
+.line {
616
+  height: 478px;
617
+}
618
+.memberBoxBig {
619
+  height: 400px;
620
+  overflow-y: auto;
621
+}
622
+.memberBox {
623
+  display: flex;
624
+  margin-top: 10px;
625
+
626
+  .el-icon-caret-bottom {
627
+    color: #46a7ff;
628
+    cursor: pointer;
629
+    margin-right: 7px;
630
+    margin-top: 2px;
631
+    transition: all 0.3s;
632
+    display: block;
633
+    height: 14px;
634
+  }
635
+  .meberList {
636
+    flex: 1;
637
+    margin-right: 15px;
638
+    .department {
639
+      i {
640
+        color: #46a7ff;
641
+      }
642
+      span {
643
+        color: #383e47;
644
+        font-size: 14px;
645
+        line-height: 20px;
646
+        margin-left: 5px;
647
+        font-weight: bold;
648
+      }
649
+    }
650
+
651
+    .checkbox {
652
+      width: 15px;
653
+      height: 15px;
654
+      border: 1px solid #979797;
655
+      border-radius: 50%;
656
+      display: flex;
657
+      align-items: center;
658
+      justify-content: center;
659
+      font-size: 12px;
660
+      margin-left: 10px;
661
+      i {
662
+        color: transparent;
663
+      }
664
+      &.checkbox_active {
665
+        i {
666
+          color: #ffffff;
667
+        }
668
+        background: #00b38a;
669
+        border-color: #00b38a;
670
+      }
671
+    }
672
+  }
673
+}
674
+.memberItem,
675
+.department {
676
+  display: flex;
677
+  align-items: center;
678
+  justify-content: space-between;
679
+  cursor: pointer;
680
+}
681
+.memberItem {
682
+  margin: 14px 0;
683
+  .memberImg {
684
+    width: 38px;
685
+    height: 38px;
686
+    border-radius: 4px;
687
+  }
688
+  .memberInfo {
689
+    margin-left: 7px;
690
+    flex: 1;
691
+    .name {
692
+      color: #333333;
693
+      font-size: 13px;
694
+      line-height: 18px;
695
+      .status-tag {
696
+        background-color: #00B38A;
697
+        color: #fff;
698
+        border-radius: 4px;
699
+        font-size: 12px;
700
+        padding: 0 1px;
701
+        &.disabled {
702
+          background-color: #B3B2B2;
703
+        }
704
+      }
705
+    }
706
+    .other {
707
+      color: #898d92;
708
+      font-size: 12px;
709
+      line-height: 18px;
710
+    }
711
+  }
712
+}
713
+.reversalAnimation {
714
+  transform: rotate(-90deg);
715
+}
716
+.buttons {
717
+  text-align: right;
718
+  padding: 20px 0 10px;
719
+}
720
+
721
+.corp-wrap {
722
+  margin-top: 14px;
723
+  display: flex;
724
+  justify-content: space-between;
725
+  align-items: center;
726
+  .corp-info {
727
+    color: #383e47;
728
+    font-size: 14px;
729
+    line-height: 20px;
730
+    font-weight: bold;
731
+  }
732
+}
733
+
734
+</style>

+ 59 - 7
project/src/components/dataBoard/chatGroupData.vue

@@ -2,13 +2,20 @@
2 2
   <div>
3 3
     <div class="screenBox">
4 4
       <div class="flex-align-center" style="flex-wrap: wrap;margin-right: 60px;min-height: 60px;">
5
-        <datePicker title="客户入群时间" :quickFlag="false" :afferent_time="default_time" :clearFlag='true' :reset="resetFlag" @changeTime="onChangeTime" style="margin-right: 10px;" />
5
+        <el-select v-model="filter.dataType" placeholder="请选择" size="small" class="dataType" @change="onChangeDataType">
6
+          <el-option label="群主" value="qz" />
7
+          <el-option label="企微主体" value="qwzt" />
8
+        </el-select>
9
+        <!-- 多主体选择成员(群主) -->
10
+        <customerServiceCorpV2 v-show="filter.dataType === 'qz'" title="" placeholder="请选择群主" :reset="resetFlag" :isRequired="false" :isDisableSelectAllCorp="true"  @customerDefine="onChangeMultiCorpUsers" />
11
+        <!-- 企微主体(无权限) -->
12
+        <selfChannelV2 v-show="filter.dataType === 'qwzt'" v-model="filter.corpid2" class="qwzt-sl" title="" type="corpAll" placeholder="请选择企微主体" labelWidth @change="onChangeCorpid2" />
13
+        <!-- 入群时间 -->
14
+        <datePicker title="客户入群时间" :quickFlag="false" :afferent_time="default_time" :clearFlag='true' :reset="resetFlag" @changeTime="onChangeTime" style="margin-left:20px;margin-right: 10px;" />
6 15
         <!-- 企微主体 -->
7 16
         <!-- <selfSelectCorp style="margin-right: 30px;" v-model="filter.corpid" @change="onChangeCorpid" /> -->
8 17
         <!-- 群主 -->
9 18
         <!-- <selfChannelV2 v-model="filter.owner" title="群主" type="chatGroupOwner" ref="selectOwnerEl" labelWidth :afferent_params="{ isSelectedCorp: true, corpid: filter.corpid }" @change="onChangeOwner" @visible-change="onSelectOwnerVisibleChange" /> -->
10
-        <!-- 多主体选择成员(群主) -->
11
-        <customerServiceCorpV2 style="margin-left: -40px;" title="群主" :reset="resetFlag" :isRequired="false"  @customerDefine="onChangeMultiCorpUsers" />
12 19
         <inputRange v-model="filter.member" label="群人数" style="margin-left: 20px;" />
13 20
         <div style="margin-left: 20px;">
14 21
           <el-button size="mini" type="primary" plain @click="init(1);init_predata();">确定</el-button>
@@ -72,6 +79,7 @@ import datePicker from '@/components/assembly/screen/datePicker.vue'
72 79
 import selfChannelV2 from '@/components/assembly/screen/channelV2.vue'
73 80
 import selfSelectCorp from '@/components/assembly/screen/selectCorp.vue'
74 81
 import customerServiceCorpV2 from '@/components/assembly/screen/customerServiceCorpV2.vue'
82
+import customerServiceCorpV3 from '@/components/assembly/screen/customerServiceCorpV3.vue'
75 83
 import { chatGroupStatusCodeMap } from '@/assets/js/staticTypes'
76 84
 import inputRange from '@/components/dataBoard/inputRange.vue'
77 85
 
@@ -82,6 +90,7 @@ export default {
82 90
     selfChannelV2,
83 91
     selfSelectCorp,
84 92
     customerServiceCorpV2,
93
+    customerServiceCorpV3,
85 94
     inputRange,
86 95
   },
87 96
   data () {
@@ -147,6 +156,8 @@ export default {
147 156
         owner: '', // 群主
148 157
         multiple_senders: [], // 多个主体时选择的客服成员结果
149 158
         member: ['', ''], // 群人数
159
+        dataType: 'qwzt', // 维度 群主qz 企微主体qwzt
160
+        corpid2: '', // 企微主体
150 161
       },
151 162
     }
152 163
   },
@@ -174,7 +185,8 @@ export default {
174 185
       const params = {
175 186
         corpid: this.filter.corpid,
176 187
         owner: this.filter.owner,
177
-        owner_list: this.filter.multiple_senders,
188
+        corpid: this.filter.dataType === 'qwzt' ? this.filter.corpid2 : '',
189
+        owner_list: this.filter.dataType === 'qz' ? this.filter.multiple_senders : [],
178 190
         create_time_st: this.filter.time[0] || '',
179 191
         create_time_et: this.filter.time[1] || '',
180 192
         min_member: this.filter.member[0] || '',
@@ -206,7 +218,8 @@ export default {
206 218
       const params = {
207 219
         corpid: this.filter.corpid,
208 220
         owner: this.filter.owner,
209
-        owner_list: this.filter.multiple_senders,
221
+        corpid: this.filter.dataType === 'qwzt' ? this.filter.corpid2 : '',
222
+        owner_list: this.filter.dataType === 'qz' ? this.filter.multiple_senders : [],
210 223
         create_time_st: this.filter.time[0] || '',
211 224
         create_time_et: this.filter.time[1] || '',
212 225
         min_member: this.filter.member[0] || '',
@@ -269,6 +282,16 @@ export default {
269 282
       this.init(1);
270 283
       this.init_predata();
271 284
     },
285
+    onChangeDataType(val) {
286
+      this.filter.dataType = val || 'qwzt'
287
+      this.init(1);
288
+      this.init_predata();
289
+    },
290
+    onChangeCorpid2(val) {
291
+      this.filter.corpid2 = val || ''
292
+      this.init(1);
293
+      this.init_predata();
294
+    },
272 295
     onChangeMultiCorpUsers({ res_format_2 }) {
273 296
       if (res_format_2 && res_format_2.length) {
274 297
         this.filter.multiple_senders = res_format_2.map(corp => ({
@@ -281,6 +304,18 @@ export default {
281 304
       this.init(1);
282 305
       this.init_predata();
283 306
     },
307
+    // onChangeMultiCorpUsers({ res_format_3 }) {
308
+    //   if (res_format_3 && res_format_3.corpList) {
309
+    //     console.log('corpList => ', JSON.parse(JSON.stringify(res_format_3.corpList)))
310
+    //   } else {
311
+    //   }
312
+    //   if (res_format_3 && res_format_3.userList) {
313
+    //     console.log('corpList => ', JSON.parse(JSON.stringify(res_format_3.userList)))
314
+    //   } else {
315
+    //   }
316
+    //   this.init(1);
317
+    //   this.init_predata();
318
+    // },
284 319
     handleCurrentChange (val) {
285 320
       this.init(val)
286 321
     },
@@ -294,7 +329,9 @@ export default {
294 329
       this.filter.multiple_senders = []
295 330
       this.filter.corpid = ''
296 331
       this.filter.owner = ''
332
+      this.filter.corpid2 = ''
297 333
       this.filter.member = ['', '']
334
+      this.filter.dataType = 'qwzt'
298 335
       await this.$nextTick()
299 336
       this.$refs.selectOwnerEl && this.$refs.selectOwnerEl.handleGetOptions()
300 337
       this.init_predata()
@@ -307,9 +344,10 @@ export default {
307 344
       this.loading = true
308 345
       const url = `${this.URL.BASEURL}${this.URL.dataBoard_chatGroupData_list}`
309 346
       const params = {
310
-        corpid: this.filter.corpid,
347
+        // corpid: this.filter.corpid,
348
+        corpid: this.filter.dataType === 'qwzt' ? this.filter.corpid2 : '',
349
+        owner_list: this.filter.dataType === 'qz' ? this.filter.multiple_senders : [],
311 350
         owner: this.filter.owner,
312
-        owner_list: this.filter.multiple_senders,
313 351
         create_time_st: this.filter.time[0] || '',
314 352
         create_time_et: this.filter.time[1] || '',
315 353
         min_member: this.filter.member[0] || '',
@@ -444,4 +482,18 @@ export default {
444 482
     }
445 483
   }
446 484
 }
485
+/deep/ .dataType {
486
+   .el-input--small .el-input__inner {
487
+    width: 100px;
488
+    height: 30px;
489
+   }
490
+}
491
+/deep/ .qwzt-sl {
492
+  .el-input__inner {
493
+    height: 30px;
494
+  }
495
+  .el-input--small .el-input__icon {
496
+    line-height: 26px;
497
+  }
498
+}
447 499
 </style>