Browse Source

智能雷达页面

liuxiaona 2 years ago
parent
commit
bfa51f2d61

+ 1 - 0
project/src/components/channelCode/channelAnalyse.vue

@@ -36,6 +36,7 @@ export default {
36 36
       default_time: [this.$getDay(-30, false), this.$getDay(0, false)],
37 37
       resetFlag: false,
38 38
       myChart: null,
39
+      time:[]
39 40
     }
40 41
   },
41 42
   created(){

+ 203 - 0
project/src/components/smartRadar/addLimit.vue

@@ -0,0 +1,203 @@
1
+<template>
2
+  <div>
3
+<!--
4
+ <div class="regulations">
5
+      <label><em>*</em>预警人</label>
6
+      <self-customerservice title='' width="300px"
7
+                            :afferent_users='user_id_list'
8
+                            @customerDefine="(val)=>{user_id_list=val;}"></self-customerservice>
9
+
10
+    </div>
11
+-->
12
+
13
+    <div style="margin-left: 100px;width: 720px">
14
+      <div class="flex">
15
+        <self-input :hasLabel="false" @inputChange='(val)=>{member_val = val;initFlag=!initFlag}'></self-input>
16
+        <el-button type="primary" size="mini" @click="batch_setting">批量设置</el-button>
17
+      </div>
18
+      <el-table v-loading="loading" ref="multipleTable"
19
+                border
20
+                :data="tableData"
21
+                tooltip-effect="dark"
22
+                @selection-change="handleSelectionChange"
23
+                :header-cell-style="()=>{return { backgroundColor: '#f9f9f9 !important' }}"
24
+                style="width: 100%">
25
+        <el-table-column width="40px" type="selection"></el-table-column>
26
+        <el-table-column label="全部成员" align="center">
27
+          <template slot-scope="scope">
28
+            <div>{{scope.row.user_id ? scope.row.user_id : '-'}}</div>
29
+          </template>
30
+        </el-table-column>
31
+        <el-table-column label="每日添加客户上限" align="center">
32
+          <template slot-scope="scope">
33
+            <el-input size="mini" v-model="scope.row.input"></el-input>
34
+          </template>
35
+        </el-table-column>
36
+        <el-table-column label="今日添加客户数" align="center">
37
+          <template slot-scope="scope">
38
+            <div>{{scope.row.assign_count||scope.row.assign_count==0 ? scope.row.assign_count : '-'}}</div>
39
+          </template>
40
+        </el-table-column>
41
+        <el-table-column label="是否分配客户" align="center">
42
+          <template slot-scope="scope">
43
+            <el-switch v-model="scope.row.isAllot"
44
+                       active-color="#13ce66"
45
+                       inactive-color="#ddd"></el-switch>
46
+          </template>
47
+        </el-table-column>
48
+        <el-table-column label="操作" align="center">
49
+          <template slot-scope="scope">
50
+            <div class="c-00B38A pointer lMar8">删除</div>
51
+          </template>
52
+        </el-table-column>
53
+      </el-table>
54
+      <div class="pagination" v-show="total>0">
55
+        <el-pagination background :current-page="page" @current-change="handleCurrentChange" layout="prev, pager, next" :page-count='Number(pages)'>
56
+        </el-pagination>
57
+      </div>
58
+    </div>
59
+
60
+
61
+    <el-dialog
62
+      title="设置添加上限"
63
+      :center="true"
64
+      :visible.sync="dialogVisible"
65
+      width="20%">
66
+      <div style="display: flex;align-items: center;justify-content: center">
67
+        <div>每日添加客户上限: </div>
68
+        <div style="width: 100px;margin-left: 20px"><el-input size="mini" v-model="batchVal"></el-input></div>
69
+      </div>
70
+      <span slot="footer" class="dialog-footer">
71
+        <el-button size="mini" @click="dialogVisible = false">取 消</el-button>
72
+        <el-button size="mini" type="primary" @click="batchValSave">确 定</el-button>
73
+      </span>
74
+    </el-dialog>
75
+
76
+  </div>
77
+</template>
78
+
79
+<script>
80
+import selfInput from '@/components/assembly/screen/input.vue'
81
+import selfCustomerservice from '@/components/assembly/screen/customerService.vue'
82
+export default {
83
+  name: "addLimit",
84
+  components:{
85
+    selfCustomerservice,
86
+    selfInput
87
+  },
88
+  data(){
89
+    return{
90
+      loading: false,
91
+      dataLoading: false,
92
+      page: 1,
93
+      pages: 0,
94
+      total: 0,
95
+      page_size: 20,
96
+      tableData:[],
97
+      user_id_list:[],
98
+      input:'',
99
+      initFlag:false,
100
+      member_val:'',
101
+      noChooseFlag:false,
102
+      user_ids:[],
103
+      dialogVisible:false,
104
+      batchVal:100,
105
+    }
106
+  },
107
+  watch:{
108
+
109
+  },
110
+  created() {
111
+    this.init(1)
112
+  },
113
+  methods:{
114
+    batchValSave(){
115
+      this.dialogVisible = false
116
+    },
117
+    noChooseCustomeTips(){//没有选择客户提示
118
+      this.noChooseFlag = false
119
+      if( this.user_ids){
120
+        if(this.user_ids.length==0){
121
+          this.$message({
122
+            type: 'error',
123
+            message: '请选择成员!'
124
+          });
125
+          this.noChooseFlag = true
126
+        }
127
+        if(this.user_ids.length>=4){
128
+          this.$message({
129
+            type: 'error',
130
+            message: '最多可选3个成员!'
131
+          });
132
+          this.noChooseFlag = true
133
+        }
134
+      }
135
+
136
+    },
137
+    handleSelectionChange(val){//列表选择人员
138
+      this.user_ids = []
139
+      val.forEach(item=>{
140
+        this.user_ids.push(item.user_id)
141
+      })
142
+    },
143
+    batch_setting(){//批量设置
144
+      this.noChooseCustomeTips()
145
+      if(this.noChooseFlag){return}
146
+      this.batchVal = 100
147
+      this.dialogVisible = true
148
+
149
+    },
150
+    goDataAanlyse(id){
151
+      this.$router.push('/dataAnalyse/'+id)
152
+    },
153
+    init (page, type) {
154
+      if (type != 'export') {
155
+        this.page = page ? page : this.page;
156
+      } else {
157
+        if (this.total == 0) {
158
+          this.$message({
159
+            message: '暂无数据可导出',
160
+            type: "warning"
161
+          })
162
+          return
163
+        }
164
+      }
165
+      this.loading = true
166
+      this.$axios.get(this.URL.BASEURL + this.URL.batchAddCustomer_statistic, {
167
+        params:{
168
+          start_date: '2022-05-14',
169
+          end_date: '2022-06-13',
170
+          page: type == 'export' ? 1 : this.page,
171
+          pagesize: type == 'export' ? this.$store.state.exportNumber : this.page_size,
172
+        }
173
+      }).then((res) => {
174
+        var res = res.data
175
+        this.loading = false
176
+        if (res && res.errno == 0) {
177
+          if (type == 'export') {
178
+            this.exportEvent(res.rst.data)
179
+          } else {
180
+            this.tableData = res.rst.data
181
+            this.total = res.rst.pageInfo.total;
182
+            this.pages = res.rst.pageInfo.pages;
183
+          }
184
+        } else if (res.errno != 4002) {
185
+          this.$message({
186
+            message: res.err,
187
+            type: "warning"
188
+          })
189
+        }
190
+      }).catch((err) => {
191
+        this.loading = false
192
+      });
193
+    },
194
+    handleCurrentChange (val) {
195
+      this.init(val)
196
+    },
197
+  }
198
+}
199
+</script>
200
+
201
+<style lang="scss" scoped>
202
+@import "../customOperate/create.scss";
203
+</style>

+ 363 - 0
project/src/components/smartRadar/createRadar.vue

@@ -0,0 +1,363 @@
1
+<template>
2
+  <div>
3
+    <div class="backBox" @click="$router.go(-1)">
4
+     <div class="back">
5
+       <i class="el-icon-back"></i>
6
+       <span>返回</span>
7
+     </div>
8
+   </div>
9
+
10
+    <div v-if="!loading" class="bg-ffffff createMassMsg" style="padding: 10px 30px 10px;">
11
+      <div class="regulations">
12
+        <label><em>*</em>名称</label>
13
+        <el-input placeholder="请输入雷达名称" style="width:300px" v-model.trim="radarName"
14
+                  maxlength="32"
15
+                  show-word-limit
16
+                  clearable size="small"></el-input>
17
+      </div>
18
+      <div class="regulations" style="align-items: center">
19
+        <label>选择分组</label>
20
+        <el-select v-model="group_val" size="small" clearable placeholder="请选择" style="width: 300px">
21
+          <el-option
22
+            v-for="item in groupArrs"
23
+            :key="item.value"
24
+            :label="item.label"
25
+            :value="item.value">
26
+          </el-option>
27
+        </el-select>
28
+      </div>
29
+      <div class="regulations">
30
+        <label><em>*</em>文件类型</label>
31
+<!--        <fileType></fileType>-->
32
+      </div>
33
+      <div class="regulations">
34
+        <label><em>*</em>跳转链接</label>
35
+        <el-input placeholder="请输入跳转链接" style="width:300px" v-model.trim="jumplink_val"
36
+                  clearable size="small"></el-input>
37
+      </div>
38
+      <div class="regulations">
39
+        <label><em>*</em>雷达标题</label>
40
+        <el-input placeholder="请输入雷达标题" style="width:300px" v-model.trim="radartitle"
41
+                  clearable size="small"></el-input>
42
+      </div>
43
+      <div class="regulations">
44
+        <label><em>*</em>雷达描述</label>
45
+        <el-input placeholder="请输入雷达标题" style="width:300px" v-model.trim="radardesc"
46
+                  clearable size="small"></el-input>
47
+      </div>
48
+      <div class="regulations">
49
+        <label><em>*</em>雷达封面</label>
50
+        <div>
51
+
52
+        </div>
53
+      </div>
54
+      <div class="regulations smartFollow">
55
+        <label class="fWeight600">智能跟进</label>
56
+        <div>
57
+          <el-checkbox-group v-model="smartVal">
58
+            <el-checkbox label="行为通知(当客户点击雷达时,发送雷达的员工将会收到消息提醒)"></el-checkbox>
59
+            <el-checkbox label="动态通知(当客户点击雷达时,会将客户的打开行为记录在客户动态里)"></el-checkbox>
60
+            <el-checkbox label="客户标签(给点击雷达的客户打上选中的标签)"></el-checkbox>
61
+          </el-checkbox-group>
62
+        </div>
63
+      </div>
64
+
65
+      <div style="margin-top: 20px">
66
+        <el-button type="primary" @click="newCode_click">创建雷达</el-button>
67
+      </div>
68
+    </div>
69
+  </div>
70
+</template>
71
+
72
+<script>
73
+// import dialogGroup from './dialogGroup.vue'
74
+export default {
75
+  name: "createRadar",
76
+  components:{
77
+    // dialogGroup
78
+  },
79
+  data(){
80
+    return{
81
+      loading:false,
82
+      radarName:'',
83
+      jumplink_val:'',
84
+      radartitle:'',
85
+      radardesc:'',
86
+      group_val:0,
87
+      groupArrs:[
88
+        {
89
+          label:'分组一',
90
+          value:0
91
+        }
92
+      ],
93
+      user_id_list: [],
94
+
95
+      resetFlag: false,
96
+      smartVal: [],
97
+
98
+    }
99
+  },
100
+  watch:{
101
+
102
+  },
103
+  created(){
104
+
105
+  },
106
+  methods:{
107
+    detail () {//详情
108
+      this.loading = true
109
+      this.$axios.get(this.URL.BASEURL + this.URL.welcomeMsg_detail, {
110
+        params: {
111
+          rule_id: this.$route.query.id
112
+        }
113
+      }).then((res) => {
114
+        var res = res.data
115
+        this.loading = false
116
+        if (res && res.errno == 0) {
117
+          this.dataInfo = res.rst;
118
+          this.is_for_all = res.rst.is_for_all;
119
+          this.user_id_list = res.rst.users ? res.rst.users.split(',') : [];
120
+          this.name = res.rst.name;
121
+          let msg_list = res.rst.msg_list;
122
+          msg_list.forEach((item) => {
123
+            item.content = item.content ? item.content.replace('%NICKNAME%', '「客户昵称」') : '';
124
+            item.attachments = item.attachments && item.attachments != '' ? JSON.parse(item.attachments) : [];
125
+            item.weeks = item.weeks ? item.weeks.split(',') : []
126
+          })
127
+          let main_msg_data = msg_list.filter((v) => {//特定有一个主欢迎语内容
128
+            return v.is_day_parting == 0
129
+          })
130
+          this.main_msg_data = main_msg_data && main_msg_data.length > 0 ? main_msg_data[0] : {};
131
+
132
+          this.timeIntervalList = msg_list.filter((v) => {//分时段欢迎语内容
133
+            return v.is_day_parting == 1
134
+          })
135
+
136
+          if (msg_list.length > 1) {
137
+            this.is_day_parting = true
138
+          }
139
+        } else if (res.errno != 4002) {
140
+          this.$message({
141
+            message: res.err,
142
+            type: "warning"
143
+          })
144
+        }
145
+      }).catch((err) => {
146
+        this.loading = false
147
+      });
148
+    },
149
+    tipsClick(){
150
+      if(this.user_id_list&&this.user_id_list.length==0){
151
+        this.$message({
152
+          type: 'error',
153
+          message: '请先选择使用客服!'
154
+        });
155
+      }
156
+    },
157
+    newCode_click(){//新建活码
158
+      if(this.radarName == ''){
159
+        this.$message({
160
+          type: 'error',
161
+          message: '渠道名称不能为空!'
162
+        });
163
+        return
164
+      }
165
+      if(this.user_id_list&&this.user_id_list.length==0){
166
+        this.$message({
167
+          type: 'error',
168
+          message: '使用客服不能为空!'
169
+        });
170
+        return
171
+      }
172
+      if(this.customerNote_val==''){
173
+        this.$message({
174
+          type: 'error',
175
+          message: '客户备注不能为空!'
176
+        });
177
+        return
178
+      }
179
+      if (this.main_msg_data.content == '' && (!this.main_msg_data.attachments || this.main_msg_data.attachments == '' || this.main_msg_data.attachments.length == 0)) {
180
+        this.$message({
181
+          message: '请输入【主】欢迎语内容!',
182
+          type: "warning"
183
+        })
184
+        return
185
+      }
186
+      if (this.main_msg_data.content != '' && this.$getStrBytes(this.main_msg_data.content) > 4000) {
187
+        this.$message({
188
+          message: '请检查【主】欢迎语内容,最多4000个字节,已超出!',
189
+          type: "error"
190
+        })
191
+        return
192
+      }
193
+
194
+      let msg_data = []
195
+      if (this.is_day_parting) {//开启分段欢迎语
196
+        for (let i = 0; i < this.timeIntervalList.length; i++) {
197
+          let item = this.timeIntervalList[i];
198
+          if (item.content == '' && (!item.attachments || item.attachments == '' || item.attachments.length == 0)) {
199
+            this.$message({
200
+              message: `请输入【时段${i + 1}】欢迎语内容!`,
201
+              type: "warning"
202
+            })
203
+            return
204
+          }
205
+          if (item.content != '' && this.$getStrBytes(item.content) > 4000) {
206
+            this.$message({
207
+              message: `请检查【时段${i + 1}】欢迎语内容,最多4000个字节,已超出!`,
208
+              type: "error"
209
+            })
210
+            return
211
+          }
212
+          if (!item.weeks || item.weeks.length == 0) {
213
+            this.$message({
214
+              message: `请选择【时段${i + 1}】发送日期!`,
215
+              type: "warning"
216
+            })
217
+            return
218
+          }
219
+          if (!item.start_time || item.start_time == '') {
220
+            this.$message({
221
+              message: `请输入【时段${i + 1}】发送开始时间!`,
222
+              type: "warning"
223
+            })
224
+            return
225
+          }
226
+          if (!item.end_time || item.end_time == '') {
227
+            this.$message({
228
+              message: `请输入【时段${i + 1}】发送结束时间!`,
229
+              type: "warning"
230
+            })
231
+            return
232
+          }
233
+          if (this.$date_compatible(('2020-04-01 ' + item.start_time)).getTime() > this.$date_compatible(('2020-04-01 ' + item.end_time)).getTime()) {
234
+            this.$message({
235
+              message: `请正确输入【时段${i + 1}】发送时间!`,
236
+              type: "warning"
237
+            })
238
+            return
239
+          }
240
+        }
241
+        msg_data = msg_data.concat(this.timeIntervalList)
242
+      } else {//关闭分段欢迎语
243
+        let delete_arr = JSON.parse(JSON.stringify(this.timeIntervalList));
244
+        delete_arr = delete_arr.filter((v) => {
245
+          return v.msg_id
246
+        })
247
+        delete_arr.forEach((item) => {
248
+          item.operate = 'del'
249
+        })
250
+        this.deleteTimeIntervalList = this.deleteTimeIntervalList.concat(delete_arr)
251
+      }
252
+      msg_data = msg_data.concat(this.deleteTimeIntervalList);//删除的分时段内容
253
+
254
+      msg_data.push(this.main_msg_data)
255
+      msg_data.forEach((item) => {
256
+        item.weeks = item.weeks.join(',');
257
+        item.content = item.content.replace('「客户昵称」', '%NICKNAME%')
258
+        item.attachments = item.attachments == '' || item.attachments.length == 0 ? '' : JSON.stringify(item.attachments)
259
+      })
260
+
261
+      this.$loading(this.$loadingConfig)
262
+
263
+      this.$axios.post(this.URL.BASEURL + this.URL.welcomeMsg_set, {
264
+        rule_id: this.$route.query.id ? this.$route.query.id : '',
265
+        radarName: this.radarName,
266
+        is_for_all: this.is_for_all,
267
+        users: this.is_for_all == 0 ? this.user_id_list.join(',') : '',
268
+        msg_data: msg_data
269
+      }).then((res) => {
270
+        var res = res.data
271
+        this.$loading(this.$loadingConfig).close()
272
+        if (res && res.errno == 0) {
273
+          this.$router.go(-1)
274
+        } else if (res.errno != 4002) {
275
+          this.$message({
276
+            message: res.err,
277
+            type: "warning"
278
+          })
279
+        }
280
+      }).catch((err) => {
281
+        this.$loading(this.$loadingConfig).close()
282
+      });
283
+    },
284
+    tagDefine (data) {//标签选择回调
285
+      if (data.tag_id_list && data.tag_id_list.length != 0) {
286
+        this.tag_info = data.tag_id_list
287
+      } else {
288
+        this.tag_info = []
289
+      }
290
+    },
291
+    getAttachment (val) {
292
+      this.main_msg_data.attachments = val;
293
+    },
294
+    switchChange () {//分时段开关打开
295
+      if (this.is_day_parting && this.timeIntervalList.length == 0) {
296
+        this.timeIntervalList.push(this.init_welcom_con)
297
+      }
298
+    },
299
+    getWelcomEdit (val, index) {//分时段编辑
300
+      this.$set(this.timeIntervalList, index, val)
301
+    },
302
+    deleteWelcomCon (index) {//删除分时段
303
+      if (this.$route.query.id && this.timeIntervalList[index].msg_id) {//删除的分时段内容
304
+        let obj = JSON.parse(JSON.stringify(this.timeIntervalList[index]))
305
+        obj.operate = 'del';
306
+        this.deleteTimeIntervalList.push(obj)
307
+      }
308
+      this.timeIntervalList.splice(index, 1)
309
+    },
310
+    addWelcom () {//添加分时段
311
+      this.timeIntervalList.push(this.init_welcom_con)
312
+    },
313
+    switchLimit(){
314
+      if(this.user_id_list&&this.user_id_list.length==0){
315
+        this.$message({
316
+          type: 'error',
317
+          message: '使用客服不能为空!'
318
+        });
319
+        return
320
+      }
321
+
322
+    }
323
+  }
324
+}
325
+</script>
326
+<style lang="scss">
327
+.appendOnly{
328
+  .el-input-group__append{
329
+    padding: 0 20px;
330
+  }
331
+}
332
+.limitBox{
333
+  .el-switch.is-disabled .el-switch__core{
334
+    cursor: pointer;
335
+  }
336
+}
337
+.createMassMsg .smartFollow label{
338
+  display: block;
339
+  font-weight: 600;
340
+  font-size: 12px;
341
+}
342
+
343
+</style>
344
+<style lang="scss" scoped>
345
+@import "../customOperate/create.scss";
346
+
347
+.newGroupCss{
348
+  color: #00b38a;
349
+  font-size: 14px;
350
+  margin-left: 10px;
351
+  cursor: pointer;
352
+}
353
+.add_welcom_hint {
354
+  color: #00b38a;
355
+  font-size: 16px;
356
+  font-weight: bold;
357
+  margin-left: 90px;
358
+  margin-top: 10px;
359
+  margin-bottom: 20px;
360
+  cursor: pointer;
361
+  display: inline-block;
362
+}
363
+</style>

+ 81 - 0
project/src/components/smartRadar/customerNote.vue

@@ -0,0 +1,81 @@
1
+<template>
2
+  <div>
3
+    <div class="flex-align-center">
4
+        <el-input style="width: 300px"
5
+                  clearable
6
+                  @blur="changeIpt"
7
+                  v-if="node_radio==2"
8
+                  placeholder="请输入客户备注"
9
+                  size="small"
10
+                  v-model="customerNote_val">
11
+          <template slot="prepend">客户昵称-</template>
12
+        </el-input>
13
+        <el-input style="width: 300px"
14
+                  clearable
15
+                  @blur="changeIpt"
16
+                  class="appendOnly"
17
+                  size="small"
18
+                  v-if="node_radio==1"
19
+                  placeholder="请输入客户备注"
20
+                  v-model="customerNote_val">
21
+          <template slot="append">-客户昵称</template>
22
+        </el-input>
23
+      <div style="display: flex;margin-left: 20px">
24
+        <el-radio v-model="node_radio" :label="1">备注在昵称后</el-radio>
25
+        <el-radio v-model="node_radio" :label="2">备注在昵称前</el-radio>
26
+      </div>
27
+    </div>
28
+    <div class="sampleBox">
29
+      <div class="f14">示例</div>
30
+      <div class="customerNoteBox">
31
+        <img src="../../assets/img/cs_logo.png" alt="">
32
+        <div class="flex-align-center">
33
+          <template v-if="node_radio==1"><span class="c-000">{{customerNote_val}}</span> -客户昵称</template>
34
+          <template v-if="node_radio==2">客户昵称- <span class="c-000">{{customerNote_val}}</span></template>
35
+        </div>
36
+      </div>
37
+    </div>
38
+  </div>
39
+</template>
40
+
41
+<script>
42
+export default {
43
+  name: "customerNote",
44
+  props:['customerNote_val'],
45
+  data(){
46
+    return{
47
+      // customerNote_val:'',//客户备注
48
+      node_radio:1,
49
+    }
50
+  },
51
+  methods:{
52
+    changeIpt(){
53
+      this.$emit('changeVal',this.customerNote_val)
54
+    }
55
+  }
56
+}
57
+</script>
58
+
59
+<style lang="scss" scoped>
60
+.sampleBox{
61
+  width: 710px;
62
+  background: #fbfbfb;
63
+  border: 1px solid #eee;
64
+  padding: 10px;
65
+  display: flex;
66
+  align-items: flex-start;
67
+  margin-top: 10px;
68
+  .customerNoteBox{
69
+    display: flex;
70
+    padding:10px;
71
+    border: 1px solid #ddd;
72
+    margin-left: 20px;
73
+    color: #999;
74
+    img{
75
+      width: 30px;
76
+      height: 30px;
77
+      margin-right: 8px;
78
+    }
79
+  }
80
+}
81
+</style>

+ 133 - 0
project/src/components/smartRadar/dataAnalyse.vue

@@ -0,0 +1,133 @@
1
+<template>
2
+  <div class="con" v-loading="loading">
3
+    <div class="backBox" @click="$router.go(-1)">
4
+      <div class="back">
5
+        <i class="el-icon-back"></i>
6
+        <span>返回</span>
7
+        (数据分析)
8
+      </div>
9
+    </div>
10
+
11
+    <div class="dataBox">
12
+      <div v-for="(item,index) in dataPreview" :key="index" class="box_item">
13
+        <div class="c-000 fWeight600">{{item.bigTitle?item.bigTitle:'-'}}</div>
14
+        <div class="f28 pad120">{{item.bigNum||item.bigNum==0?item.bigNum:'-'}}</div>
15
+      </div>
16
+    </div>
17
+
18
+    <div class="topTagBox">
19
+      <div class="span_title">打开链接的客户</div>
20
+      <div class="flex-align-center">
21
+        <self-input :hasLabel="false" label_name="搜索客户" @inputChange='(val)=>{kehu_val = val;initFlag=!initFlag}'></self-input>
22
+        <div style="width: 20px"></div>
23
+        <self-input :hasLabel="false" label_name="选择渠道" @inputChange='(val)=>{kehu_val = val;initFlag=!initFlag}'></self-input>
24
+        <div style="width: 20px"></div>
25
+        <date-picker title="" :quickFlag="false" :afferent_time="default_time"
26
+                     :clearFlag='false' :reset="resetFlag" @changeTime="changeTime"></date-picker>
27
+        <div style="width: 20px"></div>
28
+        <self-input :hasLabel="false" label_name="所属成员" @inputChange='(val)=>{kehu_val = val;initFlag=!initFlag}'></self-input>
29
+        <div style="width: 20px"></div>
30
+        <el-button type="primary" size="small" >重置</el-button>
31
+      </div>
32
+      <publicTable
33
+        :propsData="{
34
+          desCol:desCol,
35
+          source:'dataAnalyse',
36
+          initFlag:initFlag
37
+        }"
38
+      ></publicTable>
39
+    </div>
40
+  </div>
41
+</template>
42
+
43
+<script>
44
+import datePicker from '@/components/assembly/screen/datePicker.vue'
45
+import selfInput from '@/components/assembly/screen/input.vue'
46
+import publicTable from './publicTable.vue'
47
+export default {
48
+  name: "dataAnalyse",
49
+  components:{
50
+    publicTable,
51
+    selfInput,
52
+    datePicker
53
+  },
54
+  data(){
55
+    return{
56
+      loading:false,
57
+      dataPreview:[
58
+        {
59
+          bigTitle:'总访问人数',
60
+          bigNum:0,
61
+        },
62
+        {
63
+          bigTitle:'今日访问人数',
64
+          bigNum:0,
65
+        },
66
+        {
67
+          bigTitle:'总访问次数',
68
+          bigNum:0,
69
+        },
70
+        {
71
+          bigTitle:'今日访问次数',
72
+          bigNum:0,
73
+        }
74
+      ],
75
+      default_time: [this.$getDay(-30, false), this.$getDay(0, false)],
76
+      resetFlag: false,
77
+      kehu_val:'',
78
+      initFlag:false,
79
+      time:[],
80
+      desCol:[
81
+        { prop: "name", label: "客户" },
82
+        { prop: "assign_count", label: "所属成员" },
83
+        { prop: "name", label: "最近点击时间" },
84
+        { prop: "waiting_add_count", label: "最近点击渠道" },
85
+        { prop: "passed_count", label: "客户访问总次数"}
86
+      ]
87
+    }
88
+  },
89
+  methods:{
90
+    changeTime (time) {//筛选时间变化
91
+      if (!time || time && time.length == 0) {
92
+        this.time = []
93
+      } else {
94
+        this.time = time
95
+      }
96
+      this.initFlag=!this.initFlag
97
+
98
+    },
99
+  }
100
+}
101
+</script>
102
+
103
+<style lang="scss" scoped>
104
+@import "@/style/list.scss";
105
+.con{
106
+  padding-right: 10px;
107
+}
108
+.dataBox{
109
+  display: flex;
110
+  align-items: center;
111
+  justify-content: space-between;
112
+  .box_item{
113
+    min-width: 23%;
114
+    padding: 20px 15px 10px;
115
+    font-size: 14px;
116
+    background-color: #fff;
117
+    border-radius: 4px;
118
+    .splitLine{
119
+      width: 100%;
120
+      border-bottom: 1px solid #ddd;
121
+    }
122
+  }
123
+}
124
+.topTagBox{
125
+  margin-top: 10px;
126
+  font-size: 14px;
127
+  .span_title{
128
+    font-weight: 600;
129
+    color: #000;
130
+    margin: 10px 0 ;
131
+  }
132
+}
133
+</style>

+ 53 - 0
project/src/components/smartRadar/dialogGroup.vue

@@ -0,0 +1,53 @@
1
+<template>
2
+  <el-dialog
3
+    :append-to-body="true"
4
+    custom-class="channel_code_group"
5
+    :title="propsData.dialogTitle+'分组'"
6
+    :visible.sync="dialogVisible"
7
+    width="30%">
8
+    <div class="dialogBox">
9
+      <div class="lable">分组名称</div>
10
+      <el-input
11
+        size="small"
12
+        placeholder="请输入内容"
13
+        maxlength="8"
14
+        v-model="groupName"
15
+        clearable>
16
+      </el-input>
17
+    </div>
18
+    <span slot="footer" class="dialog-footer">
19
+        <el-button size="mini" @click="dialogVisible=false">取 消</el-button>
20
+        <el-button size="mini" type="primary" @click="dialogVisible=false">确 定</el-button>
21
+      </span>
22
+  </el-dialog>
23
+</template>
24
+
25
+<script>
26
+export default {
27
+  name: "dialogGroup",
28
+  props:['propsData'],
29
+  data(){
30
+    return{
31
+      groupName:'',
32
+      dialogTitle:'',
33
+      dialogVisible:false,
34
+    }
35
+  }
36
+}
37
+</script>
38
+
39
+<style lang="scss">
40
+.channel_code_group{
41
+  .dialogBox{
42
+    display: flex;
43
+    align-items: center;
44
+    .lable{
45
+      font-weight: 600;
46
+      margin-right: 10px;
47
+      font-size: 14px;
48
+      flex-shrink: 0;
49
+    }
50
+  }
51
+}
52
+
53
+</style>

+ 188 - 0
project/src/components/smartRadar/groupList.vue

@@ -0,0 +1,188 @@
1
+<template>
2
+  <div>
3
+    <div class="title">
4
+      <span class="fWeight600 c-000 f14">雷达分组</span>
5
+      <span class="addGroupBox" @click="$refs.dialogGroupRef.dialogVisible = true">
6
+        <i class="el-icon-plus f12"></i>
7
+        添加分组
8
+      </span>
9
+    </div>
10
+    <div class="listBox">
11
+
12
+      <div class="item_css" :class="[acIdx==null? 'ac_css' : '']" @click="itemClick(null)"><i class="el-icon-folder"></i>全部雷达</div>
13
+      <draggable class="syllable_ul" element="ul"
14
+                 :list="tableData"
15
+                 :emptyInsertThreshold="0"
16
+                 :options="{group:'name',
17
+                 animation:200,
18
+                 ghostClass:'ghostClass',
19
+                 dragClass:'dragClass'}">
20
+        <div v-for="(item,index) in tableData" :key="item.id" class="item_css"
21
+             @click="itemClick(item.id)"
22
+             :class="[acIdx==item.id ? 'ac_css' : '']">
23
+          <i class="el-icon-folder"></i>
24
+          <span>{{item.name ? item.name : '-'}}</span>
25
+          <span class="lMarauto">
26
+  <!--          <span class="c-ddd">{{item.nums||item.nums==0 ? item.nums : '-'}}</span>-->
27
+
28
+            <el-dropdown @command="handleCommand">
29
+              <span class="el-dropdown-link">
30
+                <i class="el-icon-more"></i>
31
+              </span>
32
+              <el-dropdown-menu slot="dropdown" >
33
+                <el-dropdown-item :command="'editName/'+item.id+'/'+item.name">修改名称</el-dropdown-item>
34
+                <el-dropdown-item :command="'deleGroup/'+item.id">删除分组</el-dropdown-item>
35
+              </el-dropdown-menu>
36
+            </el-dropdown>
37
+
38
+          </span>
39
+        </div>
40
+      </draggable>
41
+    </div>
42
+
43
+    <dialogGroup
44
+      ref="dialogGroupRef"
45
+      :propsData="{
46
+      dialogTitle:dialogTitle
47
+    }"></dialogGroup>
48
+  </div>
49
+</template>
50
+
51
+<script>
52
+import order from '@/components/mixins/order'
53
+import dialogGroup from './dialogGroup.vue'
54
+import draggable from "vuedraggable"
55
+export default {
56
+  name: "groupList",
57
+  mixins:[order],
58
+  components:{
59
+    dialogGroup,
60
+    draggable
61
+  },
62
+  data(){
63
+    return{
64
+      dialogTitle:'',
65
+      acIdx:null,
66
+      tableData:[
67
+        {
68
+          id:0,
69
+          name:'全部自定义可拖动的',
70
+          nums:0,
71
+          canEdit:false
72
+        },
73
+        {
74
+          id:1,
75
+          name:'默认分组zidingyi',
76
+          nums:0,
77
+          canEdit:false
78
+        },
79
+        {
80
+          id:2,
81
+          name:'自定义分组',
82
+          nums:0,
83
+          canEdit:true
84
+        },
85
+        {
86
+          id:3,
87
+          name:'自定义分组2',
88
+          nums:0,
89
+          canEdit:true
90
+        },
91
+        {
92
+          id:4,
93
+          name:'自定义分组5',
94
+          nums:0,
95
+          canEdit:true
96
+        }
97
+      ]
98
+
99
+    }
100
+  },
101
+  methods:{
102
+    //下移报错,置顶,置地错误
103
+    handleCommand(command){
104
+      var eventArr = command.split('/'),//0是点击名字,1是id,2是分组名(仅修改名称有)
105
+        eventName = eventArr[0],
106
+         id = eventArr[1],
107
+        name = eventArr[2]
108
+      if(eventName == 'editName'){
109
+        this.editGroup(name)
110
+      }else if(eventName == 'deleGroup'){
111
+        this.deleGroup(id)
112
+      }
113
+    },
114
+    editGroup(name){//修改分组
115
+      this.$nextTick(()=>{
116
+        this.dialogTitle = '修改'
117
+        this.$refs.dialogGroupRef.groupName = name
118
+        this.$refs.dialogGroupRef.dialogVisible = true
119
+      })
120
+    },
121
+    deleGroup(id){//删除分组
122
+      this.$confirm('此操作将永久删除该分组, 是否继续?', '提示', {
123
+        confirmButtonText: '确定',
124
+        cancelButtonText: '取消',
125
+        type: 'warning'
126
+      }).then(() => {
127
+        this.listArrs.forEach((item,idx)=>{
128
+          if(item.id == id){
129
+            this.listArrs.splice(idx,1)
130
+          }
131
+        })
132
+
133
+      })
134
+    },
135
+
136
+    itemClick(id){
137
+      this.acIdx = id
138
+    },
139
+    showMore(){
140
+
141
+    }
142
+  }
143
+}
144
+</script>
145
+
146
+<style lang="scss" scoped>
147
+.ghostClass{
148
+  font-weight: 600;
149
+}
150
+.title{
151
+  padding: 10px;
152
+  display: flex;
153
+  align-items: center;
154
+  justify-content: space-between;
155
+  .addGroupBox{
156
+    color: #00b38a;
157
+    font-size: 13px;
158
+    cursor: pointer;
159
+
160
+  }
161
+}
162
+.listBox{
163
+  margin-top: 10px;
164
+  .item_css{
165
+    display: flex;
166
+    align-items: center;
167
+    padding: 15px 10px;
168
+    font-size: 14px;
169
+    cursor: pointer;
170
+    border-left: 2px solid transparent;
171
+    .el-icon-folder{
172
+      margin-right: 4px;
173
+      color: #00b38a;
174
+    }
175
+    .el-icon-more{
176
+      //transform:rotate(90deg);
177
+      font-size: 12px;
178
+      color: #999;
179
+      cursor: pointer;
180
+    }
181
+  }
182
+  .ac_css,.item_css:hover{
183
+    border-left: 2px solid #00b38a;
184
+    background-color: rgba(0,179,138,0.1);
185
+  }
186
+
187
+}
188
+</style>

+ 117 - 0
project/src/components/smartRadar/index.vue

@@ -0,0 +1,117 @@
1
+<template>
2
+  <div class="con">
3
+    <div class="searchBox">
4
+      <el-button type="primary" size="mini" @click="createdchannel_code">新建智能雷达</el-button>
5
+      <self-input label_name="搜索雷达" @inputChange='(val)=>{radar_val = val;initFlag=!initFlag}'></self-input>
6
+      <div class="reset" @click="resetEvent">重置</div>
7
+    </div>
8
+    <div class="mainBox">
9
+      <div class="groupBox">
10
+        <groupList></groupList>
11
+      </div>
12
+      <div class="tableBox">
13
+        <publicTable
14
+          :propsData="{
15
+            desCol:desCol,
16
+            source:'radarIndex',
17
+            initFlag:initFlag,
18
+            radar_val:radar_val
19
+          }"
20
+          ></publicTable>
21
+      </div>
22
+    </div>
23
+  </div>
24
+</template>
25
+
26
+<script>
27
+import selfInput from '@/components/assembly/screen/input.vue'
28
+import publicTable from './publicTable.vue'
29
+import groupList from './groupList.vue'
30
+export default {
31
+  name: "codeIndex",
32
+  components:{
33
+    publicTable,
34
+    selfInput,
35
+    groupList
36
+  },
37
+  data() {
38
+    return {
39
+      initFlag:false,
40
+      radar_val:'',
41
+      desCol:[
42
+        { prop: "name", label: "名称" },
43
+        { prop: "assign_count", label: "类型" },
44
+        { prop: "waiting_add_count", label: "分组" },
45
+        { prop: "waiting_add_count", label: "客户标签" },
46
+        { prop: "passed_count", label: "总访问人数",},
47
+        { prop: "passed_count", label: "总发送次数",},
48
+        { prop: "passed_count", label: "添加时间",}
49
+      ],
50
+    }
51
+  },
52
+  methods:{
53
+    resetEvent () {//重置
54
+      this.initFlag = !this.initFlag
55
+      this.radar_val = ''
56
+    },
57
+    createdchannel_code(){//新建渠道活码
58
+      this.$router.push({path:'/createRadar'})
59
+    }
60
+  }
61
+}
62
+</script>
63
+
64
+<style lang="scss" scoped>
65
+.con{
66
+  padding-right: 10px;
67
+  .searchBox{
68
+    display: flex;
69
+    align-items: center;
70
+    background-color: #fff;
71
+    padding: 5px 10px ;
72
+    position: relative;
73
+    .reset {
74
+      width: 80px;
75
+      height: 30px;
76
+      background: #00b38a;
77
+      border-radius: 100px 3px 3px 3px;
78
+      border: 1px solid #d2d2d2;
79
+      color: #ffffff;
80
+      font-size: 14px;
81
+      line-height: 30px;
82
+      text-align: center;
83
+      position: absolute;
84
+      bottom: 0;
85
+      right: 0;
86
+      letter-spacing: 2px;
87
+      cursor: pointer;
88
+    }
89
+  }
90
+  .mainBox{
91
+    display: flex;
92
+    align-items: flex-start;
93
+    margin-top: 10px;
94
+    .groupBox{
95
+      width: 20%;
96
+      background-color: #fff;
97
+      flex-shrink: 0;
98
+      margin-right: 10px;
99
+      height: calc(100vh - 60px - 62px - 20px - 10px);
100
+      overflow-y: auto;
101
+      &::-webkit-scrollbar{
102
+        width: 3px;
103
+      }
104
+    }
105
+    .tableBox{
106
+      flex: 1;
107
+      background-color: #fff;
108
+      height: calc(100vh - 60px - 62px - 20px - 10px);
109
+      overflow-y: auto;
110
+      &::-webkit-scrollbar{
111
+        width: 3px;
112
+      }
113
+    }
114
+  }
115
+}
116
+
117
+</style>

+ 125 - 0
project/src/components/smartRadar/publicTable.vue

@@ -0,0 +1,125 @@
1
+<template>
2
+  <div>
3
+  <!-- table -->
4
+    <el-table v-loading="loading" ref="multipleTable"
5
+              border
6
+              :height='height'
7
+              :data="tableData"
8
+              tooltip-effect="dark"
9
+              :header-cell-style="()=>{return { backgroundColor: '#f9f9f9 !important' }}"
10
+              style="width: 100%">
11
+      <template v-for="item in propsData.desCol">
12
+        <el-table-column :key="item.prop" :label="item.label" align="center"
13
+                         :show-overflow-tooltip="item.showOverTooltip"
14
+                         :min-width="item.min_width?item.min_width:120">
15
+          <template #header v-if="item.tooltip">
16
+            {{item.label?item.label:'-'}}
17
+            <el-tooltip class="disinblock" :content="item.tooltip" placement="top">
18
+              <i class="el-icon-question"></i>
19
+            </el-tooltip>
20
+          </template>
21
+          <template slot-scope="scope">
22
+            <div>{{scope.row[item.prop] ? scope.row[item.prop] : '-'}}</div>
23
+          </template>
24
+        </el-table-column>
25
+      </template>
26
+
27
+      <template v-if="propsData.source=='radarIndex'">
28
+        <el-table-column label="操作" align="center" min-width="180px">
29
+          <template slot-scope="scope">
30
+              <div class="flex">
31
+                <div class="c-00B38A pointer">编辑</div>
32
+                <div class="c-00B38A pointer lMar8">删除</div>
33
+                <div class="c-00B38A pointer lMar8" @click="goDataAanlyse(scope.row.id)">分析数据</div>
34
+              </div>
35
+          </template>
36
+        </el-table-column>
37
+      </template>
38
+    </el-table>
39
+    <div class="pagination" v-show="total>0">
40
+      <el-pagination background :current-page="page" @current-change="handleCurrentChange" layout="prev, pager, next" :page-count='Number(pages)'>
41
+      </el-pagination>
42
+    </div>
43
+  </div>
44
+</template>
45
+
46
+<script>
47
+export default {
48
+  name: "publicTable",
49
+  props:['propsData'],
50
+  data(){
51
+    return{
52
+      loading: false,
53
+      dataLoading: false,
54
+      page: 1,
55
+      pages: 0,
56
+      total: 0,
57
+      page_size: 20,
58
+      height: '',
59
+      tableData:[]
60
+    }
61
+  },
62
+  watch:{
63
+    'propsData.initFlag'(){
64
+      this.init(1)
65
+    }
66
+  },
67
+  created() {
68
+    this.height = document.documentElement.clientHeight - 300 > 400 ? document.documentElement.clientHeight - 300 : 400
69
+    this.init(1)
70
+  },
71
+  methods:{
72
+    goDataAanlyse(id){
73
+      this.$router.push('/radar_dataAnalyse/'+id)
74
+    },
75
+    init (page, type) {
76
+      if (type != 'export') {
77
+        this.page = page ? page : this.page;
78
+      } else {
79
+        if (this.total == 0) {
80
+          this.$message({
81
+            message: '暂无数据可导出',
82
+            type: "warning"
83
+          })
84
+          return
85
+        }
86
+      }
87
+      this.loading = true
88
+      this.$axios.get(this.URL.BASEURL + this.URL.batchAddCustomer_statistic, {
89
+        params:{
90
+          start_date: '2022-05-14',
91
+          end_date: '2022-06-13',
92
+          page: type == 'export' ? 1 : this.page,
93
+          pagesize: type == 'export' ? this.$store.state.exportNumber : this.page_size,
94
+        }
95
+      }).then((res) => {
96
+        var res = res.data
97
+        this.loading = false
98
+        if (res && res.errno == 0) {
99
+          if (type == 'export') {
100
+            this.exportEvent(res.rst.data)
101
+          } else {
102
+            this.tableData = res.rst.data
103
+            this.total = res.rst.pageInfo.total;
104
+            this.pages = res.rst.pageInfo.pages;
105
+          }
106
+        } else if (res.errno != 4002) {
107
+          this.$message({
108
+            message: res.err,
109
+            type: "warning"
110
+          })
111
+        }
112
+      }).catch((err) => {
113
+        this.loading = false
114
+      });
115
+    },
116
+    handleCurrentChange (val) {
117
+      this.init(val)
118
+    },
119
+  }
120
+}
121
+</script>
122
+
123
+<style lang="scss" scoped>
124
+
125
+</style>

+ 33 - 0
project/src/router/allRouter.js

@@ -41,6 +41,9 @@ const importRecordDetial = () => import(/* webpackChunkName: 'importRecordDetial
41 41
 const codeIndex = () => import(/* webpackChunkName: 'codeIndex' */ '@/components/channelCode/codeIndex.vue')
42 42
 const code_dataAnalyse = () => import(/* webpackChunkName: 'dataAnalyse' */ '@/components/channelCode/dataAnalyse.vue')
43 43
 const createChannelCode = () => import(/* webpackChunkName: 'createChannelCode' */ '@/components/channelCode/createChannelCode.vue')
44
+const codeIndex_radar = () => import(/* webpackChunkName: 'codeIndex_radar' */ '@/components/smartRadar/index.vue')
45
+const radar_dataAnalyse = () => import(/* webpackChunkName: 'radar_dataAnalyse' */ '@/components/smartRadar/dataAnalyse.vue')
46
+const createRadar = () => import(/* webpackChunkName: 'createRadar' */ '@/components/smartRadar/createRadar.vue')
44 47
 //
45 48
 
46 49
 // name与菜单配置的页面路由一致
@@ -103,6 +106,36 @@ export var allRouter = [
103 106
         }
104 107
       },
105 108
       {
109
+        path: 'codeIndex_radar',
110
+        name: 'codeIndex_radar',
111
+        component: codeIndex_radar,
112
+        meta: {
113
+          keepAlive: false,
114
+          isLogin: true,
115
+          title: '智能雷达'
116
+        }
117
+      },
118
+      {
119
+        path: 'radar_dataAnalyse/:id',
120
+        name: 'codeIndex_radar',
121
+        component: radar_dataAnalyse,
122
+        meta: {
123
+          keepAlive: false,
124
+          isLogin: true,
125
+          title: '数据分析'
126
+        }
127
+      },
128
+      {
129
+        path: 'createRadar',
130
+        name: 'codeIndex',
131
+        component: createRadar,
132
+        meta: {
133
+          keepAlive: false,
134
+          isLogin: true,
135
+          title: '新建智能雷达'
136
+        }
137
+      },
138
+      {
106 139
         path: 'codeIndex',
107 140
         name: 'codeIndex',
108 141
         component: codeIndex,