walter 6 mesiacov pred
rodič
commit
048f9acd2b

+ 1 - 1
src/point/view/integral/deptRank.vue

@@ -294,7 +294,7 @@ export default {
           this.rws.send("dept rank keep connecting")
           break;
         case 'auth':
-          if (msg.code === 1) this.rwsHasAuth = true;
+          this.rwsHasAuth = msg.code === 1;
           break;
         case 'dr':
           if (msg.code === 1) this.dataList = msg.result.list;

+ 237 - 31
src/point/view/integral/integral_application.vue

@@ -89,40 +89,66 @@
     </div>
     <div style="padding:0.32rem;" class="flex-box-ce">
       <van-button size="large" plain type="info" style="margin-right: 0.2rem;width: 2rem;" @click="openSelect" v-if="rule_switch">已选{{items.length}}条</van-button>
-      <van-button size="large" @click="data_verify" :disabled="subloading" type="info">提交</van-button>
+<!--      <van-button size="large" @click="data_verify" :disabled="subloading" type="info">提交</van-button>-->
+      <van-button size="large" @click="rwsBusinessVerify" :disabled="subloading || !rwsHasAuth" type="info">提交</van-button>
     </div>
 
     <!-- 提交结果 -->
-    <van-popup v-model="isResult" style="width: 90%;border-radius: 5px;">
-    	<div v-if="!isShowError" style="padding: 0.24rem;">
-        <van-progress :percentage="percentage" />
-    		<div style="margin-top: 10px;border: 1px solid #f1f1f1;max-height: 7rem;overflow-y: auto;" class="scroll-bar">
-    			<div class="flex-box-ce results" style="font-weight: 600;">
-    				<div style="border-right: 1px solid #f1f1f1;width: 40px;">序号</div>
-    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">申请对象</div>
-    				<div class="flex-1" >处理结果</div>
-    			</div>
-    			<div class="flex-box-ce results" v-for="(item, index) in results" :key="index">
-    				<div style="border-right: 1px solid #f1f1f1;width: 40px;">{{results.length-index}}</div>
-    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.target }}</div>
-    				<div class="flex-1 font-flex-word" v-if="item.status == 1">
-    					<span class="green">提交成功</span>
-    				</div>
-    				<div class="flex-1 red" v-else>{{ item.msg }}</div>
-    			</div>
-    		</div>
-        <div class="flex-box-end" style="margin-top: 20px;" v-show="results.length==resultList.length">
-          <van-button type="info" @click="isResult = false" size="small">确 定</van-button>
-        </div>
-    	</div>
-    	<div v-else>
-    		<div style="text-align: center;" class="red">{{errorMsg}}</div>
-    		<div>
-    			<div class="flex-box-end" style="margin-top: 10px;">
-            <van-button type="info" @click="isResult = false" size="small">确 定</van-button>
+<!--    <van-popup v-model="isResult" style="width: 90%;border-radius: 5px;">-->
+<!--    	<div v-if="!isShowError" style="padding: 0.24rem;">-->
+<!--        <van-progress :percentage="percentage" />-->
+<!--    		<div style="margin-top: 10px;border: 1px solid #f1f1f1;max-height: 7rem;overflow-y: auto;" class="scroll-bar">-->
+<!--    			<div class="flex-box-ce results" style="font-weight: 600;">-->
+<!--    				<div style="border-right: 1px solid #f1f1f1;width: 40px;">序号</div>-->
+<!--    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">申请对象</div>-->
+<!--    				<div class="flex-1" >处理结果</div>-->
+<!--    			</div>-->
+<!--    			<div class="flex-box-ce results" v-for="(item, index) in results" :key="index">-->
+<!--    				<div style="border-right: 1px solid #f1f1f1;width: 40px;">{{results.length-index}}</div>-->
+<!--    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.target }}</div>-->
+<!--    				<div class="flex-1 font-flex-word" v-if="item.status == 1">-->
+<!--    					<span class="green">提交成功</span>-->
+<!--    				</div>-->
+<!--    				<div class="flex-1 red" v-else>{{ item.msg }}</div>-->
+<!--    			</div>-->
+<!--    		</div>-->
+<!--        <div class="flex-box-end" style="margin-top: 20px;" v-show="results.length==resultList.length">-->
+<!--          <van-button type="info" @click="isResult = false" size="small">确 定</van-button>-->
+<!--        </div>-->
+<!--    	</div>-->
+<!--    	<div v-else>-->
+<!--    		<div style="text-align: center;" class="red">{{errorMsg}}</div>-->
+<!--    		<div>-->
+<!--    			<div class="flex-box-end" style="margin-top: 10px;">-->
+<!--            <van-button type="info" @click="isResult = false" size="small">确 定</van-button>-->
+<!--          </div>-->
+<!--    		</div>-->
+<!--    	</div>-->
+<!--    </van-popup>-->
+
+<!--  rws提交结果  -->
+    <van-popup v-model="rwsBusinessData.showBusiness" :close-on-click-overlay="false" style="width: 90%;border-radius: 5px;">
+      <div style="padding: 0.24rem;">
+        <van-progress :percentage="rwsBusinessProgress" />
+        <div style="margin-top: 10px;border: 1px solid #f1f1f1;max-height: 7rem;overflow-y: auto;" class="scroll-bar">
+          <div class="flex-box-ce results" style="font-weight: 600;">
+            <div style="border-right: 1px solid #f1f1f1;width: 40px;">序号</div>
+            <div class="flex-1" style="border-right: 1px solid #f1f1f1;">申请对象</div>
+            <div class="flex-1" >处理结果</div>
+          </div>
+          <div class="flex-box-ce results" v-for="(item, index) in rwsBusinessData.dataList" :key="index">
+            <div style="border-right: 1px solid #f1f1f1;width: 40px;">{{`${index + 1}`}}</div>
+            <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.employee_name }}</div>
+            <div class="flex-1">
+              <span :class="{'cyan':item.status === -2,'origin':item.status === -1,'green':item.status === 1,'red':item.status === 0}">{{item.msg}}</span>
+            </div>
           </div>
-    		</div>
-    	</div>
+        </div>
+        <div class="flex-box-end" style="margin-top: 20px;" >
+          <van-button type="info" :disabled="rwsBusinessProgress < 100" @click="rwsBusinessData.showBusiness = false" size="small">确 定</van-button>
+          <van-tag style="margin-left: 0.2rem;" @click="rwsClipResult">{{rwsBusinessData.result.length}} / {{rwsBusinessData.dataList.length}}</van-tag>
+        </div>
+      </div>
     </van-popup>
   </div>
 </template>
@@ -136,6 +162,8 @@ import moment from 'moment'
 import Vue from 'vue'
 import {Switch,Progress,Icon  } from 'vant'
 import RuleScopeSelector from "../../../components/RuleScopeSelector.vue";
+import ReconnectingWebSocket from "reconnecting-websocket";
+import {generateUUID, getToken} from "../../../utils/auth";
 
 Vue.use(Switch).use(Progress).use(Icon)
 
@@ -159,6 +187,7 @@ export default {
       superior_list:this.$userInfo().employee_detail.superior_list,
       employee_list: [this.$userInfo()],
       employeeid:this.$userInfo().id,
+      employeeName:this.$userInfo().name,
       ptId:3,
       change_reviewer:Number(this.$userInfo().site_config.change_reviewer),//是否允许员工修改审批人
       userName:'',
@@ -193,6 +222,20 @@ export default {
       resultIndex:0,
       isShowError:false,
       errorMsg:'服务器繁忙,请稍后再试',
+      rws:null,
+      rwsHasAuth:false,
+      rwsBusinessData:{
+        showBusiness:false,
+        dataList:[],
+        msgQueue:[],
+        result:[],
+        intervalId:null,
+      }
+    }
+  },
+  computed:{
+    rwsBusinessProgress(){
+      return this.rwsBusinessData.dataList.length === 0 ? 0 : Math.floor(this.rwsBusinessData.dataList.filter(item => item.status >= 0).length / this.rwsBusinessData.dataList.length * 100)
     }
   },
   watch: {
@@ -227,9 +270,11 @@ export default {
     employee_list(val) {
       if (val.length > 0) {
         this.employeeid=val[0].id;
+        this.employeeName=val[0].name;
         this.initializesReviewer(val[0].id);
       } else {
         this.employeeid = ''
+        this.employeeName = ''
         this.items.forEach(item=>{
           item.reviewer_id='';
           item.reviewer_list=[];
@@ -247,6 +292,14 @@ export default {
     		this.$socketApi.closewebsocket();
     	}
     },
+    'rwsBusinessData.showBusiness'(v){
+      if (!v) {
+        this.initRwsBusinessData();
+        this.items = [];
+        this.itemRule=[];//规则数组
+        this.rule_switch=true;
+      }
+    }
   },
   mounted() {
     this.initializesReviewer(this.employeeid);
@@ -257,6 +310,14 @@ export default {
        }
     }
   },
+  activated() {
+    console.log('activated');
+    this.initRws();
+  },
+  beforeDestroy() {
+    console.log('before destroy');
+    this.clearRws();
+  },
   methods: {
     openText(){
        this.$dialog.alert({
@@ -439,7 +500,152 @@ export default {
     		this.isShowError = true;
     	}
     },
-  }
+    initRws(){
+      if (this.rws){
+        this.rws.close();
+        this.rws = null;
+        this.rwsHasAuth = false;
+      }
+      this.rws = new ReconnectingWebSocket(process.env.VUE_APP_WEBSCOKET);
+      this.rws.onopen = this.onWsOpen;
+      this.rws.onmessage = this.onWsMessage;
+      this.rws.onerror = this.onWsError;
+      this.rws.onclose = this.onWsClose;
+    },
+    initRwsBusinessData(){
+      this.rwsBusinessData.dataList = [];
+      this.rwsBusinessData.msgQueue = [];
+      this.rwsBusinessData.result = [];
+      if (this.rwsBusinessData.intervalId) clearInterval(this.rwsBusinessData.intervalId);
+      this.rwsBusinessData.intervalId = null;
+    },
+    onWsOpen(){
+      let params = {
+        type:'auth',
+        token: getToken(),
+        machine: generateUUID(),
+      }
+      this.rws.send(JSON.stringify(params));
+    },
+    onWsMessage(event){
+      let msg = event.data ?  JSON.parse(event.data) : null;
+      if (!msg) return;
+      let type = msg.type || 'none';
+      switch (type){
+        case 'ping':
+          this.rws.send('integral application keep connecting');
+          break;
+        case 'auth':
+          this.rwsHasAuth = msg.code === 1;
+          break;
+        case 'point_apply':
+          this.rwsBusinessData.result.push(msg);
+          let businessId = msg.result.task.msg.businessId;
+          this.rwsBusinessData.dataList.forEach(item => {
+            if (item.businessId !== businessId) return;
+            item.status = msg.result.status;
+            item.msg = msg.result.msg;
+          })
+          this.rwsIntegralApplication();
+          break;
+      }
+    },
+    onWsError(event){
+      console.log('on ws error',event);
+      this.rwsHasAuth = false;
+    },
+    onWsClose(event){
+      console.log('on ws close',event)
+      this.rwsHasAuth = false;
+    },
+    clearRws(){
+      if (this.rws) this.rws.close();
+      this.rws = null;
+      this.rwsHasAuth = false;
+      this.initRwsBusinessData();
+    },
+    rwsBusinessVerify() {
+      if(!this.employeeid){
+        this.showMessage('请选择录入对象')
+        return false
+      }
+      if(this.items.length === 0){
+        this.showMessage('请选择规则')
+        return false
+      }
+
+      let now = moment();
+      let businessId = 1;
+      for (var i = 0; i < this.items.length; i++){
+        let item = this.items[i];
+        if (!item.remark){
+          this.showMessage(`第${i + 1}条申请,请输入时间内容及描述`);
+          return false;
+        }
+        if (item.reviewer_list.length <= 0){
+          this.showMessage(`第${i + 1}条申请,请选择审批人`);
+          return false;
+        }
+        if (moment(item.event_time).isAfter(now)){
+          this.showMessage(`第${i + 1}条申请,发生时间不能大于今天`);
+          return false;
+        }
+
+        this.rwsBusinessData.dataList.push({
+          rule_id: item.rule_id || 0,
+          employee_id: this.employeeid || 0,
+          item_id: item.item_id || 0,
+          remark: item.remark,
+          event_time: item.event_time,
+          files: item.files,
+          type:'point_apply',
+          reviewer_id:item.reviewer_list[0].id,
+          employee_name:this.employeeName,
+          status:-2,
+          msg:'待处理',
+          businessId:businessId,
+        });
+        /*队列数据*/
+        let msg = {
+          rule_id: item.rule_id || 0,
+          employee_id: this.employeeid || 0,
+          item_id: item.item_id || 0,
+          remark: item.remark,
+          event_time: item.event_time,
+          files: item.files,
+          type:'point_apply',
+          reviewer_id:item.reviewer_list[0].id,
+          businessId:businessId,
+        }
+        this.rwsBusinessData.msgQueue.push(msg);
+
+        businessId++;
+      }
+      if (this.rwsBusinessData.dataList.length <= 0){
+        this.showMessage("请重新指定规则");
+        return false;
+      }
+
+      this.rwsBusinessData.showBusiness = true;
+
+      /*开始提交*/
+      this.rwsIntegralApplication();
+    },
+    rwsClipResult(){
+      navigator.clipboard.writeText(JSON.stringify(this.rwsBusinessData.result));
+      this.$notify({type: 'info', message: '结果已经复制到剪切板'})
+    },
+    rwsIntegralApplication(){
+      let msg = this.rwsBusinessData.msgQueue.shift();
+      if (!msg) return;
+      this.rwsBusinessData.dataList.forEach(item => {
+        if (item.businessId !== msg.businessId) return;
+        item.status = -1;
+        item.msg = '处理中';
+      })
+      this.rws.send(JSON.stringify(msg));
+    }
+  },
 }
 </script>
 <style scoped>

+ 310 - 44
src/point/view/integral/integral_entry_n.vue

@@ -88,46 +88,78 @@
     <div v-isKeyboard>
       <div class="flex-box-ce footer">
         <van-button size="large" plain type="info" style="margin-right: 0.2rem;width: 2rem;" @click="openSelect">已选{{items.length}}条</van-button>
-        <van-button size="large" @click="data_verify" type="info">提交</van-button>
+<!--        <van-button size="large" @click="data_verify" type="info" :disabled="!rwsHasAuth" >提交</van-button>-->
+        <van-button size="large" @click="rwsBusinessVerify" type="info" :disabled="!rwsHasAuth" >提交</van-button>
       </div>
     </div>
 
     <!-- 提交结果 -->
-    <van-popup v-model="isResult" style="width: 90%;border-radius: 5px;">
-    	<div v-if="!isShowError" style="padding: 0.24rem;">
-        <van-progress :percentage="percentage" />
-    		<div style="margin-top: 10px;border: 1px solid #f1f1f1;max-height: 7rem;overflow-y: auto;" class="scroll-bar">
-    			<div class="flex-box-ce results" style="font-weight: 600;">
-    				<div style="border-right: 1px solid #f1f1f1;width: 40px;">序号</div>
-    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">奖扣对象</div>
-    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">积分</div>
-    				<div class="flex-1" >处理结果</div>
-    			</div>
-    			<div class="flex-box-ce results" v-for="(item, index) in results" :key="index">
-    				<div style="border-right: 1px solid #f1f1f1;width: 40px;">{{results.length-index}}</div>
-    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.target }}</div>
-    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.point>0? '+'+item.point:item.point }}<span> {{ $getTypesName(ptId) }}</span></div>
-    				<div class="flex-1" v-if="item.status == 1">
-    					<span v-if="item.msg=='奖扣成功'" class="green">{{ item.msg }}</span>
-    					<span class="blue" v-else>{{ item.msg }}</span>
-    				</div>
-    				<div class="flex-1 red" v-else>{{ item.msg }}</div>
-    			</div>
-    		</div>
-        <div class="flex-box-end" style="margin-top: 20px;" v-show="results.length==resultList.length">
-          <van-button type="info" @click="isResult = false" size="small">确 定</van-button>
-        </div>
-    	</div>
-    	<div v-else>
-    		<div style="text-align: center;" class="red">{{errorMsg}}</div>
-    		<div>
-    			<div class="flex-box-end" style="margin-top: 10px;">
-            <van-button type="info" @click="isResult = false" size="small">确 定</van-button>
+<!--    <van-popup v-model="isResult" style="width: 90%;border-radius: 5px;">-->
+<!--    	<div v-if="!isShowError" style="padding: 0.24rem;">-->
+<!--        <van-progress :percentage="percentage" />-->
+<!--    		<div style="margin-top: 10px;border: 1px solid #f1f1f1;max-height: 7rem;overflow-y: auto;" class="scroll-bar">-->
+<!--    			<div class="flex-box-ce results" style="font-weight: 600;">-->
+<!--    				<div style="border-right: 1px solid #f1f1f1;width: 40px;">序号</div>-->
+<!--    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">奖扣对象</div>-->
+<!--    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">积分</div>-->
+<!--    				<div class="flex-1" >处理结果</div>-->
+<!--    			</div>-->
+<!--    			<div class="flex-box-ce results" v-for="(item, index) in results" :key="index">-->
+<!--    				<div style="border-right: 1px solid #f1f1f1;width: 40px;">{{results.length-index}}</div>-->
+<!--    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.target }}</div>-->
+<!--    				<div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.point>0? '+'+item.point:item.point }}<span> {{ $getTypesName(ptId) }}</span></div>-->
+<!--    				<div class="flex-1" v-if="item.status == 1">-->
+<!--    					<span v-if="item.msg=='奖扣成功'" class="green">{{ item.msg }}</span>-->
+<!--    					<span class="blue" v-else>{{ item.msg }}</span>-->
+<!--    				</div>-->
+<!--    				<div class="flex-1 red" v-else>{{ item.msg }}</div>-->
+<!--    			</div>-->
+<!--    		</div>-->
+<!--        <div class="flex-box-end" style="margin-top: 20px;" v-show="results.length==resultList.length">-->
+<!--          <van-button type="info" @click="isResult = false" size="small">确 定</van-button>-->
+<!--        </div>-->
+<!--    	</div>-->
+<!--    	<div v-else>-->
+<!--    		<div style="text-align: center;" class="red">{{errorMsg}}</div>-->
+<!--    		<div>-->
+<!--    			<div class="flex-box-end" style="margin-top: 10px;">-->
+<!--            <van-button type="info" @click="isResult = false" size="small">确 定</van-button>-->
+<!--          </div>-->
+<!--    		</div>-->
+<!--    	</div>-->
+<!--    </van-popup>-->
+    <RuleScopeSelector :visible.sync = showRuleSelector :selected="itemRule" multi @confirm="selected => itemRule = selected" :pt-id="ptId" />
+
+<!--  rws提交结果  -->
+    <van-popup v-model="rwsBusinessData.showBusiness" :close-on-click-overlay="false" style="width: 90%; border-radius: 5px;">
+      <div style="padding: 0.24rem;">
+        <van-progress :percentage="rwsBusinessProgress" />
+        <div style="margin-top: 10px;border: 1px solid #f1f1f1;max-height: 7rem;overflow-y: auto;" class="scroll-bar">
+          <div class="flex-box-ce results" style="font-weight: 600;">
+            <div style="border-right: 1px solid #f1f1f1;width: 40px;">序号</div>
+            <div class="flex-1" style="border-right: 1px solid #f1f1f1;">奖扣对象</div>
+            <div class="flex-1" style="border-right: 1px solid #f1f1f1;">积分</div>
+            <div class="flex-1" >处理结果</div>
+          </div>
+          <div class="flex-box-ce results" v-for="(item,index) in rwsBusinessData.dataList" :key="index">
+            <div style="border-right: 1px solid #f1f1f1;width: 40px;">{{`${index + 1}`}}</div>
+            <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.employee_name }}</div>
+            <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.point>0? '+'+item.point:item.point }}<span> {{ $getTypesName(ptId) }}</span></div>
+            <div class="flex-1">
+              <span :class="{'cyan':item.status === -2,'origin':item.status === -1,'green':item.status === 1,'red':item.status === 0}" >{{item.msg}}</span>
+            </div>
           </div>
-    		</div>
-    	</div>
+        </div>
+<!--        <div class="flex-box-end" style="margin-top: 20px;" v-show="rwsBusinessProgress >= 100">-->
+<!--          <van-button type="info" @click="rwsBusinessData.showBusiness = false" size="small">确 定</van-button>-->
+<!--        </div>-->
+        <div class="flex-box-end" style="margin-top: 20px;">
+          <van-button type="info" :disabled="rwsBusinessProgress < 100" @click="rwsBusinessData.showBusiness = false" size="small" >确 定</van-button>
+          <van-tag style="margin-left: 0.2rem;" @click="rwsClipResult">{{rwsBusinessData.result.length}} / {{rwsBusinessData.dataList.length}}</van-tag>
+        </div>
+      </div>
     </van-popup>
-    <RuleScopeSelector :visible.sync = showRuleSelector :selected="itemRule" multi @confirm="selected => itemRule = selected" :pt-id="ptId" />
+
   </div>
 </template>
 <script>
@@ -142,6 +174,8 @@ import Vue from 'vue'
 import ImageCamera from '@/attendance/components/image-camera';
 import {Switch,Progress} from 'vant'
 import RuleScopeSelector from "../../../components/RuleScopeSelector.vue";
+import ReconnectingWebSocket from "reconnecting-websocket";
+import {generateUUID, getToken} from "../../../utils/auth";
 
 Vue.use(Switch).use(Progress)
 export default {
@@ -210,7 +244,16 @@ export default {
       resultIndex:0,
       isShowError:false,
       errorMsg:'服务器繁忙,请稍后再试',
-
+      rws:null,
+      rwsHasAuth:false,
+      rwsBusinessData:{
+        showBusiness:false,
+        dataList:[],
+        msgQueue:[],
+        result:[],
+        employees:[],
+        items:[],
+      }
     }
   },
   watch: {
@@ -272,14 +315,17 @@ export default {
       }
     },
     employee_list(val) {
-      if (val.length > 0) {
-        this.dialogData.members = []
-        this.dialogData.members=val.map(element => {
-          return element.id
-        })
-      } else {
-        this.dialogData.members = []
-      }
+      // if (val.length > 0) {
+      //   this.dialogData.members = []
+      //   this.dialogData.members=val.map(element => {
+      //     return element.id
+      //   })
+      // } else {
+      //   this.dialogData.members = []
+      // }
+      //
+      // console.log(val);
+      this.rwsBusinessData.employees = val && val.length > 0 ? val : [];
     },
     isResult(val){
     	if(!val){
@@ -297,6 +343,25 @@ export default {
     		this.$socketApi.closewebsocket();
     	}
     },
+    'rwsBusinessData.showBusiness'(v){
+      if (!v){
+        this.initRwsBusinessData();
+        this.dialogData = {
+          members: [],
+          items: []
+        };
+        this.itemRule = [];
+        this.ruleCate = [];
+        this.rule_switch = true;
+        this.items = [];
+        this.employee_list = [];
+      }
+    }
+  },
+  computed:{
+    rwsBusinessProgress(){
+      return this.rwsBusinessData.dataList.length === 0 ? 0 : Math.floor(this.rwsBusinessData.dataList.filter(item => item.status >= 0).length / this.rwsBusinessData.dataList.length * 100);
+    }
   },
   methods: {
     openText(){
@@ -317,6 +382,7 @@ export default {
       this.$notify({type: 'danger', message: str})
     },
     data_verify () {
+      // console.log(this.dialogData,this.items);return ;
       let dialogData=this.dialogData
       dialogData.items=this.items.map(e=>{
         if(e.reviewer_list.length>0){
@@ -401,7 +467,9 @@ export default {
             files: element.files
           });
       });
-      this.webSocket(data);
+      // console.log(data,this.dialogData);this.isResult = true; return ;
+      this.rwsBusinessSubmit(data.members,data.items);
+      // this.webSocket(data);
     },
     webSocket(data){
     	let {members,items}=data;
@@ -485,6 +553,200 @@ export default {
 
       }).catch(() => {});
     },
+    initRws(){
+      if (this.rws){
+        this.rws.close();
+        this.rws = null;
+        this.rwsHasAuth = false;
+      }
+      this.rws = new ReconnectingWebSocket(process.env.VUE_APP_WEBSCOKET);
+      this.rws.onopen = this.onWsOpen;
+      this.rws.onmessage = this.onWsMessage;
+      this.rws.onerror = this.onWsError;
+      this.rws.onclose = this.onWsClose;
+    },
+    initRwsBusinessData(){
+      this.rwsBusinessData.dataList = [];
+      this.rwsBusinessData.msgQueue = [];
+      this.rwsBusinessData.result = [];
+      this.rwsBusinessData.items = [];
+    },
+    onWsOpen(){
+      let params = {
+        type:'auth',
+        token: getToken(),
+        machine: generateUUID(),
+      }
+      this.rws.send(JSON.stringify(params));
+    },
+    onWsMessage(event){
+      let msg = event.data ?  JSON.parse(event.data) : null;
+      if (!msg) return;
+      let type = msg.type || 'none';
+      switch (type){
+        case 'ping':
+          this.rws.send('point entry keep connecting');
+          break;
+        case 'auth':
+          this.rwsHasAuth = msg.code === 1;
+          break;
+        case 'pea':
+        case 'peb':
+          this.rwsBusinessData.result.push(msg);
+          let businessId = msg.result.task.msg.businessId;
+          this.rwsBusinessData.dataList.forEach(item => {
+            if (item.businessId !== businessId) return;
+            item.status = msg.result.status;
+            item.msg = msg.result.msg;
+          })
+          this.rwsPointEntry();
+          break;
+      }
+    },
+    onWsError(event){
+      console.log('on ws error',event);
+      this.rwsHasAuth = false;
+    },
+    onWsClose(event){
+      console.log('on ws close',event)
+      this.rwsHasAuth = false;
+    },
+    clearRws(){
+      if (this.rws) this.rws.close();
+      this.rws = null;
+      this.rwsHasAuth = false;
+      this.initRwsBusinessData();
+    },
+    rwsPointEntry(){
+      let msg = this.rwsBusinessData.msgQueue.shift();
+      if (!msg) return;
+      this.rwsBusinessData.dataList.forEach(item => {
+        if (item.businessId !== msg.businessId) return;
+        item.status = -1;
+        item.msg = '处理中';
+      })
+
+      this.rws.send(JSON.stringify(msg));
+    },
+    rwsBusinessSubmit(members,items){
+      if (!members || members.length <= 0 || !items || items.length <= 0) {
+        this.showMessage('规则/分类以及录入对象必须选择');
+        return;
+      }
+
+      let employeeMap = {}
+      this.rwsBusinessData.employees.forEach(employee => {
+        employeeMap[employee.id] = employee;
+      });
+      let businessId = 1;
+      this.initRwsBusinessData();   //清空提交业务数据
+      members.forEach(memberId => {
+        items.forEach(item => {
+          item.type = this.ptId === 2 ? 'pea' : 'peb';
+          item.employee_id = memberId;
+          item.employee_name = employeeMap[memberId] ? employeeMap[memberId].name : '';
+          item.status = -2;
+          item.msg = '待处理';
+          item.businessId = businessId;
+          this.rwsBusinessData.dataList.push(JSON.parse(JSON.stringify(item)))
+          businessId++;
+
+          /*队列数据*/
+          let msg = {
+            type:item.type,
+            employee_id:item.employee_id,
+            event_time:item.event_time,
+            files:item.files,
+            item_id:item.item_id,
+            point:item.point,
+            pt_id:item.pt_id,
+            remark:item.remark,
+            reviewer_id:item.reviewer_id,
+            rule_id:item.rule_id,
+            businessId:item.businessId,
+          }
+          this.rwsBusinessData.msgQueue.push(JSON.parse(JSON.stringify(msg)))
+        })
+      })
+      this.rwsBusinessData.showBusiness = true;
+
+
+      /*开始提交*/
+      this.rwsPointEntry();
+    },
+    rwsBusinessVerify(){
+      if (this.items.length === 0) {
+        this.showMessage("请选择规则或者分类");
+        return false;
+      }
+
+      if (this.rwsBusinessData.employees.length === 0) {
+        this.showMessage("请选择录入对象");
+        return false;
+      }
+
+      this.rwsBusinessData.items = this.items.map(item => {
+        item.reviewer_id = item.reviewer_list.length > 0 ? item.reviewer_list[0].id : '';
+        return item;
+      })
+
+
+      let userMaxPoint = null;
+      let userMinPoint = null;
+
+      this.$userInfo().point_config.point_limit.forEach(point => {
+        if (this.ptId !== point.pt_id) return;
+        userMaxPoint = Math.abs(point.point);
+        userMinPoint = userMaxPoint * -1;
+      });
+
+
+      let members = this.rwsBusinessData.employees.map(employee => employee.id);
+      let items = [];
+
+      // for ([item,index] of this.rwsBusinessData.items){
+      for (var i = 0; i < this.rwsBusinessData.items.length; i++){
+        let item = this.rwsBusinessData.items[i];
+        items.push({
+          rule_id: item.rule_id || 0,
+          item_id: item.item_id || 0,
+          point: item.point,
+          remark: item.remark,
+          event_time: item.event_time,
+          pt_id: this.ptId,
+          reviewer_id: item.reviewer_id || 0,
+          files: item.files
+        })
+
+        if (item.point === 0){
+          this.showMessage(`第${i + 1}条奖扣输入积分分值不能为0`);
+          return false;
+        }
+        if (!item.remark){
+          this.showMessage(`第${i + 1}条奖扣请输入事件内容及描述`);
+          return false;
+        }
+
+        /*非创始人并且奖扣A分/指定分类/企业配置规则内要验证权限分时,验证权限分*/
+        if (!this.isCreator && (this.ptId === 2 || !this.rule_switch || this.$userInfo().site_config.rule_limit_check > 0) && userMaxPoint !== null && userMinPoint !== null){
+          if (item.reviewer_id > 0) continue;
+
+          if (item.point > 0 && item.point > userMaxPoint){
+            this.showMessage(`第${i + 1}条奖扣输入积分分值超出权限分,请选择审批人递交`);
+            return false;
+          }else if (item.point <= 0 && item.point < userMinPoint){
+            this.showMessage(`第${i + 1}`);
+            return false;
+          }
+        }
+      }
+
+      this.rwsBusinessSubmit(members,items);
+    },
+    rwsClipResult(){
+      navigator.clipboard.writeText(JSON.stringify(this.rwsBusinessData.result));
+      this.$notify({type: 'info', message: '结果已经复制到剪切板'})
+    }
   },
   created () {
     this.itemRule=[];
@@ -503,6 +765,10 @@ export default {
     this.$nextTick(()=>{
       this.rule_switch=true;
     })
+    this.initRws();
+  },
+  beforeDestroy() {
+    this.clearRws();
   }
 }
 </script>

+ 115 - 6
src/point/view/pointHome.vue

@@ -237,6 +237,8 @@ import {getToken, setToken} from '@/utils/auth';
 import moment, {min} from 'moment';
 import Vue from 'vue';
 import { NoticeBar, Swipe, SwipeItem, Cell, Dialog,Popup,Loading  } from 'vant';
+import ReconnectingWebSocket from "reconnecting-websocket";
+import {generateUUID} from "../../utils/auth";
 Vue.use(NoticeBar)
   .use(Swipe)
   .use(SwipeItem)
@@ -306,6 +308,8 @@ export default {
         left:0,
         top:0
       },
+      rws:null,
+      rwsHasAuth:false,
     };
   },
   created() {
@@ -340,6 +344,9 @@ export default {
       this.getMenu(res);
     });
   },
+  beforeDestroy() {
+    this.clearRws();
+  },
   methods: {
     timeScopeThisWeek(){
       this.pkTimeScope = [new Date(moment().startOf('week').format('YYYY-MM-DD')),new Date(moment().endOf('week').format('YYYY-MM-DD'))]
@@ -609,10 +616,11 @@ export default {
       });
       var http1 = this.$axiosUser('get', '/api/pro/integral/statistics', { employee_id: this.userInfo.id, month: this.month }, 'v3'); // 获取个人统计
       this.rankingListname(); //排行榜
-      this.$socketApiTow.authWebSocket(() =>{
-        // this.getPkDocList();    //团队pk
-        this.opneWebSocket();   //本月B分奖扣
-      });
+      // this.$socketApiTow.authWebSocket(() =>{
+      //   // this.getPkDocList();    //团队pk
+      //   this.opneWebSocket();   //本月B分奖扣
+      // });
+      this.initRws();   //初始化websocket数据
 
       Promise.all([http1]).then(res => {
           if (res[0].data.code === 1) {
@@ -719,7 +727,8 @@ export default {
       this.saveScrollerPosition();
       if (this.pk.currentDocIndex !== index && this.pk.pkDocList.length > index){
         this.pk.currentDocIndex = index;
-        this.getPkRankList(this.pk.pkDocList[index].id)
+        // this.getPkRankList(this.pk.pkDocList[index].id)
+        this.rwsPkRankList(this.pk.pkDocList[index].id)
       }
     },
     getPkDocList(){
@@ -762,6 +771,105 @@ export default {
     },
     goAppeal(){
       this.$router.push({name:'appeal'})
+    },
+    initRws(){
+      if (this.rws){
+        this.rws.close();
+        this.rws = null;
+        this.rwsHasAuth = false;
+      }
+      this.rws = new ReconnectingWebSocket(process.env.VUE_APP_WEBSCOKET_TOW);
+      this.rws.onopen = this.onWsOpen;
+      this.rws.onmessage = this.onWsMessage;
+      this.rws.onerror = this.onWsError;
+      this.rws.onclose = this.onWsClose;
+    },
+    onWsOpen(){
+      let params = {
+        type:'auth',
+        token: getToken(),
+        machine: generateUUID(),
+      }
+      this.rws.send(JSON.stringify(params));
+    },
+    onWsMessage(event){
+      let msg = event.data ?  JSON.parse(event.data) : null;
+      if (!msg) return;
+      let type = msg.type || 'none';
+      switch (type){
+        case 'ping':
+          this.rws.send('point home keep connecting');
+          break;
+        case 'auth':
+          this.rwsHasAuth = msg.code === 1;
+          this.rwsEsInfo();
+          this.rwsPkDoc();
+          break;
+        case 'es_info':
+          if (msg.code !== 1) return;
+          let data = msg.result;
+          let task = data.task;
+          let ratio = task.ratio.enable === 0 ? '-' : `${task.ratio.reward_ratio}:1`;
+          let target_ratio = task.ratio.target <= 0 ? '0:1' : `${task.ratio.target}:1`;
+          data.ratio = {
+            ratio: ratio,
+            target_ratio: target_ratio
+          }
+          this.userMonth=data;
+          break;
+        case 'team_pk':
+          if (msg.code !== 1) return;
+          this.pk.pkTeamList = msg.result.teams;
+          this.pk.teamLoading = false;
+          this.$nextTick(() => {
+            setTimeout(() => {
+              this.restoreScrollerPosition()
+            },50)
+          })
+          break;
+      }
+    },
+    onWsError(event){
+      this.rwsHasAuth = false;
+    },
+    onWsClose(event){
+      this.rwsHasAuth = false;
+    },
+    clearRws(){
+      if (this.rws) this.rws.close();
+      this.rws = null;
+      this.rwsHasAuth = false;
+    },
+    rwsEsInfo(){
+      if (!this.rws || this.rws.readyState !== ReconnectingWebSocket.OPEN || !this.rwsHasAuth) return;
+      let params = {
+        type:'es_info',
+        recorder_id: this.userInfo.id,
+        month:this.month
+      };
+      this.rws.send(JSON.stringify(params))
+    },
+    rwsPkDoc(){
+      this.$axiosUser('get','/api/pro/pk/doc/list/visible')
+        .then(res => {
+          this.pk.pkDocList = res.data.data.list;
+          if(this.pk.pkDocList.length > 0) this.rwsPkRankList(this.pk.pkDocList[0].id)
+        })
+    },
+    rwsPkRankList(docId){
+      if (!this.rws || this.rws.readyState !== ReconnectingWebSocket.OPEN || !this.rwsHasAuth || this.pk.teamLoading) return;
+      if (!this.pk.pkTimeScope || this.pk.pkTimeScope.length !== 2) {
+        this.pk.pkTeamList = [];
+        return;
+      }
+      let type = "team_pk";
+      let params = {
+        type:type,
+        doc_id:docId,
+        start_date:this.$moment(this.pk.pkTimeScope[0]).format("YYYY-MM-DD"),
+        end_date:this.$moment(this.pk.pkTimeScope[1]).format("YYYY-MM-DD"),
+      };
+      this.rws.send(JSON.stringify(params));
     }
   },
   watch: {
@@ -769,7 +877,8 @@ export default {
       this.pk.pkTimeScope[0] = val[0]
       this.pk.pkTimeScope[1] = val[1]
       this.pk.pkTimeScopeStr = this.$moment(this.pk.pkTimeScope[0]).format("MM/DD") + "-" + this.$moment(this.pk.pkTimeScope[1]).format("MM/DD");
-      if (this.pk.pkDocList.length > this.pk.currentDocIndex) this.getPkRankList(this.pk.pkDocList[this.pk.currentDocIndex].id)
+      // if (this.pk.pkDocList.length > this.pk.currentDocIndex) this.getPkRankList(this.pk.pkDocList[this.pk.currentDocIndex].id)
+      if (this.pk.pkDocList.length > this.pk.currentDocIndex) this.rwsPkRankList(this.pk.pkDocList[this.pk.currentDocIndex].id)
     }
   }
 };