applicationIntegrationPopup.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. <template>
  2. <div>
  3. <!-- 奖扣ab分弹窗 -->
  4. <el-dialog
  5. :title="title"
  6. :visible.sync="visible"
  7. :close-on-click-modal="false"
  8. :before-close="closePopup"
  9. width="600px">
  10. <div>
  11. <el-form :model="dialogData" ref="dialogData" label-width="80px" v-loading="loading">
  12. <div v-for="(item,index) in dialogData.items" :key="index" @click="itemIndex = index">
  13. <div style="overflow: hidden;">
  14. <span style="line-height: 36px;">申请明细({{index+1}})</span>
  15. <el-button type="text" class="fr" v-show="index > 0 || dialogData.items.length > 1" @click="delItem(index)">删除</el-button>
  16. </div>
  17. <el-form-item label="录入对象" :prop="'items.'+ index +'.employeeName'" :rules="[{ required: true, message: '请选择录入对象', trigger: 'change' }]">
  18. <el-row>
  19. <el-col :span="18">
  20. <el-input auto-complete="off" v-model="item.employeeName" placeholder="请选择录入对象"></el-input>
  21. <div @click="item.show_employee_selector = true" style=" position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 9;"></div>
  22. </el-col>
  23. </el-row>
  24. <EmployeeSelector
  25. :employee_not_select="item.employee_not_select"
  26. :can_select_employee="true"
  27. :can_select_dept="false"
  28. :multi="false"
  29. :selected="item.employee_selected"
  30. :visible.sync="item.show_employee_selector"
  31. @confirm="employee_confirm"/>
  32. </el-form-item>
  33. <el-form-item label="指定规则">
  34. <el-switch
  35. v-model="item.rule_switch"
  36. @change="switchChange(index,item.rule_switch)"
  37. active-color="#13ce66">
  38. </el-switch>
  39. </el-form-item>
  40. <el-form-item label="选择规则" v-if="item.rule_switch" :prop="'items.'+ index +'.rule_item_list_value'" :rules="[{ required: true, message: '请选择规则', trigger: 'blur' }]">
  41. <el-cascader
  42. v-model="item.rule_item_list_value"
  43. ref="ruleItem"
  44. :popper-class="'itemClass'"
  45. :options="rule_item_list"
  46. @change="ruleItemChange"
  47. :show-all-levels="false"
  48. :props="{ children: 'child', label: 'name', value: 'id'}"
  49. ></el-cascader>
  50. </el-form-item>
  51. <el-form-item v-if="item.rule_switch && item.rule_id">
  52. <div v-show="item.rule_item_details.range_type == 1">{{get_point_name(item.rule_item_details.pt_id)}} {{item.rule_item_details.min_point}}</div>
  53. <div v-show="item.rule_item_details.range_type == 2">{{get_point_name(item.rule_item_details.pt_id)}} {{item.rule_item_details.min_point}} ~ {{item.rule_item_details.max_point}}</div>
  54. <div>{{item.rule_item_details.name}}</div>
  55. </el-form-item>
  56. <el-form-item label="发生时间" :prop="'items.'+ index +'.event_time'" :rules="[{ required: true, message: '请选择时间', trigger: 'blur' }]">
  57. <el-row>
  58. <el-col :span="18">
  59. <el-date-picker v-model="item.event_time" type="date" placeholder="请选择时间" value-format="yyyy-MM-dd"></el-date-picker>
  60. </el-col>
  61. </el-row>
  62. </el-form-item>
  63. <el-form-item label="事件内容" :prop="'items.'+ index +'.remark'" :rules="[{ required: true, message: '请输入事件内容', trigger: 'blur' },{ min: 3, max: 100, message: '长度在 3 到 100 个字符', trigger: 'blur' }]">
  64. <el-row>
  65. <el-col :span="18">
  66. <el-input type="textarea" rows="6" placeholder="请输入事件内容" style="width: 100%;" v-model="item.remark"></el-input>
  67. </el-col>
  68. </el-row>
  69. </el-form-item>
  70. <el-form-item label="图片" label-width="100px">
  71. </el-form-item>
  72. <el-form-item label="审批人" :prop="'items.'+ index +'.approvalName'" :rules="[{ required: true, message: '请选择审批人', trigger: 'blur' }]">
  73. <el-row>
  74. <el-col :span="18">
  75. <el-input auto-complete="off" v-model="item.approvalName" placeholder="请选择审批人"></el-input>
  76. <div v-if="item.approval_selected.length == 0" @click="approval_selected_null" style=" position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 9;"></div>
  77. <div v-else @click="item.show_approval_selector = true" style=" position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 9;"></div>
  78. </el-col>
  79. </el-row>
  80. <EmployeeSelector
  81. :employee_not_select="item.approval_not_select"
  82. :can_select_employee="true"
  83. :can_select_dept="false"
  84. :multi="false"
  85. :employee_list="item.approval_employee_list"
  86. :selected="item.approval_selected"
  87. :visible.sync="item.show_approval_selector"
  88. @confirm="approval_confirm"/>
  89. </el-form-item>
  90. </div>
  91. <el-form-item style="margin-bottom: 0;">
  92. <div>如需录入多条,请点击“增加一条”</div>
  93. </el-form-item>
  94. <el-form-item style="margin-bottom: 0;">
  95. <el-button type="primary" plain @click="addItem">+ 增加一条</el-button>
  96. </el-form-item>
  97. <el-form-item style="text-align: right; margin-bottom: 0;">
  98. <el-button @click="closeDialog('dialogData')">取 消</el-button>
  99. <el-button :disabled="btn_loading" type="primary" @click="subData('dialogData')">确 认</el-button>
  100. </el-form-item>
  101. </el-form>
  102. </div>
  103. </el-dialog>
  104. <el-dialog
  105. :title="'提交结果'"
  106. :visible.sync="error_list_show"
  107. :append-to-body='true'
  108. @close='error_list_SX'
  109. width="700px">
  110. <el-table :data="error_list">
  111. <el-table-column prop="target" label="员工"></el-table-column>
  112. <el-table-column prop="point" label="积分"></el-table-column>
  113. <el-table-column prop="status" label="处理状态">
  114. <template slot-scope="scope">
  115. <span :style="'color:'+(scope.row.status==0?'#f70000':'#47bf47')">{{scope.row.status==0?'申请失败':'申请成功'}}</span>
  116. </template>
  117. </el-table-column>
  118. <el-table-column prop="msg" label="备注信息"></el-table-column>
  119. </el-table>
  120. </el-dialog>
  121. </div>
  122. </template>
  123. <script>
  124. import moment from 'moment'
  125. import EmployeeSelector from '@/components/EmployeeSelector'
  126. // import uploadOss from "@/views/upload_oss/upload"
  127. export default {
  128. name: 'applicationIntegration',
  129. // 数据
  130. model: {
  131. prop: 'list',
  132. event: 'value'
  133. },
  134. props:{
  135. title: {
  136. type: String,
  137. default: ''
  138. },
  139. visible:{
  140. type: Boolean,
  141. default: false
  142. },
  143. integralType:{
  144. type: Number,
  145. default: 0
  146. }
  147. },
  148. data() {
  149. return {
  150. error_list:[],//错误信息数组
  151. error_list_show:false,//错误信息弹窗
  152. Xtoken: { 'X-Token': this.$getToken() },
  153. loading: false,
  154. dialogData:{
  155. items: [{
  156. rule_switch: true,
  157. rule_id: '',
  158. item_id: '',
  159. remark: '',
  160. event_time: moment().format('YYYY-MM-DD'),
  161. // 审批人信息
  162. reviewer_id: '',
  163. approvalName: '',
  164. approval_not_select: [],
  165. approval_employee_id:0,//当前选中人的直属上级。0表示没有直属上级
  166. approval_employee_list: [],//当前选中人的 上级
  167. approval_selected: {dept: [],employee:[]},
  168. show_approval_selector: false,
  169. // 录入对象
  170. employee_id: '',
  171. employeeName: '',
  172. employee_not_select: [],
  173. employee_selected: {dept: [],employee:[]},
  174. show_employee_selector: false,
  175. // 附件
  176. fileList: [],
  177. files: [],
  178. // 规则分类 与 规则细则 名称
  179. rule_list_value: null,
  180. rule_item_list_value: null,
  181. rule_item_details: {range_type: ''}
  182. }]
  183. },
  184. // 规则分类
  185. rule_list: [],
  186. // 规则细则
  187. rule_item_list: [],
  188. flatteningIntegralRules: null,
  189. user_info: null,
  190. employee_map: JSON.parse(localStorage.getItem('SET_EMPLOYEE_MAP')),
  191. point_types: JSON.parse(localStorage.getItem('SET_POINT_TYPES')),
  192. btn_loading: false
  193. }
  194. },
  195. components: {EmployeeSelector},
  196. watch:{},
  197. mounted() {
  198. // this.getRuleItemData()
  199. // this.user_info = this.$store.getters.user_info
  200. // this.point_types = JSON.parse(localStorage.getItem('SET_POINT_TYPES'))
  201. // // 初始化录入对象
  202. // this.dialogData.items[0].employee_selected.employee = [{id: this.user_info.id ,img_url: this.user_info.img_url,name: this.user_info.name}]
  203. // this.dialogData.items[0].employee_id = this.user_info.id
  204. // this.dialogData.items[0].employeeName = this.user_info.name
  205. // this.initializesReviewer(this.user_info.employee_detail.superior_list,0,true)
  206. },
  207. methods: {
  208. // 附件上传
  209. beforeUpload(file){
  210. const isJPG = /^image\/(jpeg|png|jpg)$/.test(file.type)
  211. const isLt2M = file.size / 1024 / 1024 < 1
  212. if (!isJPG) {
  213. this.$message.error('上传头像图片只能是 JPG 格式!')
  214. }
  215. if (!isLt2M) {
  216. this.$message.error('上传头像图片大小不能超过 2MB!')
  217. }
  218. return isJPG && isLt2M
  219. },
  220. onFilePreView(file) {
  221. window.open(file.response.url,'_blank')
  222. },
  223. onFileRemove(file, fileList) {
  224. this.dialogData.items[this.itemIndex].fileList = fileList
  225. this.dialogData.items[this.itemIndex].files = []
  226. fileList.forEach((element,index) => {
  227. this.dialogData.items[this.itemIndex].files.push(element.url)
  228. });
  229. },
  230. handleFilesSuccess(response, file, fileList) {
  231. this.dialogData.items[this.itemIndex].fileList = fileList
  232. this.dialogData.items[this.itemIndex].files = []
  233. fileList.forEach((element,index) => {
  234. this.dialogData.items[this.itemIndex].files.push(element.url)
  235. });
  236. },
  237. // 审核人为空
  238. approval_selected_null(){
  239. this.$message.error('您没有审批人,请联系管理员');
  240. },
  241. // 获取规则信息
  242. getRuleData(){
  243. let data = {
  244. cycle_type: '1'
  245. }
  246. this.integralType === 1?data.pt_id = '1':this.integralType === 2?data.pt_id = '2':data.pt_id = '3'
  247. this.$axios('get','/api/integral/rule/trees',data).then(res => {
  248. if (res.data.code == 1) {
  249. const resultData = res.data.data
  250. this.rule_list = resultData.rule_tree
  251. }
  252. this.rule_list = this.getTreeData(this.rule_list)
  253. }).catch(e => {this.$message.error(e.data.msg)})
  254. },
  255. // 获取规则细则
  256. getRuleItemData(){
  257. let data = {cycle_type: '1'}
  258. this.loading = true
  259. this.$axios('get','/api/integral/rule/trees',data,'v2').then(res => {
  260. if (res.data.code == 1) {
  261. const resultData = res.data.data
  262. this.rule_item_list = resultData.tree
  263. this.flatteningIntegralRules = this.getItemDetail(this.rule_item_list)
  264. this.loading = false
  265. }
  266. }).catch(e => {this.$message.error(e.data.msg)})
  267. },
  268. // 规则细则变化关闭down
  269. ruleItemChange(value){
  270. const item = this.dialogData.items[this.itemIndex]
  271. let ruleItemDetail = null
  272. this.flatteningIntegralRules.forEach(element => {
  273. if (element.id == value[value.length - 1]) {
  274. ruleItemDetail = {...element}
  275. }
  276. })
  277. item.rule_item_details = ruleItemDetail
  278. item.remark = ruleItemDetail.name
  279. item.rule_id = ruleItemDetail.pid
  280. item.item_id = value[value.length - 1]
  281. this.$refs.ruleItem.dropDownVisible = false;
  282. },
  283. // 规则分类变化关闭dewn
  284. ruleChange(value){
  285. this.dialogData.items[this.itemIndex].rule_id = value[value.length - 1]
  286. this.$refs.rule.dropDownVisible = false;
  287. },
  288. // 递归判断列表,把最后的child设为undefined
  289. getTreeData(data) {
  290. for (var i = 0; i < data.length; i++) {
  291. if (data[i].child.length < 1) {
  292. // child若为空数组,则将child设为undefined
  293. data[i].child = undefined;
  294. } else {
  295. // child若不为空数组,则继续 递归调用 本方法
  296. this.getTreeData(data[i].child);
  297. }
  298. }
  299. return data;
  300. },
  301. getItemDetail(arr) {
  302. let result = []
  303. for (const item of arr) {
  304. var res = JSON.parse(JSON.stringify(item)) // 先克隆一份数据作为第一层级的填充
  305. delete res['child']
  306. result.push(res)
  307. if (item.child instanceof Array && item.child.length > 0) { // 如果当前child为数组并且长度大于0,才可进入getItemDetail()方法
  308. result = result.concat(this.getItemDetail(item.child))
  309. }
  310. }
  311. return result
  312. },
  313. // 加一条
  314. addItem(){
  315. this.dialogData.items.push({
  316. rule_switch: true,
  317. rule_id: '',
  318. item_id: '',
  319. remark: '',
  320. event_time: moment().format('YYYY-MM-DD'),
  321. // 审批人信息
  322. reviewer_id: '',
  323. approvalName: '',
  324. approval_not_select: [],
  325. approval_employee_id:0,//当前选中人的直属上级。0表示没有直属上级
  326. approval_employee_list: [],
  327. approval_selected: {dept: [],employee:[]},
  328. show_approval_selector: false,
  329. // 录入对象
  330. employee_id: this.user_info.id,
  331. employeeName: this.user_info.name,
  332. employee_not_select: [],
  333. employee_selected: {dept: [],employee:[{id: this.user_info.id ,img_url: this.user_info.img_url,name: this.user_info.name}]},
  334. show_employee_selector: false,
  335. // 附件
  336. fileList: [],
  337. files: [],
  338. // 规则分类 与 规则细则 名称
  339. rule_list_value: null,
  340. rule_item_list_value: null,
  341. rule_item_details: {range_type: ''}
  342. })
  343. },
  344. closeDialog(formName){
  345. this.$refs[formName].resetFields();
  346. this.$emit('update:visible', false)
  347. },
  348. delItem(index){
  349. this.$confirm('你确定要删除奖扣明细'+parseInt(index+1)+'吗?', '提示', {
  350. confirmButtonText: '确定',
  351. cancelButtonText: '取消',
  352. type: 'warning'
  353. }).then(() => {
  354. this.dialogData.items.splice(index, 1)
  355. this.$message({
  356. type: 'success',
  357. message: '删除成功!'
  358. });
  359. }).catch(() => {});
  360. },
  361. subData(formName){
  362. this.$refs[formName].validate((valid) => {
  363. if (valid) {
  364. this.btn_loading = true
  365. this.save()
  366. }
  367. });
  368. },
  369. // 提交数据
  370. save(){
  371. let data = {items: []}
  372. this.dialogData.items.forEach(element => {
  373. data.items.push({rule_id: element.rule_id || 0, employee_id: element.employee_id || 0 ,item_id: element.item_id || 0, remark: element.remark, event_time: element.event_time, pt_id: element.pt_id, reviewer_id: element.reviewer_id || 0, files: element.files})
  374. });
  375. this.$axios('post','/api/integral/review/apply',data,'v2').then(res => {
  376. if(res.data.code == 1){
  377. this.$refs['dialogData'].resetFields();
  378. this.$emit('update:visible', false)
  379. this.$message.success(res.data.msg)
  380. this.error_list = res.data.data.list
  381. this.error_list_show = true
  382. this.dialogData.items[0].employee_id = this.user_info.id
  383. }else{
  384. this.$message.error(res.data.msg)
  385. }
  386. this.btn_loading = false
  387. }).catch(e => {this.$message.close()})
  388. },
  389. //关闭错误信息时的回调
  390. error_list_SX(){
  391. // this.loadBaseData();
  392. // this.loadEmployeeList()
  393. },
  394. // 当switch 改变了
  395. switchChange(index,value){
  396. this.itemIndex = index
  397. const item = this.dialogData.items[this.itemIndex]
  398. if (!value) {
  399. item.rule_id = ""
  400. item.item_id = ""
  401. item.rule_item_list_value = ""
  402. item.rule_item_details = {range_type: ''}
  403. }else{
  404. item.rule_id = ""
  405. item.rule_list_value = ""
  406. }
  407. },
  408. // 初始化审核人
  409. initializesReviewer(list,index,bool){
  410. const superior = list || this.user_info.employee_detail.superior_list
  411. const num = index || 0
  412. const item = this.dialogData.items[num]
  413. item.approval_employee_list = [...superior]
  414. if (superior.length !== 0) {
  415. if(bool){
  416. item.approval_employee_id = this.user_info.employee_detail.superior_id//直属上级(这里是第一个,默认为当前登录人)
  417. }
  418. if(item.approval_employee_id != 0){//判断有无直属上级
  419. for(let a in item.approval_employee_list){
  420. if(item.approval_employee_id == item.approval_employee_list[a].id){
  421. item.approval_employee_list[a].direct_Supervisor = true//一个字段,是直属上级的字段,为true
  422. }
  423. }
  424. for(let i in superior){
  425. if(item.approval_employee_id == superior[i].id){
  426. item.approval_selected.employee = [{id: superior[i].id ,img_url: superior[i].img_url,name: superior[i].name}]
  427. item.reviewer_id = superior[i].id
  428. item.approvalName = superior[i].name//审批人
  429. }
  430. }
  431. }else{
  432. // 拿取列表最后一个的数据,没有筛选
  433. item.approval_selected.employee = [{id: superior[superior.length - 1].id ,img_url: superior[superior.length - 1].img_url,name: superior[superior.length - 1].name}]
  434. item.reviewer_id = superior[superior.length - 1].id//审批人id
  435. item.approvalName = superior[superior.length - 1].name//审批人name
  436. }
  437. }
  438. },
  439. // 选择审核人
  440. approval_confirm(data){
  441. const item = this.dialogData.items[this.itemIndex]
  442. item.approvalName = ''
  443. item.approval_selected.employee = {dept: [],employee:[]}
  444. item.reviewer_id = ''
  445. if (data.employee !== null && data.employee.length != 0) {
  446. item.approvalName = data.employee[0].name
  447. item.approval_selected.employee = [{name: data.employee[0].name,id:data.employee[0].id,img_url: data.employee[0].img_url}]
  448. item.reviewer_id = data.employee[0].id
  449. }
  450. },
  451. // 选择对象
  452. employee_confirm(data){
  453. const item = this.dialogData.items[this.itemIndex]
  454. for (const key in this.employee_map) {
  455. if (this.employee_map.hasOwnProperty(key)) {
  456. const element = this.employee_map[key];//循环人员列表
  457. if(element.id == data.employee[0].id){//通过选中的id拿到当前人员信息
  458. item.approval_employee_id = element.superior_id//选中对象的直属上级id
  459. this.initializesReviewer(element.superior_list,this.itemIndex)
  460. }
  461. }
  462. }
  463. item.employeeName = ''
  464. item.employee_selected.employee = {dept: [],employee:[]}
  465. item.employee_id = ''
  466. if (data.employee !== null && data.employee.length != 0) {
  467. item.employeeName = data.employee[0].name
  468. item.employee_selected.employee = [{name: data.employee[0].name,id:data.employee[0].id,img_url: data.employee[0].img_url}]
  469. item.employee_id = data.employee[0].id
  470. }
  471. },
  472. // 获取积分名称
  473. get_point_name(id){
  474. let name = ''
  475. this.point_types.forEach(element => {
  476. if (element.id == id) {
  477. name = element.name
  478. }
  479. });
  480. return name
  481. },
  482. // 关闭弹窗
  483. closePopup(){
  484. this.$emit('update:visible', false)
  485. }
  486. }
  487. }
  488. </script>
  489. <style lang="scss">
  490. .itemClass .el-cascader-menu .el-cascader-menu__wrap li.el-cascader-node{
  491. height: auto;
  492. max-width: 500px;
  493. .el-cascader-node__label{
  494. white-space: initial;
  495. overflow: initial;
  496. text-overflow: initial;
  497. }
  498. }
  499. // ruleClass
  500. // itemClass
  501. </style>