Przeglądaj źródła

Merge branch 'dev/v1.0_fu' of dataservice/datatag into feature/v1.0

fuwencai 1 rok temu
rodzic
commit
d32e742be3

+ 8 - 8
CMPlatform/config.json

@@ -225,23 +225,23 @@
   "need_projectid_appid": [
     "jyFApXQQIEAw5TTUZOMBpD"
   ],
-  "redis_addrs": "datag=192.168.3.149:1712,session=192.168.3.149:1712,other=192.168.3.11:1712,ent=192.168.3.149:1712",
+  "redis_addrs": "datag=192.168.3.149:1712,session=192.168.3.149:1712,other=192.168.3.149:1712,ent=192.168.3.149:1712",
   "jyPushMysql": {
     "username": "root",
-    "password": "Topnet123",
-    "address": "192.168.3.149:3306",
+    "password": "=PDT49#80Z!RVv52_z",
+    "address": "192.168.3.14:4000",
     "dbName": "jianyu"
   },
   "jyMysql": {
     "username": "root",
-    "password": "Topnet123",
-    "address": "192.168.3.149:3306",
+    "password": "=PDT49#80Z!RVv52_z",
+    "address": "192.168.3.14:4000",
     "dbName": "jianyu"
   },
   "pushMysql": {
     "username": "root",
-    "password": "Topnet123",
-    "address": "192.168.3.149:3306",
+    "password": "=PDT49#80Z!RVv52_z",
+    "address": "192.168.3.14:4000",
     "dbName": "jianyu",
     "maxIdleConns": 2
   },
@@ -305,4 +305,4 @@
   ],
   "rpcServer_jy": "192.168.3.206:8699",
   "rpcServer_project": "127.0.0.1:7979"
-}
+}

+ 174 - 3
CMPlatform/web/templates/com/modal.html

@@ -78,6 +78,113 @@
         </div>
     </div><!-- /.modal -->
 </div>
+<!--新增精准筛选规则模态框-->
+<div class="modal fade" id="modal-add-exactRule" tabindex="-1" role="dialog" aria-hidden="true">
+    <div class="modal-dialog" style="width: 40%">
+        <div class="modal-content">
+            <div class="modal-header">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true" >&times;</button>
+                    <div class="edit-form">
+                        <div class="edit-info" style="text-align: center">
+                            <span >新增精准筛选规则</span>
+                        </div>
+                        <div id="insertexactRule">
+
+                        </div>
+                    </div>
+         <div style="text-align: center" id="addExactRuleButton">
+             <a onclick="addExactRule()" style="margin: 0 auto">+新增</a>
+         </div>
+
+                </div>
+               <div class="modal-footer">
+                   <button type="button" class="btn btn-default" data-dismiss="modal" >取消</button>
+                   <button type="button" class="btn btn-primary" onclick="add_exactRule_save()">确定</button>
+               </div>
+            </div>
+        </div>
+    </div><!-- /.modal -->
+</div>
+<div class="modal fade" id="modal-edit-exactRule" tabindex="-1" role="dialog" aria-hidden="true">
+    <div class="modal-dialog" style="width: 40%">
+        <div class="modal-content">
+            <div class="modal-header">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true" >&times;</button>
+                    <div class="edit-form">
+                        <div class="edit-info" style="text-align: center">
+                            <span >编辑精准筛选规则</span>
+                        </div>
+                        <div id="editexactRule">
+                            <input style="display: none" id="editexactRuleId">
+                            <!--规则1 -->
+                            <div class="editexactRule-form exact-rule-1">
+                                <div class="form-group" >
+                                    <label class="col-sm-4 control-label"><span style="color:red;">* </span>关键词分组:</label>
+                                    <div class="col-sm-8">
+                                        <select class="form-control groupSelect" name="groupSelect">
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label class="col-sm-4 control-label"><span style="color:red;">* </span>出现次数>=</label>
+                                    <div class="col-sm-8">
+                                        <input  type='number' type="number" min='0' class="form-control" name="count" placeholder="请输入次数">
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label class="col-sm-4 control-label"><span style="color:red;">* </span>匹配方式</label>
+                                    <div class="col-sm-8">
+                                        <select class="form-control selectpicker" multiple name="matchWay">
+<!--                                            <option value="title" selected>标题</option>-->
+<!--                                            <option value="content">正文</option>-->
+                                        </select>
+                                    </div>
+                                </div>
+                            </div>
+
+                            <!--规则2 -->
+                            <div class="editexactRule-form exact-rule-2" style="display: none">
+                                <div class="form-group" >
+                                    <label class="col-sm-4 control-label"><span style="color:red;">* </span>关键词分组:</label>
+                                    <div class="col-sm-8">
+                                        <select class="form-control groupSelect" name="groupSelect">
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label class="col-sm-4 control-label"><span style="color:red;">* </span>出现次数>=</label>
+                                    <div class="col-sm-8">
+                                        <input  type='number' min='0'  class="form-control" name="count" placeholder="请输入次数">
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label class="col-sm-4 control-label"><span style="color:red;">* </span>匹配方式</label>
+                                    <div class="col-sm-8">
+                                        <select class="form-control selectpicker" multiple name="matchWay">
+    <!--                                        <option value="title" selected>标题</option>-->
+    <!--                                        <option value="content">正文</option>-->
+                                        </select>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+         <div style="text-align: center" id="editExactRuleButton">
+             <a onclick="editExactRule()" style="margin: 0 auto">+新增</a>
+         </div>
+
+                </div>
+               <div class="modal-footer">
+                   <button type="button" class="btn btn-default" data-dismiss="modal" >取消</button>
+                   <button id="edit_exactRule_save" type="button" class="btn btn-primary" onclick="edit_exactRule_save()">确定</button>
+               </div>
+            </div>
+        </div>
+    </div><!-- /.modal -->
+</div>
+
 
 <!-- 选择采购单位行业模态框 -->
 <div class="modal fade" id="modal-select-buyer" tabindex="-1" role="dialog" aria-hidden="true">
@@ -234,7 +341,7 @@
                                 <label class="col-sm-2 control-label">分组</label>
                                 <div class="col-sm-10">
                                     <select class="form-control selectpicker" id="selectGroups"></select>
-                                </div>                    
+                                </div>
                             </div>
                         </form>
                     </div>
@@ -332,7 +439,16 @@
                     <div id="testExactRule" class="exactRuleShow" style="display: none">
                         <label class="control-label">精准筛选规则</label><br/>
                         <div id="checkExactResult">验证结果:通过</div>
-                        <div id="checkExactRule">规则:title_A > 0 and content_A > 0</div><br/>
+                        <div id="checkExactRule">规则:
+                            <table id="checkExactRuleTable" class="table table-bordered">
+                                <thead>
+                                <tr>
+                                    <th>编号</th>
+                                    <th>关键词分组匹配条件</th>
+                                </tr>
+                                </thead>
+                            </table>
+                        </div><br/>
                     </div>
                     <div id="testKeyDiv" style="display: none">
                         <label class="control-label">关键词规则</label>
@@ -358,6 +474,61 @@
 </div>
 
 <script>
+    var exactRuleBool = false
+    var ruleHtml = "<div class=\"#b#-form  exact-rule-1 exact-rule-class #a#  #0#\" >" +
+        "<div class=\"form-group\" >" +
+        "<label class=\"col-sm-4 control-label\"><span style=\"color:red;\">* </span>关键词分组:</label>" +
+        "<div class=\"col-sm-8\">" +
+        "<select class=\"form-control groupSelect\" name=\"groupSelect\">" +
+        "#1#" +
+        "</select>" +
+        "</div>" +
+        "</div>" +
+        "<div class=\"form-group\">" +
+        "<label class=\"col-sm-4 control-label\"><span style=\"color:red;\">* </span>出现次数>=</label>" +
+        "<div class=\"col-sm-8\">" +
+        "<input  type='number' min='0'  class=\"form-control\" name=\"count\" placeholder=\"请输入次数\" value=\"#2#\">" +
+        "</div>" +
+        "</div>" +
+        "<div class=\"form-group\">" +
+        "<label class=\"col-sm-4 control-label\"><span style=\"color:red;\">* </span>匹配方式</label>" +
+        "<div class=\"col-sm-8\">" +
+        "<select class=\"form-control matchWay selectpicker\"  multiple name=\"matchWay\">" +
+        "#3#" +
+        "</select>" +
+        "</div>" +
+        "</div>" +
+        "<div class=\"form-group division-line\">" +
+        "<label class=\"col-sm-4 control-label\"><span style=\"color:red;\"></span></label>" +
+        "<div class=\"col-sm-8\">" +
+        "</div>" +
+        "</div>" +
+        "</div>"
+    //弹窗内容编辑及新增
+    function ruleHtmlFunc(className,mark,rule) {//count
+        if (ruleGroupList.length===0){
+            showGroupListData()
+        }
+        var count = 1;
+        var phrasesHtml = '';
+        var matchWayHtml = '';
+        var parentClass = rule.replaceAll("#","");
+        for (var i=0;i< ruleGroupList.length;i++){
+            phrasesHtml += "<option value='"+ruleGroupList[i]["name"]+"'>"+ruleGroupList[i]["name"]+"</option>"
+        }
+        for (let key in matchWayMap) {
+            console.log(`${key}: ${matchWayMap[key]}`);
+            var selected = ''
+            if (key=="title"){
+                selected = 'selected = true'
+            }
+            matchWayHtml +="<option value='"+key+"' "+selected+">"+matchWayMap[key]+"</option>"
+        }
+        var ph = ruleHtml.replaceAll("#b#",parentClass).replaceAll("#a#",className).replaceAll("#0#",mark).replaceAll("#1#",phrasesHtml).replaceAll("#2#",count).replaceAll("#3#",matchWayHtml)
+        $(rule).append(ph)
+        // 初始化 selectpicker 插件
+        $('.selectpicker').selectpicker('refresh');
+    }
     //通用标签列表
     function importcomrule() {
         comruletable = $('#comrule').DataTable({
@@ -671,4 +842,4 @@
         $('#keywords').dataTable().fnAddData(d.data.o_rules);
         o_rules = d.data.o_rules;
     }
-</script>
+</script>

+ 445 - 18
CMPlatform/web/templates/private/cuser_rule_edit.html

@@ -16,6 +16,33 @@
         background-color: red;
         font-weight: bold;
     }
+
+    .insertexactRule-form .division-line ,.editexactRule-form .division-line{
+        display: inline-block !important;
+    }
+    .insertexactRule-form .form-group,.editexactRule-form .form-group{
+        display: block;
+        margin-bottom: 1px !important;
+    }
+    .insertexactRule-form .form-group label,.editexactRule-form .form-group label{
+        padding-top: 8px;
+    }
+    .insertexactRule-form .form-group .col-sm-8,.editexactRule-form .form-group .col-sm-8 {
+        margin-bottom: 5px;
+    }
+    .modal-header {
+        border-bottom-color: #fff;
+        padding-bottom: 0px !important;
+    }
+    #addExactRuleButton a {
+        cursor:pointer;
+    }
+    .insertexactRule-form , .editexactRule-form{
+        padding: 10px 10px 0px 10px;
+    }
+    #editExactRuleButton a {
+        cursor: pointer;
+    }
 </style>
 <div class="content-wrapper">
     <section class="content-header">
@@ -67,6 +94,8 @@
                     </li>
                     <li data-mode="guide" class="exactRuleShow" style="display: none"><a href="#tab_3" data-toggle="tab" aria-expanded="false">精准筛选规则</a>
                     </li>
+<!--                    <li data-mode="guide" class="exactRuleShow" style="display: none"><a href="#tab_4" data-toggle="tab" aria-expanded="false">精准筛选规则</a>-->
+<!--                    </li>-->
                     <button class="btn btn-primary btn-sm" style="float: right;margin-top: 4px;margin-right: 10px"
                             onclick="saveTag()"><i class="fa fa-fw fa-file-text fa-lg"></i>保存
                     </button>
@@ -463,24 +492,49 @@
                     <div class="tab-pane" id="tab_3">
                         <div class="box box-primary">
                             <div class="box-header with-border">
-                                <div class="form-group">
-                                    <div class="col-sm-6">
-                                        <textarea name="" id="exactRule" cols="30" rows="10" placeholder="请输入精准筛选规则" style="width: 100%"></textarea>
-                                    </div>
-                                    <div class="col-sm-6">
-                                        编写规则说明:<br/>
-                                        1.应用场景:可根据该篇公告标题或全文,匹配的“关键词分组”个数,确定是否推送该篇公告。<br/>
-                                        2.规则释义:<br/>
-                                        (1)查找范围:title→公告标题,content→公告全文;not为不包含的关系;<br/>
-                                        (2)查找值:关键词分组名;<br/>
-                                        (3)查找范围和查找值用“_”连接;<br/>
-                                        (3)查找条件:数量条件可用>=<;and→且关系,or→或关系;1组条件用()。<br/>
-                                        3.规则示例(分组名为A和B):(title_A>0 and not content_B) or title_B>4 or (content_A and content_B>1) ,即该篇公告标题包含关键词分组A且公告全文文不包含关键词分组B时即推送,或该篇公告全文包含4个关键词分组B时即推送,或该篇公告全文包含关键词分组A2个及以上且关键词分组B2个及以上时即推送
-                                    </div>
+                                <div class="col-sm-10">
+                                <h5>说明:可根据公告匹配的“关键词分组”个数,确定是否推送该简公告;符合以下其中1条规则即推送</h5>
                                 </div>
+                                <div class="col-sm-2">
+                                    <button class="btn btn-twitter btn-sm" style="float: right;margin-top: 4px;margin-right: 10px"
+                                            onclick="addExactRuleShow()"><i class="fa fa-fw fa-file-text fa-lg"></i>新增
+                                    </button>                                </div>
+                            </div>
+                            <div>
+                                <table id="exactRuleTable" class="table table-bordered">
+                                    <thead>
+                                    <tr>
+                                        <th>编号</th>
+                                        <th>关键词分组匹配条件</th>
+
+                                        <th>操作</th>
+                                    </tr>
+                                    </thead>
+                                </table>
                             </div>
                         </div>
                     </div>
+<!--                    <div class="tab-pane" id="tab_4">-->
+<!--                        <div class="box box-primary">-->
+<!--                            <div class="box-header with-border">-->
+<!--                                <div class="form-group">-->
+<!--                                    <div class="col-sm-6">-->
+<!--                                        <textarea name="" id="exactRule" cols="30" rows="10" placeholder="请输入精准筛选规则" style="width: 100%"></textarea>-->
+<!--                                    </div>-->
+<!--                                    <div class="col-sm-6">-->
+<!--                                        编写规则说明:<br/>-->
+<!--                                        1.应用场景:可根据该篇公告标题或全文,匹配的“关键词分组”个数,确定是否推送该篇公告。<br/>-->
+<!--                                        2.规则释义:<br/>-->
+<!--                                        (1)查找范围:title→公告标题,content→公告全文;not为不包含的关系;<br/>-->
+<!--                                        (2)查找值:关键词分组名;<br/>-->
+<!--                                        (3)查找范围和查找值用“_”连接;<br/>-->
+<!--                                        (3)查找条件:数量条件可用>=<;and→且关系,or→或关系;1组条件用()。<br/>-->
+<!--                                        3.规则示例(分组名为A和B):(title_A>0 and not content_B) or title_B>4 or (content_A and content_B>1) ,即该篇公告标题包含关键词分组A且公告全文文不包含关键词分组B时即推送,或该篇公告全文包含4个关键词分组B时即推送,或该篇公告全文包含关键词分组A2个及以上且关键词分组B2个及以上时即推送-->
+<!--                                    </div>-->
+<!--                                </div>-->
+<!--                            </div>-->
+<!--                        </div>-->
+<!--                    </div>-->
                 </div>
             </div>
         </div>
@@ -519,6 +573,8 @@
     var selectIndex = [];               //选中的编号
     var setValue = 0;                   // 4: 关键词匹配方式,6:附加词匹配方式,8:排除词匹配方式,9:采购单位,10:公告行业, 2:全局采购单位类型, 3:全局公告行业
     var state = 1;
+    var exactRuleTableArr =[];// 临时数组 用于存放规则字符串转换后的数据
+    var testexactRuleTableArr =[];// 临时数组 用于存放数据验证规则字符串转换后的数据
     $(document).ready(function () {
         var name1 = {{(session "user").name}};
         if (name1 != dataMap.s_updateuser) {
@@ -917,6 +973,42 @@
                 }
             }]
         });
+        exactRuleTableArr = exactRuleStrToArr( dataMap["s_exactRule"])
+        // 精准筛选规则表格
+        $('#exactRuleTable').DataTable({
+            "paging": false,
+            "lengthChange": false,
+            "searching": false,
+            "ordering": false,
+            "info": true,
+            "autoWidth": false,
+            "language": {
+                "url": "/dist/js/dataTables.chinese.lang"
+            },
+            "fnDrawCallback": function () {
+                this.api().column(0).nodes().each(function (cell, i) {
+                    cell.innerHTML = i + 1;
+                });
+                this.api().column(2).nodes().each(function (cell, i) {
+                    cell.innerHTML = '<div>' +
+                        '<a onclick="editExacRuleClick(\'' + i + '\')" >编辑</a>&nbsp&nbsp' +
+                        '<a onclick="delExacRuleClick(\'' + i + '\')" >删除</a>&nbsp&nbsp' +
+                        '</div>';
+                });
+            },
+            "data": exactRuleTableArr,
+            "columns": [
+                {"data": null},
+                {
+                    "data": function (row) {
+                        return exactRuleDataFormat(row)
+                    }
+                },
+                {
+                    "data": null
+                },
+            ]
+        });
     });
 
     $('#province').selectpicker({
@@ -1678,7 +1770,7 @@
         dataMap["s_globaladdkey"] = $('#g_addkey').val();
         dataMap["s_globalnotkey"] = $('#g_notkey').val();
         dataMap["s_globalclearkey"] = $('#s_globalclearkey').val();
-        dataMap["s_exactRule"] = $('#exactRule').val();
+        dataMap["s_exactRule"] = exactRuleArrToStr()
         if (dataMap["s_customer"] == "" || dataMap["s_name"] == "" || dataMap["s_salesperson"] == "" || dataMap["s_serverperson"] == "") {
             alert("请填写必须字段!")
             return
@@ -1806,7 +1898,7 @@
                     } else {
                         showTip("数据生成失败", 12000);
                     }
-            
+
                 },
                 error: function (r) {
                     com.maskHide();
@@ -2105,7 +2197,7 @@
             $('#dataCount').html(str);
         }
     }
-    
+
     function produceAll(){
         $('#modal-preview').modal("hide");
         produceData("2");
@@ -2531,7 +2623,33 @@
             data: {"title": title, "detail": detail},
             success: function (r) {
                 if (r.exactRule != ""){
-                    $("#checkExactRule").text("规则:"+r.exactRule)
+                    testexactRuleTableArr = exactRuleStrToArr( r.exactRule)
+                    $('#checkExactRuleTable').DataTable({
+                        "paging": false,
+                        "lengthChange": false,
+                        "searching": false,
+                        "ordering": false,
+                        "info": true,
+                        "autoWidth": false,
+                        "language": {
+                            "url": "/dist/js/dataTables.chinese.lang"
+                        },
+                        "fnDrawCallback": function () {
+                            this.api().column(0).nodes().each(function (cell, i) {
+                                cell.innerHTML = i + 1;
+                            });
+                        },
+                        "data": testexactRuleTableArr,
+                        "columns": [
+                            {"data": null},
+                            {
+                                "data": function (row) {
+                                    return exactRuleDataFormat(row)
+                                }
+                            }
+                        ]
+                    });
+
                 }else{
                     $("#checkExactRule").text("规则:")
                 }
@@ -2706,4 +2824,313 @@
         })
     }
     //分组管理
+    var ruleGroupList = new Array()
+    // 精准筛选规则-新增按钮点击方法
+    function addExactRuleShow(){
+        // 判断是否设置关键词
+        if (ruleGroupList.length===0){
+            showGroupListData()
+            if (ruleGroupList.length===0){
+                showTip("请先设置关键词规则分组")
+                return
+            }
+        }
+        // 判断是否设置关键词匹配方式
+        // debugger
+        //  判断是否设置关键词
+        if (o_rules.length===0) {
+            showTip("请先设置关键词")
+            return
+        }
+        //  判断是否设置关键词匹配方式
+        if (!hasMatchWay()){
+            showTip("请先设置关键词匹配方式")
+            return
+        }
+        //初始化
+        $("#insertexactRule").html("");
+        $("#addExactRuleButton").show();
+        // 新增精准筛选规则弹框
+       // 请求分组列表接口获取数据
+        ruleHtmlFunc("insert-class","","#insertexactRule")
+        $("#modal-add-exactRule").modal("show");
+    }
+    // 精准筛选规则-新增页面 +新增按钮
+    function addExactRule(){
+        ruleHtmlFunc("insert-class","","#insertexactRule")
+        if ($('.exact-rule-class').length > 3){
+            $("#addExactRuleButton").hide()
+        }
+    }
+    // 精准筛选规则-新增精准匹配规则保存按钮点击事件
+    function add_exactRule_save(){
+        // 获取值
+        let ruleArr = [];
+        let checkObj = {};
+        let formList =  $("#insertexactRule .insertexactRule-form");
+        formList.each(function() {
+            var groupName = $(this).find('select[name="groupSelect"]').val();
+            var count = $(this).find('input[name="count"]').val();
+            var matchWayValue = $(this).find('select[name="matchWay"]').val();
+            if (groupName===""||matchWayValue.length===0||count===""){
+                // todo
+                return true;
+            }
+            for (let j = 0; j < matchWayValue.length; j++) {
+                let rule =      {
+                    "group":groupName,"match_way":matchWayValue[j],"count":count
+                }
+                if(checkObj[groupName+"_"+count+"_"+matchWayValue[j]]){
+                    return  true
+                }
+                checkObj[groupName+"_"+count+"_"+matchWayValue[j]] = matchWayValue[j]
+                ruleArr.push(rule)
+            }
+            console.log(matchWayValue);
+        });
+        if (ruleArr.length===0){
+            showMsg("规则已存在!")
+            return
+        }
+        // 保存到exactRuleTableArr 临时数组
+        exactRuleTableArr.push(ruleArr)
+        $('#exactRuleTable').dataTable().fnClearTable();
+        $('#exactRuleTable').dataTable().fnAddData(exactRuleTableArr);
+        if (exactRuleTableArr.length == 0) {
+            $('#exactRuleTable').dataTable().fnClearTable();
+        }
+        $("#modal-add-exactRule").modal("hide");
+
+    }
+    // 精准筛选规则-临时数组转换成规则字符串
+    // [[{"group":"A","match_way":"content","count":5},{},{}],[]]
+    // (title_A>0 and content_B>8) or title_B>4 or (content_A>7 and content_B>1)
+    function exactRuleArrToStr(){
+        let ruleStrArr = []
+        for (let i = 0; i < exactRuleTableArr.length; i++) {
+            let rulesArr = [];
+            for (let j = 0; j < exactRuleTableArr[i].length; j++) {
+                let count =exactRuleTableArr[i][j].count-1
+                let group = exactRuleTableArr[i][j].group
+                let match_way = exactRuleTableArr[i][j].match_way
+                let rule = match_way+"_"+group+">"+count
+                rulesArr.push(rule)
+            }
+            if (rulesArr.length>1){ // 拼接小括号
+                ruleStrArr.push("("+rulesArr.join(" and ")+")")
+            }else {
+                if (rulesArr.length>0){
+                    ruleStrArr.push(rulesArr[0])
+                }
+            }
+        }
+        return  ruleStrArr.join(" or ")
+    }
+    // (title_A>0 and content_B>8) or title_B>4 or (content_A>7 and content_B>1)
+    // 精准筛选规则-规则字符串转换成临时数组   仅支持这种格式 (title_A>0 and  content_B>8) or title_B>4 or (content_A>7 and content_B>1)
+    // 分组名称不要包含公式中的符号 :  下划线、>、()、or、and
+    function exactRuleStrToArr( exactRuleStr)  {
+        if (exactRuleStr===undefined||exactRuleStr===""){
+            return []
+        }
+        let exactRuleTableArrTmp = []
+        // let exactRuleStr = "(title_A>0 and content_B>8) or title_B>4 or (content_A>7 and content_B>1)"
+        let exactRuleList = exactRuleStr.split(" or ") // 分割成单条规则
+        for (let i=0; i< exactRuleList.length; i++) {
+            let exactRuleTmp = exactRuleList[i]
+            let rulesArr = [];
+            if (exactRuleTmp.startsWith("(")) {
+                exactRuleTmp = exactRuleTmp.slice(1, -1) //去掉首尾的括号
+            }
+            let singleRuleArr = exactRuleTmp.split(" and ")  // 分割单条规则中的数据
+            for (let j=0;j<singleRuleArr.length;j++) {
+                let singleRule  =singleRuleArr[j]
+                // 匹配方式
+                 let singleRuleSplit = singleRule.split("_")
+                 if (singleRuleSplit.length<2){
+                     console.log("singleRuleSplit 长度不够",singleRuleSplit)
+                     return
+                 }
+                 let matchWay = singleRuleSplit[0] // 第一位是匹配方式
+                 // 然后接着分割出分组名称和次数  使用 _
+                 let singleRuleSplit2 = singleRuleSplit[1].split(">")
+                if (singleRuleSplit2.length<2){
+                    console.log("singleRuleSplit2 长度不够",singleRuleSplit2)
+                    return
+                }
+                let groupName = singleRuleSplit2[0]
+                let count = singleRuleSplit2[1]
+                 // 次数    次数这里要+1  因为展示框里用的是>=  公式里面用的是>
+                 let rule = {
+                     "group":groupName,"match_way":matchWay,"count":parseInt(count)+1
+                 }
+                rulesArr.push(rule)
+            }
+            exactRuleTableArrTmp.push(rulesArr)
+        }
+        return exactRuleTableArrTmp;
+    }
+    var editexactRuleId = 0;
+    const matchWayMap = {
+        "title":"标题匹配",
+        "content":"全文匹配"
+    }
+    // 规则数组转换列表字符串
+    function exactRuleDataFormat(contentArr ){
+        // keyArr 定义数组 维持最后有序
+        let keyArr = []
+        // 合并 标题正文 如果
+        let tmpDict = {}
+        for (let i = 0; i < contentArr.length; i++) {
+            let keyGroupCount = contentArr[i].group+"_"+ contentArr[i].count
+            if (tmpDict.hasOwnProperty(keyGroupCount)){
+                tmpDict[keyGroupCount].match_way.add(matchWayMap[contentArr[i].match_way])
+            }else {
+                let set = new Set();
+                tmpDict[keyGroupCount] = {
+                    "group":contentArr[i].group,"match_way":set.add(matchWayMap[contentArr[i].match_way]),"count":contentArr[i].count
+                }
+                keyArr.push(keyGroupCount)
+
+            }
+        }
+        let str = ""
+        for (let tmpDictKey in keyArr) {
+            str += "关键词分组:"+tmpDict[keyArr[tmpDictKey]].group+",出现次数>="+tmpDict[keyArr[tmpDictKey]].count+",匹配方式:"+Array.from(tmpDict[keyArr[tmpDictKey]].match_way).join(",")+";"
+        }
+        return str
+    }
+    // 删除 点击事件
+    function delExacRuleClick(index) {
+        index = parseInt(index)
+        showConfirm("确定删除?", function () {
+            exactRuleTableArr  =  $.grep(exactRuleTableArr,function (n,i) {
+                return i!==index
+            })
+            $('#exactRuleTable').dataTable().fnClearTable();
+            $('#exactRuleTable').dataTable().fnAddData(exactRuleTableArr);
+            if (exactRuleTableArr.length == 0) {
+                $('#exactRuleTable').dataTable().fnClearTable();
+            }
+        })
+
+    }
+    function showGroupListData(){
+        $.ajax({
+            url: "/service/cuser/groupList",
+            type: "post",
+            data: {"id": dataMap.id},
+            async: false,
+            success: function (r) {
+                if (r.data) {
+                    ruleGroupList=r.data;
+                }
+            }})
+    }
+    // 编辑点击事件
+    function editExacRuleClick(index){
+        $("#editexactRule").html("");
+        $("#editExactRuleButton").show();
+        editexactRuleId = index;
+        // 铺数据
+        let contentArr = exactRuleTableArr[index]
+        // keyArr 定义数组 维持最后有序
+        let keyArr = []
+        // 合并 标题正文
+        let tmpDict = {}
+        for (let i = 0; i < contentArr.length; i++) {
+            let keyGroupCount = contentArr[i].group+"_"+ contentArr[i].count
+            if (tmpDict.hasOwnProperty(keyGroupCount)){
+                tmpDict[keyGroupCount].match_way.add(contentArr[i].match_way)
+            }else {
+                let set = new Set();
+                tmpDict[keyGroupCount] = {
+                    "group":contentArr[i].group,"match_way":set.add(contentArr[i].match_way),"count":contentArr[i].count
+                }
+                keyArr.push(keyGroupCount)
+            }
+        }
+        for (let i = 0; i < keyArr.length; i++) {
+            var keyGroup = tmpDict[keyArr[i]].group;
+            var count = tmpDict[keyArr[i]].count;
+            var matchWay = tmpDict[keyArr[i]].match_way;
+            ruleHtmlFunc("edit-class",keyArr[i],"#editexactRule");
+            $('#editexactRule .'+keyArr[i]+' select[name=groupSelect]').selectpicker('val',keyGroup);
+            $('#editexactRule .'+keyArr[i]+' input[name=count]').val(count);
+            let matchWayArr = Array.from(matchWay);
+            $('#editexactRule .'+keyArr[i]+' select[name=matchWay]').val("").trigger("change").selectpicker('val',matchWayArr);
+        }
+        $("#modal-edit-exactRule").modal("show");
+    }
+    // 编辑保存
+    function edit_exactRule_save(){
+       // let index =  $("#editexactRuleId").text()
+        // 获取数
+        let ruleArr = []
+        let formList =  $("#editexactRule .editexactRule-form")
+        formList.each(function() {
+            var groupName = $(this).find('select[name="groupSelect"]').val();
+            var count = $(this).find('input[name="count"]').val();
+            var matchWayValue = $(this).find('select[name="matchWay"]').val();
+            if (groupName===""||matchWayValue.length===0||count===""){
+                // todo
+                return true;
+            }
+            for (let j = 0; j < matchWayValue.length; j++) {
+                let rule =      {
+                    "group":groupName,"match_way":matchWayValue[j],"count":count
+                }
+                ruleArr.push(rule)
+            }
+            console.log(matchWayValue);
+        });
+        // 保存到exactRuleTableArr 临时数组
+        exactRuleTableArr[editexactRuleId] = ruleArr
+        $('#exactRuleTable').dataTable().fnClearTable();
+        $('#exactRuleTable').dataTable().fnAddData(exactRuleTableArr);
+        if (exactRuleTableArr.length === 0) {
+            $('#exactRuleTable').dataTable().fnClearTable();
+        }
+        $("#modal-edit-exactRule").modal("hide");
+    }
+    // 精准筛选规则-编辑页面 +新增按钮
+    function editExactRule(){
+        ruleHtmlFunc("edit-class","","#editexactRule")
+        if ($('.edit-class').length > 3){
+            $("#editExactRuleButton").hide();
+        }
+    }
+    //  判断是否设置匹配方式
+    function hasMatchWay() {
+        for (let i = 0; i < o_rules.length; i++) {
+            if (o_rules[i]["s_keymatch"]!=""&&o_rules[i]["s_keymatch"]!=undefined){
+                return true
+            }
+        }
+        return false
+    }
+    // 获取已经设置的匹配方式  但是目前仅支持 标题和正文
+    const ruleMatchMruleStr = {
+        "1":"title",
+        "2":"content"
+    }
+    function matchWayShow(mId) {
+        let arr  = new Set();
+        for (let i = 0; i < o_rules.length; i++) {
+            if (o_rules[i]["s_keymatch"] != "" && o_rules[i]["s_keymatch"] != undefined) {
+                if (ruleMatchMruleStr.hasOwnProperty(o_rules[i]["s_keymatch"])){
+                    let matchWay = ruleMatchMruleStr[o_rules[i]["s_keymatch"]]
+                    arr.add({ value: matchWay, text: matchWayMap[matchWay] })
+                }
+            }
+        }
+        let  arr2 = Array.from(arr)
+        for (let i = 0; i <arr2.length; i++) {
+            let  option = arr2[i]
+            let s = `<option value="`+option.value+`">`+option.text+`</option>`
+            $(mId+'  select[name=matchWay]').append(`<option value="`+option.value+`">`+option.text+`</option>`)
+        }
+        $(mId+'  select[name=matchWay]').selectpicker('refresh');
+
+    }
 </script>

+ 136 - 14
CMPlatform/web/templates/private/euser_rule_edit.html

@@ -288,27 +288,48 @@
                             </table>
                         </div>
                     </div>
+<!--                    <div class="tab-pane" id="tab_3">-->
+<!--                        <div class="box box-primary">-->
+<!--                            <div class="box-header with-border">-->
+<!--                                <div class="form-group">-->
+<!--                                    <div class="col-sm-6">-->
+<!--                                        <textarea name="" id="exactRule" cols="30" rows="10" placeholder="" style="width: 100%" disabled></textarea>-->
+<!--                                    </div>-->
+<!--                                    <div class="col-sm-6">-->
+<!--                                        编写规则说明:<br/>-->
+<!--                                        1.应用场景:可根据该篇公告标题或全文,匹配的“关键词分组”个数,确定是否推送该篇公告。<br/>-->
+<!--                                        2.规则释义:<br/>-->
+<!--                                        (1)查找范围:title→公告标题,content→公告全文;not为不包含的关系;<br/>-->
+<!--                                        (2)查找值:关键词分组名;<br/>-->
+<!--                                        (3)查找范围和查找值用“_”连接;<br/>-->
+<!--                                        (3)查找条件:数量条件可用>=<;and→且关系,or→或关系;1组条件用()。<br/>-->
+<!--                                        3.规则示例(分组名为A和B):(title_A>0 and not content_B) or title_B>4 or (content_A and content_B>1) ,即该篇公告标题包含关键词分组A且公告全文文不包含关键词分组B时即推送,或该篇公告全文包含4个关键词分组B时即推送,或该篇公告全文包含关键词分组A2个及以上且关键词分组B2个及以上时即推送-->
+<!--                                    </div>-->
+<!--                                </div>-->
+<!--                            </div>-->
+<!--                        </div>-->
+<!--                    </div>-->
                     <div class="tab-pane" id="tab_3">
                         <div class="box box-primary">
                             <div class="box-header with-border">
-                                <div class="form-group">
-                                    <div class="col-sm-6">
-                                        <textarea name="" id="exactRule" cols="30" rows="10" placeholder="" style="width: 100%" disabled></textarea>
-                                    </div>
-                                    <div class="col-sm-6">
-                                        编写规则说明:<br/>
-                                        1.应用场景:可根据该篇公告标题或全文,匹配的“关键词分组”个数,确定是否推送该篇公告。<br/>
-                                        2.规则释义:<br/>
-                                        (1)查找范围:title→公告标题,content→公告全文;not为不包含的关系;<br/>
-                                        (2)查找值:关键词分组名;<br/>
-                                        (3)查找范围和查找值用“_”连接;<br/>
-                                        (3)查找条件:数量条件可用>=<;and→且关系,or→或关系;1组条件用()。<br/>
-                                        3.规则示例(分组名为A和B):(title_A>0 and not content_B) or title_B>4 or (content_A and content_B>1) ,即该篇公告标题包含关键词分组A且公告全文文不包含关键词分组B时即推送,或该篇公告全文包含4个关键词分组B时即推送,或该篇公告全文包含关键词分组A2个及以上且关键词分组B2个及以上时即推送
-                                    </div>
+                                <div class="col-sm-10">
+                                    <h5>说明:可根据公告匹配的“关键词分组”个数,确定是否推送该简公告;符合以下其中1条规则即推送</h5>
                                 </div>
                             </div>
+                            <div>
+                                <table id="exactRuleTable" class="table table-bordered">
+                                    <thead>
+                                    <tr>
+                                        <th>编号</th>
+                                        <th>关键词分组匹配条件</th>
+
+                                    </tr>
+                                    </thead>
+                                </table>
+                            </div>
                         </div>
                     </div>
+
                 </div>
             </div>
         </div>
@@ -405,6 +426,7 @@
     var selectIndex = [];               //选中的编号
     var setValue = 0;                   // 4: 关键词匹配方式,6:附加词匹配方式,8:排除词匹配方式,9:采购单位,10:公告行业, 2:全局采购单位行业, 3:全局公告行业
     var state = 1;
+    var exactRuleTableArr =[];// 临时数组 用于存放规则字符串转换后的数据
     $(document).ready(function () {
         var name1 = {{(session "user").name}};
         if (name1 != dataMap.s_updateuser) {
@@ -779,6 +801,33 @@
                 }
             }]
         });
+        exactRuleTableArr = exactRuleStrToArr( dataMap["s_exactRule"])
+        // 精准筛选规则表格
+        $('#exactRuleTable').DataTable({
+            "paging": false,
+            "lengthChange": false,
+            "searching": false,
+            "ordering": false,
+            "info": true,
+            "autoWidth": false,
+            "language": {
+                "url": "/dist/js/dataTables.chinese.lang"
+            },
+            "fnDrawCallback": function () {
+                this.api().column(0).nodes().each(function (cell, i) {
+                    cell.innerHTML = i + 1;
+                });
+            },
+            "data": exactRuleTableArr,
+            "columns": [
+                {"data": null},
+                {
+                    "data": function (row) {
+                        return exactRuleDataFormat(row)
+                    }
+                }
+            ]
+        });
     });
 
     $('#province').selectpicker({
@@ -1110,4 +1159,77 @@
             })
         });
     }
+    const matchWayMap = {
+        "title":"标题匹配",
+        "content":"全文匹配"
+    }
+    // (title_A>0 and content_B>8) or title_B>4 or (content_A>7 and content_B>1)
+    // 精准筛选规则-规则字符串转换成临时数组   仅支持这种格式 (title_A>0 and  content_B>8) or title_B>4 or (content_A>7 and content_B>1)
+    // 分组名称不要包含公式中的符号 :  下划线、>、()、or、and
+    function exactRuleStrToArr( exactRuleStr)  {
+        if (exactRuleStr===undefined||exactRuleStr===""){
+            return []
+        }
+        let exactRuleTableArrTmp = []
+        // let exactRuleStr = "(title_A>0 and content_B>8) or title_B>4 or (content_A>7 and content_B>1)"
+        let exactRuleList = exactRuleStr.split(" or ") // 分割成单条规则
+        for (let i=0; i< exactRuleList.length; i++) {
+            let exactRuleTmp = exactRuleList[i]
+            let rulesArr = [];
+            if (exactRuleTmp.startsWith("(")) {
+                exactRuleTmp = exactRuleTmp.slice(1, -1) //去掉首尾的括号
+            }
+            let singleRuleArr = exactRuleTmp.split(" and ")  // 分割单条规则中的数据
+            for (let j=0;j<singleRuleArr.length;j++) {
+                let singleRule  =singleRuleArr[j]
+                // 匹配方式
+                let singleRuleSplit = singleRule.split("_")
+                if (singleRuleSplit.length<2){
+                    console.log("singleRuleSplit 长度不够",singleRuleSplit)
+                    return
+                }
+                let matchWay = singleRuleSplit[0] // 第一位是匹配方式
+                // 然后接着分割出分组名称和次数  使用 _
+                let singleRuleSplit2 = singleRuleSplit[1].split(">")
+                if (singleRuleSplit2.length<2){
+                    console.log("singleRuleSplit2 长度不够",singleRuleSplit2)
+                    return
+                }
+                let groupName = singleRuleSplit2[0]
+                let count = singleRuleSplit2[1]
+                // 次数    次数这里要+1  因为展示框里用的是>=  公式里面用的是>
+                let rule = {
+                    "group":groupName,"match_way":matchWay,"count":parseInt(count)+1
+                }
+                rulesArr.push(rule)
+            }
+            exactRuleTableArrTmp.push(rulesArr)
+        }
+        return exactRuleTableArrTmp;
+    }
+    // 规则数组转换列表字符串
+    function exactRuleDataFormat(contentArr ){
+        // keyArr 定义数组 维持最后有序
+        let keyArr = []
+        // 合并 标题正文 如果
+        let tmpDict = {}
+        for (let i = 0; i < contentArr.length; i++) {
+            let keyGroupCount = contentArr[i].group+"_"+ contentArr[i].count
+            if (tmpDict.hasOwnProperty(keyGroupCount)){
+                tmpDict[keyGroupCount].match_way.add(matchWayMap[contentArr[i].match_way])
+            }else {
+                let set = new Set();
+                tmpDict[keyGroupCount] = {
+                    "group":contentArr[i].group,"match_way":set.add(matchWayMap[contentArr[i].match_way]),"count":contentArr[i].count
+                }
+                keyArr.push(keyGroupCount)
+
+            }
+        }
+        let str = ""
+        for (let tmpDictKey in keyArr) {
+            str += "关键词分组:"+tmpDict[keyArr[tmpDictKey]].group+",出现次数>="+tmpDict[keyArr[tmpDictKey]].count+",匹配方式:"+Array.from(tmpDict[keyArr[tmpDictKey]].match_way).join(",")+";"
+        }
+        return str
+    }
 </script>

+ 403 - 16
CMPlatform/web/templates/private/history_rule_edit.html

@@ -6,6 +6,44 @@
 {{include "com/modal.html"}}
 <script src="/time/js/angular.min.js"></script>
 <script src="/time/js/wui-date.js"></script>
+<style>
+    mark {
+        background-color: #00ff90;
+        font-weight: bold;
+    }
+
+    mark1 {
+        background-color: red;
+        font-weight: bold;
+    }
+
+    .insertexactRule-form .division-line ,.editexactRule-form .division-line{
+        display: inline-block !important;
+    }
+    .insertexactRule-form .form-group,.editexactRule-form .form-group{
+        display: block;
+        margin-bottom: 1px !important;
+    }
+    .insertexactRule-form .form-group label,.editexactRule-form .form-group label{
+        padding-top: 8px;
+    }
+    .insertexactRule-form .form-group .col-sm-8,.editexactRule-form .form-group .col-sm-8 {
+        margin-bottom: 5px;
+    }
+    .modal-header {
+        border-bottom-color: #fff;
+        padding-bottom: 0px !important;
+    }
+    #addExactRuleButton a {
+        cursor:pointer;
+    }
+    .insertexactRule-form , .editexactRule-form{
+        padding: 10px 10px 0px 10px;
+    }
+    #editExactRuleButton a {
+        cursor: pointer;
+    }
+</style>
 <div class="content-wrapper">
     <section class="content-header">
         <h1> 编辑客户规则
@@ -435,24 +473,50 @@
                     <div class="tab-pane" id="tab_3">
                         <div class="box box-primary">
                             <div class="box-header with-border">
-                                <div class="form-group">
-                                    <div class="col-sm-6">
-                                        <textarea name="" id="exactRule" cols="30" rows="10" placeholder="请输入精准筛选规则" style="width: 100%"></textarea>
-                                    </div>
-                                    <div class="col-sm-6">
-                                        编写规则说明:<br/>
-                                        1.应用场景:可根据该篇公告标题或全文,匹配的“关键词分组”个数,确定是否推送该篇公告。<br/>
-                                        2.规则释义:<br/>
-                                        (1)查找范围:title→公告标题,content→公告全文;not为不包含的关系;<br/>
-                                        (2)查找值:关键词分组名;<br/>
-                                        (3)查找范围和查找值用“_”连接;<br/>
-                                        (3)查找条件:数量条件可用>=<;and→且关系,or→或关系;1组条件用()。<br/>
-                                        3.规则示例(分组名为A和B):(title_A>0 and not content_B) or title_B>4 or (content_A and content_B>1) ,即该篇公告标题包含关键词分组A且公告全文文不包含关键词分组B时即推送,或该篇公告全文包含4个关键词分组B时即推送,或该篇公告全文包含关键词分组A2个及以上且关键词分组B2个及以上时即推送
-                                    </div>
+                                <div class="col-sm-10">
+                                    <h5>说明:可根据公告匹配的“关键词分组”个数,确定是否推送该简公告;符合以下其中1条规则即推送</h5>
                                 </div>
+                                <div class="col-sm-2">
+                                    <button class="btn btn-twitter btn-sm" style="float: right;margin-top: 4px;margin-right: 10px"
+                                            onclick="addExactRuleShow()"><i class="fa fa-fw fa-file-text fa-lg"></i>新增
+                                    </button>                                </div>
+                            </div>
+                            <div>
+                                <table id="exactRuleTable" class="table table-bordered">
+                                    <thead>
+                                    <tr>
+                                        <th>编号</th>
+                                        <th>关键词分组匹配条件</th>
+
+                                        <th>操作</th>
+                                    </tr>
+                                    </thead>
+                                </table>
                             </div>
                         </div>
                     </div>
+
+                    <!--                    <div class="tab-pane" id="tab_3">-->
+<!--                        <div class="box box-primary">-->
+<!--                            <div class="box-header with-border">-->
+<!--                                <div class="form-group">-->
+<!--                                    <div class="col-sm-6">-->
+<!--                                        <textarea name="" id="exactRule" cols="30" rows="10" placeholder="请输入精准筛选规则" style="width: 100%"></textarea>-->
+<!--                                    </div>-->
+<!--                                    <div class="col-sm-6">-->
+<!--                                        编写规则说明:<br/>-->
+<!--                                        1.应用场景:可根据该篇公告标题或全文,匹配的“关键词分组”个数,确定是否推送该篇公告。<br/>-->
+<!--                                        2.规则释义:<br/>-->
+<!--                                        (1)查找范围:title→公告标题,content→公告全文;not为不包含的关系;<br/>-->
+<!--                                        (2)查找值:关键词分组名;<br/>-->
+<!--                                        (3)查找范围和查找值用“_”连接;<br/>-->
+<!--                                        (3)查找条件:数量条件可用>=<;and→且关系,or→或关系;1组条件用()。<br/>-->
+<!--                                        3.规则示例(分组名为A和B):(title_A>0 and not content_B) or title_B>4 or (content_A and content_B>1) ,即该篇公告标题包含关键词分组A且公告全文文不包含关键词分组B时即推送,或该篇公告全文包含4个关键词分组B时即推送,或该篇公告全文包含关键词分组A2个及以上且关键词分组B2个及以上时即推送-->
+<!--                                    </div>-->
+<!--                                </div>-->
+<!--                            </div>-->
+<!--                        </div>-->
+<!--                    </div>-->
                 </div>
             </div>
         </div>
@@ -492,6 +556,7 @@
     var selectIndex = [];               //选中的编号
     var setValue = 0;                   // 4: 关键词匹配方式,6:附加词匹配方式,8:排除词匹配方式,9:采购单位,10:公告行业, 2:全局采购单位类型, 3:全局公告行业
     var state = 1;
+    var exactRuleTableArr =[];// 临时数组 用于存放规则字符串转换后的数据
     var user_id = getParam("id");
     var hid = getParam("hid");
     var rid = getParam("rid");
@@ -500,7 +565,7 @@
         $(".smallcaidan").hide();
         $(".btnsave").hide();
     }
-    
+
     $(document).ready(function () {
         // var name1 = {{(session "user").name}};
         // if (name1 != dataMap.s_updateuser) {
@@ -879,6 +944,42 @@
                 }
             }]
         });
+        exactRuleTableArr = exactRuleStrToArr( dataMap["s_exactRule"])
+        // 精准筛选规则表格
+        $('#exactRuleTable').DataTable({
+            "paging": false,
+            "lengthChange": false,
+            "searching": false,
+            "ordering": false,
+            "info": true,
+            "autoWidth": false,
+            "language": {
+                "url": "/dist/js/dataTables.chinese.lang"
+            },
+            "fnDrawCallback": function () {
+                this.api().column(0).nodes().each(function (cell, i) {
+                    cell.innerHTML = i + 1;
+                });
+                this.api().column(2).nodes().each(function (cell, i) {
+                    cell.innerHTML = '<div>' +
+                        '<a onclick="editExacRuleClick(\'' + i + '\')" >编辑</a>&nbsp&nbsp' +
+                        '<a onclick="delExacRuleClick(\'' + i + '\')" >删除</a>&nbsp&nbsp' +
+                        '</div>';
+                });
+            },
+            "data": exactRuleTableArr,
+            "columns": [
+                {"data": null},
+                {
+                    "data": function (row) {
+                        return exactRuleDataFormat(row)
+                    }
+                },
+                {
+                    "data": null
+                },
+            ]
+        });
     });
 
     $('#province').selectpicker({
@@ -1736,7 +1837,7 @@
         dataMap["hid"] = hid;
         dataMap["rid"] = rid;
         dataMap["s_depart_name"] = $("#departmentName").val();
-        dataMap["s_exactRule"] = $('#exactRule').val();
+        dataMap["s_exactRule"] = exactRuleArrToStr()
         $.ajax({
             url: "/service/historyRule/edit",
             type: 'POST',
@@ -2426,4 +2527,290 @@
         })
     }
     //分组管理
+    var ruleGroupList = new Array()
+    // 精准筛选规则-新增按钮点击方法
+    function addExactRuleShow(){
+        // 判断是否设置关键词
+        // 判断是否设置关键词
+        if (ruleGroupList.length===0){
+            showGroupListData()
+            if (ruleGroupList.length===0){
+                showTip("请先设置关键词规则分组")
+                return
+            }
+        }
+        // 判断是否设置关键词匹配方式
+        // debugger
+        //  判断是否设置关键词
+        if (o_rules.length===0) {
+            showTip("请先设置关键词")
+            return
+        }
+        //  判断是否设置关键词匹配方式
+        if (!hasMatchWay()){
+            showTip("请先设置关键词匹配方式")
+            return
+        }
+        //初始化
+        $("#insertexactRule").html("");
+        $("#addExactRuleButton").show();
+        // 新增精准筛选规则弹框
+        // 请求分组列表接口获取数据
+        ruleHtmlFunc("insert-class","","#insertexactRule")
+        $("#modal-add-exactRule").modal("show");
+    }
+    // 精准筛选规则-新增页面 +新增按钮
+    function addExactRule(){
+        ruleHtmlFunc("insert-class","","#insertexactRule")
+        if ($('.exact-rule-class').length > 3){
+            $("#addExactRuleButton").hide()
+        }
+    }
+    // 精准筛选规则-新增精准匹配规则保存按钮点击事件
+    function add_exactRule_save(){
+        // 获取值
+        let ruleArr = [];
+        let checkObj = {};
+        let formList =  $("#insertexactRule .insertexactRule-form");
+        formList.each(function() {
+            var groupName = $(this).find('select[name="groupSelect"]').val();
+            var count = $(this).find('input[name="count"]').val();
+            var matchWayValue = $(this).find('select[name="matchWay"]').val();
+            if (groupName===""||matchWayValue.length===0||count===""){
+                // todo
+                return true;
+            }
+            for (let j = 0; j < matchWayValue.length; j++) {
+                let rule =      {
+                    "group":groupName,"match_way":matchWayValue[j],"count":count
+                }
+                if(checkObj[groupName+"_"+count+"_"+matchWayValue[j]]){
+                    return  true
+                }
+                checkObj[groupName+"_"+count+"_"+matchWayValue[j]] = matchWayValue[j]
+                ruleArr.push(rule)
+            }
+            console.log(matchWayValue);
+        });
+        if (ruleArr.length===0){
+            showMsg("规则已存在!")
+            return
+        }
+        // 保存到exactRuleTableArr 临时数组
+        exactRuleTableArr.push(ruleArr)
+        $('#exactRuleTable').dataTable().fnClearTable();
+        $('#exactRuleTable').dataTable().fnAddData(exactRuleTableArr);
+        if (exactRuleTableArr.length == 0) {
+            $('#exactRuleTable').dataTable().fnClearTable();
+        }
+        $("#modal-add-exactRule").modal("hide");
+
+    }
+    // 精准筛选规则-临时数组转换成规则字符串
+    // [[{"group":"A","match_way":"content","count":5},{},{}],[]]
+    // (title_A>0 and content_B>8) or title_B>4 or (content_A>7 and content_B>1)
+    function exactRuleArrToStr(){
+        let ruleStrArr = []
+        for (let i = 0; i < exactRuleTableArr.length; i++) {
+            let rulesArr = [];
+            for (let j = 0; j < exactRuleTableArr[i].length; j++) {
+                let count =exactRuleTableArr[i][j].count-1
+                let group = exactRuleTableArr[i][j].group
+                let match_way = exactRuleTableArr[i][j].match_way
+                let rule = match_way+"_"+group+">"+count
+                rulesArr.push(rule)
+            }
+            if (rulesArr.length>1){ // 拼接小括号
+                ruleStrArr.push("("+rulesArr.join(" and ")+")")
+            }else {
+                if (rulesArr.length>0){
+                    ruleStrArr.push(rulesArr[0])
+                }
+            }
+        }
+        return  ruleStrArr.join(" or ")
+    }
+    // (title_A>0 and content_B>8) or title_B>4 or (content_A>7 and content_B>1)
+    // 精准筛选规则-规则字符串转换成临时数组   仅支持这种格式 (title_A>0 and  content_B>8) or title_B>4 or (content_A>7 and content_B>1)
+    // 分组名称不要包含公式中的符号 :  下划线、>、()、or、and
+    function exactRuleStrToArr( exactRuleStr)  {
+        if (exactRuleStr===undefined||exactRuleStr===""){
+            return []
+        }
+        let exactRuleTableArrTmp = []
+        // let exactRuleStr = "(title_A>0 and content_B>8) or title_B>4 or (content_A>7 and content_B>1)"
+        let exactRuleList = exactRuleStr.split(" or ") // 分割成单条规则
+        for (let i=0; i< exactRuleList.length; i++) {
+            let exactRuleTmp = exactRuleList[i]
+            let rulesArr = [];
+            if (exactRuleTmp.startsWith("(")) {
+                exactRuleTmp = exactRuleTmp.slice(1, -1) //去掉首尾的括号
+            }
+            let singleRuleArr = exactRuleTmp.split(" and ")  // 分割单条规则中的数据
+            for (let j=0;j<singleRuleArr.length;j++) {
+                let singleRule  =singleRuleArr[j]
+                // 匹配方式
+                let singleRuleSplit = singleRule.split("_")
+                if (singleRuleSplit.length<2){
+                    console.log("singleRuleSplit 长度不够",singleRuleSplit)
+                    return
+                }
+                let matchWay = singleRuleSplit[0] // 第一位是匹配方式
+                // 然后接着分割出分组名称和次数  使用 _
+                let singleRuleSplit2 = singleRuleSplit[1].split(">")
+                if (singleRuleSplit2.length<2){
+                    console.log("singleRuleSplit2 长度不够",singleRuleSplit2)
+                    return
+                }
+                let groupName = singleRuleSplit2[0]
+                let count = singleRuleSplit2[1]
+                // 次数    次数这里要+1  因为展示框里用的是>=  公式里面用的是>
+                let rule = {
+                    "group":groupName,"match_way":matchWay,"count":parseInt(count)+1
+                }
+                rulesArr.push(rule)
+            }
+            exactRuleTableArrTmp.push(rulesArr)
+        }
+        return exactRuleTableArrTmp;
+    }
+    var editexactRuleId = 0;
+    const matchWayMap = {
+        "title":"标题匹配",
+        "content":"全文匹配"
+    }
+    // 规则数组转换列表字符串
+    function exactRuleDataFormat(contentArr ){
+        // keyArr 定义数组 维持最后有序
+        let keyArr = []
+        // 合并 标题正文 如果
+        let tmpDict = {}
+        for (let i = 0; i < contentArr.length; i++) {
+            let keyGroupCount = contentArr[i].group+"_"+ contentArr[i].count
+            if (tmpDict.hasOwnProperty(keyGroupCount)){
+                tmpDict[keyGroupCount].match_way.add(matchWayMap[contentArr[i].match_way])
+            }else {
+                let set = new Set();
+                tmpDict[keyGroupCount] = {
+                    "group":contentArr[i].group,"match_way":set.add(matchWayMap[contentArr[i].match_way]),"count":contentArr[i].count
+                }
+                keyArr.push(keyGroupCount)
+
+            }
+        }
+        let str = ""
+        for (let tmpDictKey in keyArr) {
+            str += "关键词分组:"+tmpDict[keyArr[tmpDictKey]].group+",出现次数>="+tmpDict[keyArr[tmpDictKey]].count+",匹配方式:"+Array.from(tmpDict[keyArr[tmpDictKey]].match_way).join(",")+";"
+        }
+        return str
+    }
+    // 删除 点击事件
+    function delExacRuleClick(index) {
+        index = parseInt(index)
+        showConfirm("确定删除?", function () {
+            exactRuleTableArr  =  $.grep(exactRuleTableArr,function (n,i) {
+                return i!==index
+            })
+            $('#exactRuleTable').dataTable().fnClearTable();
+            $('#exactRuleTable').dataTable().fnAddData(exactRuleTableArr);
+            if (exactRuleTableArr.length == 0) {
+                $('#exactRuleTable').dataTable().fnClearTable();
+            }
+        })
+
+    }
+    function showGroupListData(){
+        $.ajax({
+            url: "/service/cuser/groupList",
+            type: "post",
+            data: {"id": dataMap.rid},
+            async: false,
+            success: function (r) {
+                if (r.data) {
+                    ruleGroupList=r.data;
+                }
+            }})
+    }
+    // 编辑点击事件
+    function editExacRuleClick(index){
+        $("#editexactRule").html("");
+        $("#editExactRuleButton").show();
+        editexactRuleId = index;
+        // 铺数据
+        let contentArr = exactRuleTableArr[index]
+        // keyArr 定义数组 维持最后有序
+        let keyArr = []
+        // 合并 标题正文
+        let tmpDict = {}
+        for (let i = 0; i < contentArr.length; i++) {
+            let keyGroupCount = contentArr[i].group+"_"+ contentArr[i].count
+            if (tmpDict.hasOwnProperty(keyGroupCount)){
+                tmpDict[keyGroupCount].match_way.add(contentArr[i].match_way)
+            }else {
+                let set = new Set();
+                tmpDict[keyGroupCount] = {
+                    "group":contentArr[i].group,"match_way":set.add(contentArr[i].match_way),"count":contentArr[i].count
+                }
+                keyArr.push(keyGroupCount)
+            }
+        }
+        for (let i = 0; i < keyArr.length; i++) {
+            var keyGroup = tmpDict[keyArr[i]].group;
+            var count = tmpDict[keyArr[i]].count;
+            var matchWay = tmpDict[keyArr[i]].match_way;
+            ruleHtmlFunc("edit-class",keyArr[i],"#editexactRule");
+            $('#editexactRule .'+keyArr[i]+' select[name=groupSelect]').selectpicker('val',keyGroup);
+            $('#editexactRule .'+keyArr[i]+' input[name=count]').val(count);
+            let matchWayArr = Array.from(matchWay);
+            $('#editexactRule .'+keyArr[i]+' select[name=matchWay]').val("").trigger("change").selectpicker('val',matchWayArr);
+        }
+        $("#modal-edit-exactRule").modal("show");
+    }
+    // 编辑保存
+    function edit_exactRule_save(){
+        // let index =  $("#editexactRuleId").text()
+        // 获取数
+        let ruleArr = []
+        let formList =  $("#editexactRule .editexactRule-form")
+        formList.each(function() {
+            var groupName = $(this).find('select[name="groupSelect"]').val();
+            var count = $(this).find('input[name="count"]').val();
+            var matchWayValue = $(this).find('select[name="matchWay"]').val();
+            if (groupName===""||matchWayValue.length===0||count===""){
+                // todo
+                return true;
+            }
+            for (let j = 0; j < matchWayValue.length; j++) {
+                let rule =      {
+                    "group":groupName,"match_way":matchWayValue[j],"count":count
+                }
+                ruleArr.push(rule)
+            }
+            console.log(matchWayValue);
+        });
+        // 保存到exactRuleTableArr 临时数组
+        exactRuleTableArr[editexactRuleId] = ruleArr
+        $('#exactRuleTable').dataTable().fnClearTable();
+        $('#exactRuleTable').dataTable().fnAddData(exactRuleTableArr);
+        if (exactRuleTableArr.length === 0) {
+            $('#exactRuleTable').dataTable().fnClearTable();
+        }
+        $("#modal-edit-exactRule").modal("hide");
+    }
+    // 精准筛选规则-编辑页面 +新增按钮
+    function editExactRule(){
+        ruleHtmlFunc("edit-class","","#editexactRule")
+        if ($('.edit-class').length > 3){
+            $("#editExactRuleButton").hide();
+        }
+    }
+    //  判断是否设置匹配方式
+    function hasMatchWay() {
+        for (let i = 0; i < o_rules.length; i++) {
+            if (o_rules[i]["s_keymatch"]!=""&&o_rules[i]["s_keymatch"]!=undefined){
+                return true
+            }
+        }
+        return false
+    }
 </script>