PerReviewsSelector.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <template>
  2. <el-dialog :visible.sync="innerVisible" @close="handleClose" @open="initData" @closed="dataReset" append-to-body
  3. :close-on-click-modal="false" center title="审批节点配置" width="600px">
  4. <el-form v-if="currentNode" label-width="200">
  5. <el-form-item label="启用">
  6. <el-switch v-model="currentNode.enable" />
  7. </el-form-item>
  8. <el-form-item label="">
  9. <div class="handler-list">
  10. <el-tag v-for="(item,index) in currentNode.children" :key="`hl_${index}`"
  11. :type="childIndex === index ? '' : 'info'" closable @close="removeChild(index)" @click="childSelect(index)">
  12. {{assigneeMap[item.assigneeType] || '未知'}}
  13. </el-tag>
  14. <el-button v-show="currentNode.enable" icon="el-icon-plus" size="mini" style="margin-bottom: 10px;"
  15. @click="addChild" />
  16. </div>
  17. </el-form-item>
  18. <el-form-item label="审批人">
  19. <el-radio-group v-model="currentNode.children[childIndex].assigneeType" :disabled="!currentNode.enable"
  20. @change="onAssigneeTypeChange">
  21. <el-radio-button label="leader">组织管理员</el-radio-button>
  22. <el-radio-button label="user">指定人员</el-radio-button>
  23. <el-radio-button label="self">被考核人</el-radio-button>
  24. <el-radio-button label="post">岗位</el-radio-button>
  25. <el-radio-button label="deptLeader">部门负责人</el-radio-button>
  26. </el-radio-group>
  27. </el-form-item>
  28. <div class="flex-center-center" style="margin-left: 100px;">
  29. <el-form-item label="">
  30. <template v-if="currentNode.children[childIndex].assigneeType === 'leader'">
  31. <el-select v-model="currentNode.children[childIndex].leaderLevel" placeholder="请选择管理员"
  32. :disabled="!currentNode.enable" filterable style="width: 300px;" key="leader"
  33. @change="onOrgManagerChange">
  34. <el-option v-for="item in levelOptions" :key="`leader_${item.value}`" :label="item.label"
  35. :value="item.value" style="width: 300px;" />
  36. </el-select>
  37. <br>
  38. <div class="fontColorC">(<span style="color: red"> * </span>被考核人所在部门的直接上级或上上级 )</div>
  39. </template>
  40. <template v-if="currentNode.children[childIndex].assigneeType === 'user'">
  41. <el-select v-model="userSelected" placeholder="请选择指定人员" multiple :disabled="!currentNode.enable" filterable
  42. style="width: 300px;" key="user" @change="onUserChange">
  43. <el-option v-for="item in employees" :key="`user_${item.id}`" :label="item.name" :value="item.id"
  44. style="width: 300px;" />
  45. </el-select>
  46. <br>
  47. <div class="fontColorC">(<span style="color: red"> * </span>直接选择需要的人员 )</div>
  48. </template>
  49. <template v-if="currentNode.children[childIndex].assigneeType === 'post'">
  50. <el-select v-model="postSelected" placeholder="请选择岗位" multiple :disabled="!currentNode.enable" filterable
  51. style="width: 300px;" key="post" @change="onPostChange">
  52. <el-option v-for="item in postList" :key="`post_${item.id}`" :label="item.name" :value="item.id"
  53. style="width: 300px;" />
  54. </el-select>
  55. <br>
  56. <div class="fontColorC">(<span style="color: red"> * </span>组织架构下,所属岗位的成员 )</div>
  57. </template>
  58. <template v-if="currentNode.children[childIndex].assigneeType === 'deptLeader'">
  59. <el-select v-model="deptSelected" placeholder="请选择部门" multiple :disabled="!currentNode.enable" filterable
  60. style="width: 300px;" key="deptLeader" @change="onDeptChange">
  61. <el-option v-for="item in deptList" :key="`deptLeader_${item.id}`" :label="item.name" :value="item.id"
  62. style="width: 300px;" />
  63. </el-select>
  64. <br>
  65. <div class="fontColorC">(<span style="color: red"> * </span>组织架构中,所设置的部门管理员 )</div>
  66. </template>
  67. </el-form-item>
  68. </div>
  69. <el-form-item label="多人时">
  70. <el-radio-group v-model="currentNode.children[childIndex].multipleType" :disabled="!currentNode.enable">
  71. <el-radio-button label="or">任一人确认(或签)</el-radio-button>
  72. <el-radio-button label="parallel">按顺序确认(会签)</el-radio-button>
  73. <el-radio-button label="sequence">同时确认(会签)</el-radio-button>
  74. </el-radio-group>
  75. <div class="flex-center-center fontColorC" style="margin-left: 100px;">
  76. ( <span style="color: red;"> * </span><span>会签要求所有审批人一致同意</span> )
  77. </div>
  78. <div class="flex-center-center fontColorC" style="margin-left: 100px;">
  79. ( <span style="color: red;"> * </span><span>或签只需任一审批人同意即可</span> )
  80. </div>
  81. </el-form-item>
  82. <!-- <el-form-item label="允许">
  83. <el-checkbox-group
  84. v-model="currentNode.children[childIndex].allows"
  85. :disabled="!currentNode.enable"
  86. >
  87. <el-checkbox-button label="transfer">转交</el-checkbox-button>
  88. </el-checkbox-group>
  89. </el-form-item> -->
  90. </el-form>
  91. </el-dialog>
  92. </template>
  93. <script>
  94. import Template from "@/examine/components/Template.vue";
  95. export default {
  96. name: "PerReviewsSelector",
  97. components: {Template},
  98. props: {
  99. showVisible: {
  100. type: Boolean,
  101. default: false
  102. },
  103. indicator:{
  104. type: Object,
  105. default: () =>{
  106. return null
  107. }
  108. }
  109. },
  110. data(){
  111. return {
  112. userInfo: this.$userInfo(),
  113. currentNode: null,
  114. childIndex: null,
  115. innerVisible: this.showVisible,
  116. loading:false,
  117. employees:[],
  118. postList:[],
  119. deptList:[],
  120. userSelected:[],
  121. postSelected:[],
  122. deptSelected:[],
  123. assigneeMap:{
  124. leader:'组织管理员',
  125. user:'指定人员',
  126. self:'被考核人',
  127. post:'岗位',
  128. deptLeader:'部门负责人',
  129. },
  130. levelOptions: [
  131. {
  132. value: 1,
  133. label: '直接管理员'
  134. },
  135. {
  136. value: 2,
  137. label: '二级管理员'
  138. },
  139. {
  140. value: 3,
  141. label: '三级管理员'
  142. },
  143. {
  144. value: 4,
  145. label: '四级管理员'
  146. },
  147. {
  148. value: 5,
  149. label: '五级管理员'
  150. },
  151. {
  152. value: 6,
  153. label: '六级管理员'
  154. }
  155. ]
  156. }
  157. },
  158. computed:{
  159. employeeMap(){
  160. const map = {};
  161. this.employees.forEach(e => {
  162. if (!map[e.id]) map[e.id] = e.name;
  163. });
  164. return map;
  165. },
  166. postMap(){
  167. const map = {};
  168. this.postList.forEach(e => {
  169. if (!map[e.id]) map[e.id] = e.name;
  170. });
  171. return map;
  172. },
  173. deptMap(){
  174. const map = {};
  175. this.deptList.forEach(e => {
  176. if (!map[e.id]) map[e.id] = e.name;
  177. });
  178. return map;
  179. },
  180. },
  181. watch:{
  182. showVisible(val){
  183. this.innerVisible = val;
  184. },
  185. },
  186. methods: {
  187. matchErrMsg(err){
  188. return err.toString().replace(/[(Error: )]/g,'');
  189. },
  190. handleClose(){
  191. this.$emit('update:showVisible',false);
  192. },
  193. dataReset(){
  194. this.currentNode = null;
  195. this.childIndex = null;
  196. this.userSelected = [];
  197. this.postSelected = [];
  198. this.deptSelected = [];
  199. },
  200. initData(){
  201. if (this.loading || !this.indicator) return;
  202. this.dataReset();
  203. this.loading = true;
  204. let result = true;
  205. Promise.all([
  206. this.$axiosUser('get', '/api/pro/employee/index', {page:0,page_size:10,status:1}, 'v2'),
  207. this.$axiosUser('get','/org/post'),
  208. this.$axiosUser('get', `/org/departments/${this.userInfo.site_id}`)
  209. ])
  210. .then(([employeeRes,postRes,deptRes]) => {
  211. if (employeeRes.data.code !== 1) throw new Error(employeeRes.data.msg);
  212. if (postRes.data.code !== 1) throw new Error(postRes.data.message);
  213. if (deptRes.data.code !== 1) throw new Error(deptRes.data.message);
  214. this.employees = employeeRes.data.data.list
  215. .filter(e => e.account_id && e.account_id > 0)
  216. .map(e => {
  217. return {
  218. id:e.id,
  219. name:e.name,
  220. }
  221. });
  222. this.postList = postRes.data.data.map(item => {
  223. return {
  224. id: item.id,
  225. name: item.name,
  226. }
  227. });
  228. this.deptList = deptRes.data.data.list.map(item => {
  229. return {
  230. id: item.id,
  231. name: item.name,
  232. }
  233. });
  234. this.currentNode = this.indicator.flow.nodes.find(node => node.type === 'reviews');
  235. this.childIndex = this.currentNode.children && this.currentNode.children.length > 0 ? 0 : null;
  236. if (this.childIndex !== null && !!this.currentNode.children[this.childIndex]){
  237. switch (this.currentNode.children[this.childIndex].assigneeType){
  238. case 'user':
  239. this.userSelected = [...this.currentNode.children[this.childIndex].assigneeIds];
  240. break;
  241. case 'post':
  242. this.postSelected = [...this.currentNode.children[this.childIndex].assigneeIds];
  243. break;
  244. case 'deptLeader':
  245. this.deptSelected = [...this.currentNode.children[this.childIndex].assigneeIds];
  246. break;
  247. }
  248. }
  249. })
  250. .catch(err => {
  251. this.$message.error(this.matchErrMsg(err));
  252. result = false;
  253. })
  254. .finally(() => {
  255. this.loading = false;
  256. if (!result) this.handleClose();
  257. })
  258. },
  259. generalId(){
  260. return Date.now() + Math.floor(Math.random() * 10000);
  261. },
  262. addChild(){
  263. let id = "R_" + this.generalId();
  264. this.currentNode.children.push({
  265. id:id,
  266. type:'review',
  267. enable:true,
  268. assigneeType:'leader',
  269. leaderLevel:1,
  270. assigneeIds:[],
  271. multipleType:'or',
  272. allows:['transfer'],
  273. weight:0,
  274. children:[],
  275. });
  276. },
  277. removeChild(index){
  278. if (this.currentNode.children.length <= 1 || !this.currentNode.children[index]) return;
  279. let selectChildId = this.currentNode.children[index].id;
  280. this.childIndex = 0;
  281. this.currentNode.children = this.currentNode.children.filter((_,i) => i !== index);
  282. if (selectChildId){
  283. this.currentNode.children.forEach((child,i) => {
  284. if (child.id === selectChildId) this.childIndex = i;
  285. })
  286. }
  287. },
  288. onAssigneeTypeChange(v){
  289. this.currentNode.children[this.childIndex].assigneeIds = [];
  290. this.currentNode.children[this.childIndex].leaderLevel = 1;
  291. this.userSelected = [];
  292. this.postSelected = [];
  293. this.deptSelected = [];
  294. },
  295. onOrgManagerChange(v){
  296. this.currentNode.children[this.childIndex].assigneeIds = [];
  297. this.currentNode.children[this.childIndex].leaderLevel = v;
  298. this.userSelected = [];
  299. this.postSelected = [];
  300. this.deptSelected = [];
  301. },
  302. onUserChange(v){
  303. this.currentNode.children[this.childIndex].assigneeIds = [...v];
  304. this.currentNode.children[this.childIndex].leaderLevel = 1;
  305. this.userSelected = v;
  306. this.postSelected = [];
  307. this.deptSelected = [];
  308. },
  309. onPostChange(v){
  310. this.currentNode.children[this.childIndex].assigneeIds = [...v];
  311. this.currentNode.children[this.childIndex].leaderLevel = 1;
  312. this.userSelected = [];
  313. this.postSelected = v;
  314. this.deptSelected = [];
  315. },
  316. onDeptChange(v){
  317. this.currentNode.children[this.childIndex].assigneeIds = [...v];
  318. this.currentNode.children[this.childIndex].leaderLevel = 1;
  319. this.userSelected = [];
  320. this.postSelected = [];
  321. this.deptSelected = v;
  322. },
  323. childSelect(index){
  324. if (!this.currentNode.children[index]) return;
  325. this.childIndex = index;
  326. this.userSelected = this.currentNode.children[this.childIndex].assigneeType === 'user' ? this.currentNode.children[this.childIndex].assigneeIds : [];
  327. this.postSelected = this.currentNode.children[this.childIndex].assigneeType === 'post' ? this.currentNode.children[this.childIndex].assigneeIds : [];
  328. this.deptSelected = this.currentNode.children[this.childIndex].assigneeType === 'deptLeader' ? this.currentNode.children[this.childIndex].assigneeIds : [];
  329. }
  330. }
  331. }
  332. </script>
  333. <style scoped lang="scss">
  334. .handler-list {
  335. width: 500px;
  336. margin: 0 auto 16px auto;
  337. border-radius: 6px;
  338. border: 1px solid #d7dae2;
  339. padding: 10px 0 0 10px;
  340. box-sizing: border-box;
  341. display: flex;
  342. flex-wrap: wrap;
  343. .el-tag {
  344. margin: 0 10px 10px 0;
  345. cursor: pointer;
  346. }
  347. }
  348. </style>