integral_entry_n.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. <template>
  2. <div>
  3. <van-nav-bar :title="ptId==2?'奖扣A分':'奖扣B分'" left-text="返回" @click-left="$route_back" left-arrow></van-nav-bar>
  4. <div class="body_com" :class="{ isIos: isIos }">
  5. <scroller :isNeed="isNeed">
  6. <van-cell-group>
  7. <EmployeeSelectorCell is_employee_list required bar_title="选择录入对象" title="录入对象" :employee_list="manage_scope"
  8. v-model="employee_list" :multi="true" iconType="friends-o" :max="10"
  9. ></EmployeeSelectorCell>
  10. <van-cell title="指定规则">
  11. <template slot="title">
  12. <span @click="openText">指定规则<van-icon name="question" class="fontColorC" style="position: relative;top: 2px;left: 3px;color:#969799;"/></span>
  13. </template>
  14. <template slot="right-icon">
  15. <van-switch :disabled="specified_rule_item" v-model="rule_switch" size="24"/>
  16. </template>
  17. </van-cell>
  18. <!--选择规则 -->
  19. <van-cell
  20. v-if="rule_switch"
  21. title="选择规则"
  22. @click="showRuleSelector = true"
  23. required
  24. :value="itemRule.length <= 0 ? '' : `已选${itemRule.length}条`"
  25. />
  26. <!-- <RuleCategorySelectorCell v-if="rule_switch" required ref="rule_selector" name="选择规则" title="选择规则" v-model="itemRule" :ptId="ptId" scope></RuleCategorySelectorCell>-->
  27. <!--选择分类 -->
  28. <CategorySelectorCell v-if="!rule_switch" title="选择分类" ref="rule_selector2" v-model="ruleCate" required :ptId="ptId" scope></CategorySelectorCell>
  29. </van-cell-group>
  30. <div v-for="(item, index) in items" :key="index">
  31. <van-cell-group>
  32. <div class="flex-box-ce" style="padding: 0.24rem 0.32rem;font-size: 0.32rem;padding-bottom: 0rem;">
  33. <div class="flex-1 item-title">{{rule_switch?'已选规则':'已选分类'}}({{index+1}})</div>
  34. <div @click="diy_item_del(item,index)" class="red" style="font-size: 0.28rem">删除</div>
  35. </div>
  36. <div style="background-color: #f5f7fa;border-radius: 5px;padding:0.2rem;margin: 0.24rem 0.32rem;font-size: 0.28rem;">
  37. <div style="word-break:break-all">{{ item.name }}</div>
  38. <div v-if="item.range_type == 1">
  39. <span :class="item.min_point > 0 ? 'red' : 'green'">{{ item.min_point }}</span>
  40. {{ $getTypesName(ptId) }}
  41. </div>
  42. <div v-if="item.range_type == 2">
  43. <span :class="item.min_point > 0 ? 'red' : 'green'">{{ item.min_point }}</span>
  44. <span :class="item.max_point > 0 ? 'red' : 'green'">{{ item.max_point }}</span>
  45. {{ $getTypesName(ptId) }}
  46. </div>
  47. </div>
  48. <!--申请事由 -->
  49. <van-cell required >
  50. <div class="flex-box-ce" style="font-size: 0.32rem;">
  51. <div class="flex-1">事件内容及描述</div>
  52. <div class="blue" @click="item.remark=''" style="font-size: 0.28rem">清空</div>
  53. </div>
  54. <Mtextarea v-model="item.remark" placeholder="请输入事件内容" name="申请事由" v-validate="'required|max:300'"
  55. :text_max="300" :imgs_max="3" images :imgs.sync="item.files"
  56. ></Mtextarea>
  57. </van-cell>
  58. <!--积分 -->
  59. <NumberInput v-model="item.point" :min.sync="item.min_point" :max.sync="item.max_point" name="积分" title="积分" required :border="item.point_remark == ''"></NumberInput>
  60. <!--选择规则 -->
  61. <div v-if="item.point_remark != ''" class="point-remark-box">{{item.point_remark}}</div>
  62. <!--发生时间 -->
  63. <DateCell required title="发生时间" name="日期" :maxDate="maxDate" v-model="item.event_time"></DateCell>
  64. <!--选择递交审批人 -->
  65. <div v-if="!isCreator">
  66. <EmployeeSelectorCell
  67. is_employee_list
  68. bar_title="选择递交审批人"
  69. title="递交审批"
  70. v-model="item.reviewer_list"
  71. :multi="false"
  72. iconType="records"
  73. :max="1"
  74. :employee_list="superior_list"
  75. ></EmployeeSelectorCell>
  76. </div>
  77. </van-cell-group>
  78. </div>
  79. <div style="height: 5rem;"></div>
  80. </scroller>
  81. </div>
  82. <div v-isKeyboard>
  83. <div class="flex-box-ce footer">
  84. <van-button size="large" plain type="info" style="margin-right: 0.2rem;width: 2rem;" @click="openSelect">已选{{items.length}}条</van-button>
  85. <!-- <van-button size="large" @click="data_verify" type="info" :disabled="!rwsHasAuth" >提交</van-button>-->
  86. <van-button size="large" @click="rwsBusinessVerify" type="info" :disabled="!rwsHasAuth" >提交</van-button>
  87. </div>
  88. </div>
  89. <!-- 提交结果 -->
  90. <!-- <van-popup v-model="isResult" style="width: 90%;border-radius: 5px;">-->
  91. <!-- <div v-if="!isShowError" style="padding: 0.24rem;">-->
  92. <!-- <van-progress :percentage="percentage" />-->
  93. <!-- <div style="margin-top: 10px;border: 1px solid #f1f1f1;max-height: 7rem;overflow-y: auto;" class="scroll-bar">-->
  94. <!-- <div class="flex-box-ce results" style="font-weight: 600;">-->
  95. <!-- <div style="border-right: 1px solid #f1f1f1;width: 40px;">序号</div>-->
  96. <!-- <div class="flex-1" style="border-right: 1px solid #f1f1f1;">奖扣对象</div>-->
  97. <!-- <div class="flex-1" style="border-right: 1px solid #f1f1f1;">积分</div>-->
  98. <!-- <div class="flex-1" >处理结果</div>-->
  99. <!-- </div>-->
  100. <!-- <div class="flex-box-ce results" v-for="(item, index) in results" :key="index">-->
  101. <!-- <div style="border-right: 1px solid #f1f1f1;width: 40px;">{{results.length-index}}</div>-->
  102. <!-- <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.target }}</div>-->
  103. <!-- <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.point>0? '+'+item.point:item.point }}<span> {{ $getTypesName(ptId) }}</span></div>-->
  104. <!-- <div class="flex-1" v-if="item.status == 1">-->
  105. <!-- <span v-if="item.msg=='奖扣成功'" class="green">{{ item.msg }}</span>-->
  106. <!-- <span class="blue" v-else>{{ item.msg }}</span>-->
  107. <!-- </div>-->
  108. <!-- <div class="flex-1 red" v-else>{{ item.msg }}</div>-->
  109. <!-- </div>-->
  110. <!-- </div>-->
  111. <!-- <div class="flex-box-end" style="margin-top: 20px;" v-show="results.length==resultList.length">-->
  112. <!-- <van-button type="info" @click="isResult = false" size="small">确 定</van-button>-->
  113. <!-- </div>-->
  114. <!-- </div>-->
  115. <!-- <div v-else>-->
  116. <!-- <div style="text-align: center;" class="red">{{errorMsg}}</div>-->
  117. <!-- <div>-->
  118. <!-- <div class="flex-box-end" style="margin-top: 10px;">-->
  119. <!-- <van-button type="info" @click="isResult = false" size="small">确 定</van-button>-->
  120. <!-- </div>-->
  121. <!-- </div>-->
  122. <!-- </div>-->
  123. <!-- </van-popup>-->
  124. <RuleScopeSelector :visible.sync = showRuleSelector :selected="itemRule" multi @confirm="selected => itemRule = selected" :pt-id="ptId" />
  125. <!-- rws提交结果 -->
  126. <van-popup v-model="rwsBusinessData.showBusiness" :close-on-click-overlay="false" style="width: 90%; border-radius: 5px;">
  127. <div style="padding: 0.24rem;">
  128. <van-progress :percentage="rwsBusinessProgress" />
  129. <div style="margin-top: 10px;border: 1px solid #f1f1f1;max-height: 7rem;overflow-y: auto;" class="scroll-bar">
  130. <div class="flex-box-ce results" style="font-weight: 600;">
  131. <div style="border-right: 1px solid #f1f1f1;width: 40px;">序号</div>
  132. <div class="flex-1" style="border-right: 1px solid #f1f1f1;">奖扣对象</div>
  133. <div class="flex-1" style="border-right: 1px solid #f1f1f1;">积分</div>
  134. <div class="flex-1" >处理结果</div>
  135. </div>
  136. <div class="flex-box-ce results" v-for="(item,index) in rwsBusinessData.dataList" :key="index">
  137. <div style="border-right: 1px solid #f1f1f1;width: 40px;">{{`${index + 1}`}}</div>
  138. <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.employee_name }}</div>
  139. <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.point>0? '+'+item.point:item.point }}<span> {{ $getTypesName(ptId) }}</span></div>
  140. <div class="flex-1">
  141. <span :class="{'cyan':item.status === -2,'origin':item.status === -1,'green':item.status === 1,'red':item.status === 0}" >{{item.msg}}</span>
  142. </div>
  143. </div>
  144. </div>
  145. <!-- <div class="flex-box-end" style="margin-top: 20px;" v-show="rwsBusinessProgress >= 100">-->
  146. <!-- <van-button type="info" @click="rwsBusinessData.showBusiness = false" size="small">确 定</van-button>-->
  147. <!-- </div>-->
  148. <div class="flex-box-end" style="margin-top: 20px;">
  149. <van-button type="info" :disabled="rwsBusinessProgress < 100" @click="rwsBusinessData.showBusiness = false" size="small" >确 定</van-button>
  150. <van-tag style="margin-left: 0.2rem;" @click.prevent.stop="rwsClipResult">{{rwsBusinessData.result.length}} / {{rwsBusinessData.dataList.length}}</van-tag>
  151. </div>
  152. </div>
  153. </van-popup>
  154. </div>
  155. </template>
  156. <script>
  157. import Mtextarea from '@/components/Mtextarea'
  158. import NumberInput from '@/components/NumberInput'
  159. import EmployeeSelectorCell from '@/components/EmployeeSelectorCell'
  160. // import RuleCategorySelectorCell from '@/components/RuleCategorySelectorCell1'
  161. import CategorySelectorCell from '@/components/CategorySelectorCell'
  162. import DateCell from '@/components/DateCell'
  163. import moment from 'moment'
  164. import Vue from 'vue'
  165. import ImageCamera from '@/attendance/components/image-camera';
  166. import {Switch,Progress} from 'vant'
  167. import RuleScopeSelector from "../../../components/RuleScopeSelector.vue";
  168. import ReconnectingWebSocket from "reconnecting-websocket";
  169. import {generateUUID, getToken} from "../../../utils/auth";
  170. import Clipboard from "clipboard";
  171. Vue.use(Switch).use(Progress)
  172. export default {
  173. name: 'integral_entry_n',
  174. components: {
  175. RuleScopeSelector,
  176. DateCell,
  177. Mtextarea,
  178. EmployeeSelectorCell,
  179. // RuleCategorySelectorCell,
  180. CategorySelectorCell,
  181. NumberInput,
  182. ImageCamera
  183. },
  184. data () {
  185. return {
  186. showRuleSelector:false,
  187. isNeed:!this.$getCache('isAndroid'),
  188. manage_scope: this.$userInfo().employee_detail.manage_scope,
  189. superior_list:this.$userInfo().employee_detail.superior_list,
  190. specified_rule_item:this.$userInfo().site_config.specified_rule_item? true:false,//奖扣时是否必选规则
  191. isIos: this.$getCache('iPhone'),
  192. ptId: 3,
  193. dialogData: {
  194. members: [],
  195. items: []
  196. },
  197. itemRule:[],//规则数组
  198. ruleCate:[],//分类数据
  199. rule_switch:'',
  200. items: [],
  201. item: {//模板数据
  202. rule_id: '',
  203. item_id: '',
  204. point: 0,
  205. remark: '',
  206. name:'',
  207. event_time: moment().format('YYYY-MM-DD'),
  208. pt_id: 3,
  209. // 积分填写限制
  210. max: 0,
  211. min: 0,
  212. // 审批人信息
  213. reviewer_id: '',
  214. approvalName: '',
  215. approval_selected: { dept: [], employee: [] },
  216. show_approval_selector: false,
  217. reviewer_list:[],
  218. // 附件
  219. fileList: [],
  220. files: []
  221. },
  222. employee_list: [],
  223. isCreator: this.$userInfo().is_creator,
  224. maxDate: new Date(2050, 12, 30),
  225. // 长连接结果
  226. results: [], //提交的返回结果集合
  227. // results:[{target: "碧玉", status: 1, point: 50, rule_item: "录入成功", msg:'奖扣成功',task: {employee_id: 1976, site_id: 389}}],
  228. isResult: false,
  229. percentage: 0,
  230. resultList:[],//要发送数据的集合
  231. resultIndex:0,
  232. isShowError:false,
  233. errorMsg:'服务器繁忙,请稍后再试',
  234. rws:null,
  235. rwsHasAuth:false,
  236. rwsBusinessData:{
  237. showBusiness:false,
  238. dataList:[],
  239. msgQueue:[],
  240. result:[],
  241. employees:[],
  242. items:[],
  243. }
  244. }
  245. },
  246. watch: {
  247. rule_switch(){
  248. this.itemRule=[];
  249. this.ruleCate=[];
  250. this.items=[];
  251. },
  252. ruleCate(val){
  253. let items = []
  254. val.forEach((e,index) => {
  255. if(this.isItemId(e.id,2)){
  256. let item=this.isItemId(e.id,2)
  257. if(item){
  258. item.max_point = 100000;
  259. item.min_point = -100000;
  260. }
  261. items.push(item)
  262. }else{
  263. let item = JSON.parse(JSON.stringify(this.item));
  264. item.rule_id = e.id;
  265. item.name=e.name
  266. item.max_point = 100000;
  267. item.min_point = -100000;
  268. items.push(item);
  269. }
  270. });
  271. this.items = items;
  272. },
  273. itemRule(rules){
  274. if (rules.length > 0) {
  275. let items = []
  276. rules.forEach(e => {
  277. if(this.isItemId(e.id,1)){
  278. items.push(this.isItemId(e.id,1))
  279. }else{
  280. let item = JSON.parse(JSON.stringify(this.item));
  281. item.remark = e.remark;
  282. item.name = e.remark;
  283. item.rule_id = e.rule_id;
  284. item.item_id = e.id;
  285. item.max = e.max_point * 1;
  286. item.min = e.min_point * 1;
  287. item.max_point = e.max_point * 1;
  288. item.min_point = e.min_point * 1;
  289. item.point = e.min_point;
  290. item.range_type = e.range_type;
  291. if (e.range_type == 1) {
  292. item.point_remark = '固定:' + e.min_point + this.$getTypesName(this.ptId)
  293. } else {
  294. item.point_remark = '范围(可修改):' + e.min_point + '至' + e.max_point + this.$getTypesName(this.ptId)
  295. }
  296. items.push(item);
  297. }
  298. });
  299. this.items = items;
  300. } else {
  301. this.items = [];
  302. }
  303. },
  304. employee_list(val) {
  305. // if (val.length > 0) {
  306. // this.dialogData.members = []
  307. // this.dialogData.members=val.map(element => {
  308. // return element.id
  309. // })
  310. // } else {
  311. // this.dialogData.members = []
  312. // }
  313. //
  314. // console.log(val);
  315. this.rwsBusinessData.employees = val && val.length > 0 ? val : [];
  316. },
  317. isResult(val){
  318. if(!val){
  319. this.isShowError = false;
  320. this.errorMsg='服务器繁忙,请稍后再试';
  321. this.dialogData={
  322. members: [],
  323. items: []
  324. };
  325. this.itemRule=[];//规则数组
  326. this.ruleCate=[];//分类数据
  327. this.rule_switch=true;
  328. this.items=[];
  329. this.employee_list= [];
  330. this.$socketApi.closewebsocket();
  331. }
  332. },
  333. 'rwsBusinessData.showBusiness'(v){
  334. if (!v){
  335. this.initRwsBusinessData();
  336. this.dialogData = {
  337. members: [],
  338. items: []
  339. };
  340. this.itemRule = [];
  341. this.ruleCate = [];
  342. this.rule_switch = true;
  343. this.items = [];
  344. this.employee_list = [];
  345. }
  346. }
  347. },
  348. computed:{
  349. rwsBusinessProgress(){
  350. return this.rwsBusinessData.dataList.length === 0 ? 0 : Math.floor(this.rwsBusinessData.dataList.filter(item => item.status >= 0).length / this.rwsBusinessData.dataList.length * 100);
  351. }
  352. },
  353. methods: {
  354. openText(){
  355. this.$dialog.alert({
  356. message: '指定规则:根据公司已经制定好的积分规则标准事由来进行奖扣或申请积分\n不指定规则:可以自由填写事由(即积分规则标准以外的内容)进行奖扣或申请积分',
  357. }).then(() => {
  358. // on close
  359. });
  360. },
  361. openSelect(){
  362. if(this.rule_switch){
  363. this.$refs.rule_selector.show_dept_selector=true;
  364. }else{
  365. this.$refs.rule_selector2.show_dept_selector=true;
  366. }
  367. },
  368. showMessage(str){
  369. this.$notify({type: 'danger', message: str})
  370. },
  371. data_verify () {
  372. // console.log(this.dialogData,this.items);return ;
  373. let dialogData=this.dialogData
  374. dialogData.items=this.items.map(e=>{
  375. if(e.reviewer_list.length>0){
  376. e.reviewer_id=e.reviewer_list[0].id
  377. }else{
  378. e.reviewer_id=''
  379. }
  380. return e
  381. })
  382. if(dialogData.members.length==0){
  383. this.showMessage('请选择录入对象')
  384. return false
  385. }
  386. if(dialogData.items.length==0){
  387. this.showMessage('请选择规则或者分类')
  388. return false
  389. }
  390. let str='';
  391. let isError=false
  392. let user_info =this.$userInfo();
  393. // 规则内积分是否需要检验权限分 0-不需要 1-需要
  394. let ruleLimitCheck = user_info.site_config.rule_limit_check;//是否现有验证权限分 0-不需要 1-需要
  395. let userMaxPoint = null;//当前用户权限分(正分)
  396. let userMinPoint = null;//当前用户权限分(负分)
  397. user_info.point_config.point_limit.forEach(element => {
  398. if (this.ptId == element.pt_id) {
  399. userMaxPoint = element.point * 1;
  400. userMinPoint = element.point * -1;
  401. }
  402. });
  403. if(!this.isCreator){//创始人不需要验证
  404. if(this.ptId==2||ruleLimitCheck||!this.rule_switch){ // 1.A分一定要验证,2.B分受配置影响,3.分类要验证
  405. this.dialogData.items.some((element, i) => {
  406. if(!element.reviewer_id){
  407. if(element.point>0){
  408. if(element.point>userMaxPoint){ //正分判断
  409. isError=true;
  410. str='第' + (i + 1) + '条奖扣输入积分分值超出权限分,请选择审批人递交';
  411. return true;
  412. }
  413. }else{
  414. if(element.point<userMinPoint){//负分判断
  415. isError=true;
  416. str='第' + (i + 1) + '条奖扣输入积分分值超出权限分,请选择审批人递交';
  417. return true;
  418. }
  419. }
  420. }
  421. })
  422. }
  423. }
  424. this.dialogData.items.some((element, i) => {
  425. if(element.point==0){
  426. isError=true;
  427. str='第' + (i + 1) + '条奖扣输入积分分值不能为0';
  428. return true;
  429. }
  430. if(!element.remark){
  431. isError=true;
  432. str='第' + (i + 1) + '条奖扣请输入事件内容及描述';
  433. return true;
  434. }
  435. })
  436. if(isError){
  437. this.$notify({type: 'danger', message: str})
  438. return false;
  439. }
  440. let data = {
  441. members: this.dialogData.members,
  442. items: []
  443. };
  444. this.dialogData.items.forEach((element, i) => {
  445. data.items.push({
  446. rule_id: element.rule_id || 0,
  447. item_id: element.item_id || 0,
  448. point: element.point,
  449. remark: element.remark,
  450. event_time: element.event_time,
  451. pt_id: this.ptId,
  452. reviewer_id: element.reviewer_id || 0,
  453. files: element.files
  454. });
  455. });
  456. // console.log(data,this.dialogData);this.isResult = true; return ;
  457. this.rwsBusinessSubmit(data.members,data.items);
  458. // this.webSocket(data);
  459. },
  460. webSocket(data){
  461. let {members,items}=data;
  462. let arr=[];
  463. members.forEach(item=>{
  464. items.forEach(item2=>{
  465. item2.type = this.ptId === 2?'pea':'peb';
  466. item2.employee_id=item;
  467. arr.push(JSON.parse(JSON.stringify(item2)))
  468. })
  469. })
  470. this.resultList=arr;
  471. this.resultIndex=0;
  472. this.percentage=0;
  473. this.results=[];
  474. this.isResult=true;
  475. this.opneWebSocket()
  476. },
  477. opneWebSocket() {
  478. let wsData=this.resultList;
  479. if(wsData[this.resultIndex]&&!this.isShowError){
  480. this.$socketApi.sendData(wsData[this.resultIndex],this.onmessageWS)
  481. }
  482. },
  483. onmessageWS(e){
  484. if(e.type=='peb'||e.type=='pea'){
  485. this.results.unshift(e.result);
  486. this.resultIndex++;
  487. this.opneWebSocket();
  488. // 进度条
  489. let lng = this.resultList.length;
  490. this.percentage += Math.floor(100 / lng);
  491. if (lng == this.results.length) {
  492. this.percentage = 100;
  493. }
  494. }
  495. // 连接不上
  496. if(e.type=='error'){
  497. this.errorMsg=e.msg
  498. this.isShowError = true;
  499. }
  500. },
  501. //判断是否已经存在
  502. isItemId(id,index){
  503. let item='';
  504. this.items.some((x)=> {
  505. if(index==1){
  506. if(x.item_id==id){
  507. item=x
  508. return true;
  509. }
  510. }else{
  511. if(x.rule_id==id){
  512. item=x
  513. return true;
  514. }
  515. }
  516. });
  517. return item
  518. },
  519. diy_item_del (item,index) {
  520. this.$dialog.confirm({
  521. message:this.rule_switch?'你确定要删除该奖扣规则吗':'你确定要删除该奖扣分类吗'
  522. }).then(() => {
  523. if(this.rule_switch){
  524. this.itemRule.some((e,index2)=>{
  525. if(item.item_id==e.id){
  526. this.itemRule.splice(index2, 1);
  527. this.items.splice(index, 1)
  528. return true;
  529. }
  530. })
  531. }else{
  532. this.ruleCate.some((e,index2)=>{
  533. if(item.rule_id==e.id){
  534. this.ruleCate.splice(index2, 1);
  535. return true;
  536. }
  537. })
  538. }
  539. }).catch(() => {});
  540. },
  541. initRws(){
  542. if (this.rws){
  543. this.rws.close();
  544. this.rws = null;
  545. this.rwsHasAuth = false;
  546. }
  547. this.rws = new ReconnectingWebSocket(process.env.VUE_APP_WEBSCOKET);
  548. this.rws.onopen = this.onWsOpen;
  549. this.rws.onmessage = this.onWsMessage;
  550. this.rws.onerror = this.onWsError;
  551. this.rws.onclose = this.onWsClose;
  552. },
  553. initRwsBusinessData(){
  554. this.rwsBusinessData.dataList = [];
  555. this.rwsBusinessData.msgQueue = [];
  556. this.rwsBusinessData.result = [];
  557. this.rwsBusinessData.items = [];
  558. },
  559. onWsOpen(){
  560. let params = {
  561. type:'auth',
  562. token: getToken(),
  563. machine: generateUUID(),
  564. }
  565. this.rws.send(JSON.stringify(params));
  566. },
  567. onWsMessage(event){
  568. let msg = event.data ? JSON.parse(event.data) : null;
  569. if (!msg) return;
  570. let type = msg.type || 'none';
  571. switch (type){
  572. case 'ping':
  573. this.rws.send('point entry keep connecting');
  574. break;
  575. case 'auth':
  576. this.rwsHasAuth = msg.code === 1;
  577. break;
  578. case 'pea':
  579. case 'peb':
  580. this.rwsBusinessData.result.push(msg);
  581. let businessId = msg.result.task.msg.businessId;
  582. this.rwsBusinessData.dataList.forEach(item => {
  583. if (item.businessId !== businessId) return;
  584. item.status = msg.result.status;
  585. item.msg = msg.result.msg;
  586. })
  587. this.rwsPointEntry();
  588. break;
  589. }
  590. },
  591. onWsError(event){
  592. console.log('on ws error',event);
  593. this.rwsHasAuth = false;
  594. },
  595. onWsClose(event){
  596. console.log('on ws close',event)
  597. this.rwsHasAuth = false;
  598. },
  599. clearRws(){
  600. if (this.rws) this.rws.close();
  601. this.rws = null;
  602. this.rwsHasAuth = false;
  603. this.initRwsBusinessData();
  604. },
  605. rwsPointEntry(){
  606. let msg = this.rwsBusinessData.msgQueue.shift();
  607. if (!msg) return;
  608. this.rwsBusinessData.dataList.forEach(item => {
  609. if (item.businessId !== msg.businessId) return;
  610. item.status = -1;
  611. item.msg = '处理中';
  612. })
  613. this.rws.send(JSON.stringify(msg));
  614. },
  615. rwsBusinessSubmit(members,items){
  616. if (!members || members.length <= 0 || !items || items.length <= 0) {
  617. this.showMessage('规则/分类以及录入对象必须选择');
  618. return;
  619. }
  620. let employeeMap = {}
  621. this.rwsBusinessData.employees.forEach(employee => {
  622. employeeMap[employee.id] = employee;
  623. });
  624. let businessId = 1;
  625. this.initRwsBusinessData(); //清空提交业务数据
  626. members.forEach(memberId => {
  627. items.forEach(item => {
  628. item.type = this.ptId === 2 ? 'pea' : 'peb';
  629. item.employee_id = memberId;
  630. item.employee_name = employeeMap[memberId] ? employeeMap[memberId].name : '';
  631. item.status = -2;
  632. item.msg = '待处理';
  633. item.businessId = businessId;
  634. this.rwsBusinessData.dataList.push(JSON.parse(JSON.stringify(item)))
  635. businessId++;
  636. /*队列数据*/
  637. let msg = {
  638. type:item.type,
  639. employee_id:item.employee_id,
  640. event_time:item.event_time,
  641. files:item.files,
  642. item_id:item.item_id,
  643. point:item.point,
  644. pt_id:item.pt_id,
  645. remark:item.remark,
  646. reviewer_id:item.reviewer_id,
  647. rule_id:item.rule_id,
  648. businessId:item.businessId,
  649. }
  650. this.rwsBusinessData.msgQueue.push(JSON.parse(JSON.stringify(msg)))
  651. })
  652. })
  653. this.rwsBusinessData.showBusiness = true;
  654. /*开始提交*/
  655. this.rwsPointEntry();
  656. },
  657. rwsBusinessVerify(){
  658. if (this.items.length === 0) {
  659. this.showMessage("请选择规则或者分类");
  660. return false;
  661. }
  662. if (this.rwsBusinessData.employees.length === 0) {
  663. this.showMessage("请选择录入对象");
  664. return false;
  665. }
  666. this.rwsBusinessData.items = this.items.map(item => {
  667. item.reviewer_id = item.reviewer_list.length > 0 ? item.reviewer_list[0].id : '';
  668. return item;
  669. })
  670. let userMaxPoint = null;
  671. let userMinPoint = null;
  672. this.$userInfo().point_config.point_limit.forEach(point => {
  673. if (this.ptId !== point.pt_id) return;
  674. userMaxPoint = Math.abs(point.point);
  675. userMinPoint = userMaxPoint * -1;
  676. });
  677. let members = this.rwsBusinessData.employees.map(employee => employee.id);
  678. let items = [];
  679. // for ([item,index] of this.rwsBusinessData.items){
  680. for (var i = 0; i < this.rwsBusinessData.items.length; i++){
  681. let item = this.rwsBusinessData.items[i];
  682. items.push({
  683. rule_id: item.rule_id || 0,
  684. item_id: item.item_id || 0,
  685. point: item.point,
  686. remark: item.remark,
  687. event_time: item.event_time,
  688. pt_id: this.ptId,
  689. reviewer_id: item.reviewer_id || 0,
  690. files: item.files
  691. })
  692. if (item.point === 0){
  693. this.showMessage(`第${i + 1}条奖扣输入积分分值不能为0`);
  694. return false;
  695. }
  696. if (!item.remark){
  697. this.showMessage(`第${i + 1}条奖扣请输入事件内容及描述`);
  698. return false;
  699. }
  700. /*非创始人并且奖扣A分/指定分类/企业配置规则内要验证权限分时,验证权限分*/
  701. if (!this.isCreator && (this.ptId === 2 || !this.rule_switch || this.$userInfo().site_config.rule_limit_check > 0) && userMaxPoint !== null && userMinPoint !== null){
  702. if (item.reviewer_id > 0) continue;
  703. if (item.point > 0 && item.point > userMaxPoint){
  704. this.showMessage(`第${i + 1}条奖扣输入积分分值超出权限分,请选择审批人递交`);
  705. return false;
  706. }else if (item.point <= 0 && item.point < userMinPoint){
  707. this.showMessage(`第${i + 1}`);
  708. return false;
  709. }
  710. }
  711. }
  712. this.rwsBusinessSubmit(members,items);
  713. },
  714. rwsClipResult(event){
  715. const clipboard = new Clipboard(event.target,{
  716. text: () => JSON.stringify(this.rwsBusinessData.result)
  717. });
  718. clipboard.on('success',() => {
  719. this.$notify({type: 'info', message: '复制成功'});
  720. clipboard.destroy();
  721. });
  722. clipboard.on('error', () => {
  723. this.$notify({type: 'info', message: '复制失败,请联系系统管理员'});
  724. clipboard.destroy();
  725. });
  726. clipboard.onClick(event);
  727. // navigator.clipboard.writeText(JSON.stringify(this.rwsBusinessData.result));
  728. // this.$notify({type: 'info', message: '结果已经复制到剪切板'})
  729. }
  730. },
  731. created () {
  732. this.itemRule=[];
  733. this.ruleCate=[];
  734. this.items=[];
  735. this.ptId = Number(this.$route.query.type=='1'? '2':'3')
  736. this.$nextTick(()=>{
  737. this.rule_switch=true;
  738. })
  739. },
  740. activated () {
  741. this.itemRule=[];
  742. this.ruleCate=[];
  743. this.items=[];
  744. this.ptId = Number(this.$route.query.type=='1'? '2':'3')
  745. this.$nextTick(()=>{
  746. this.rule_switch=true;
  747. })
  748. this.initRws();
  749. },
  750. beforeDestroy() {
  751. this.clearRws();
  752. }
  753. }
  754. </script>
  755. <style scoped>
  756. .footer{
  757. padding: 0.24rem;
  758. position: fixed;
  759. left: 0;
  760. right: 0;
  761. bottom: 0;
  762. z-index: 2;
  763. background: #fff;
  764. border-top: 1px solid #f1f1f1;
  765. }
  766. .results{
  767. font-size: 0.28rem;
  768. text-align: center;
  769. border-bottom: 1px solid #f1f1f1;
  770. }
  771. .results div {
  772. padding: 3px;
  773. }
  774. .item-title{
  775. font-size: 0.28rem;
  776. }
  777. .search-icon {
  778. font-size: 16px;
  779. line-height: inherit;
  780. }
  781. .body_com {
  782. height: calc(100% - 0.92rem);
  783. position: relative;
  784. overflow-y: scroll;
  785. }
  786. .result{
  787. height: calc(100vh - 6.6rem);
  788. position: relative;
  789. }
  790. .add_item_cell .van-icon {
  791. color: #1989fa;
  792. }
  793. .add_item_cell .van-cell__title span {
  794. color: #1989fa;
  795. }
  796. .item-del-btn {
  797. float: right;
  798. }
  799. .point-remark-box {
  800. color: #969799;
  801. padding: 0.16rem 0.32rem;
  802. position: relative;
  803. padding-top: 0;
  804. padding-left: 2.1rem;
  805. font-size: 0.24rem;
  806. }
  807. /deep/ .van-dialog__message{
  808. text-align: left;
  809. }
  810. .point-remark-box:after {
  811. position: absolute;
  812. box-sizing: border-box;
  813. content: ' ';
  814. pointer-events: none;
  815. right: 0;
  816. bottom: 0;
  817. left: 0.32rem;
  818. border-bottom: 0.02rem solid #ebedf0;
  819. -webkit-transform: scaleY(0.5);
  820. transform: scaleY(0.5);
  821. }
  822. .rentrun {
  823. width:100vw;
  824. background: #fff;
  825. }
  826. .isIos {
  827. height: calc(100% - 2.6rem);
  828. }
  829. .successful_alert{
  830. padding-top:0.5rem;
  831. }
  832. .successful_alert /deep/ .head_icon .sucessful_icon{
  833. width:1.28rem;
  834. height:1.28rem;
  835. color:#26A2FF;
  836. padding-top:0.5rem;
  837. }
  838. .successful_alert /deep/ .head_icon .overdue_deduction{
  839. width:1.28rem;
  840. height:1.28rem;
  841. color:#F56C6C;
  842. padding-top:0.5rem;
  843. }
  844. .row_line_bg{
  845. background: #f1f1f1;
  846. font-size: 0.32rem;
  847. padding: 0.1rem 0.32rem;
  848. }
  849. .buttom_btn{
  850. line-height: 0.83rem;
  851. text-align: center;
  852. font-size: 0.32rem;
  853. position: relative;
  854. /* color: #909399 */
  855. }
  856. .buttom_btn.one::after{
  857. content: '';
  858. width: 1px;
  859. height: 0.85rem;
  860. background: #f1f1f1;
  861. display: block;
  862. position: absolute;
  863. right: 0;
  864. top: 0;
  865. bottom: 0;
  866. }
  867. </style>