TargetConfirms.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <template>
  2. <div>
  3. <el-dialog :title="dialogTitle" center :visible.sync="targetConfirms" width="600px"
  4. :before-close="handleCloseDialog">
  5. <div v-if="currentNode">
  6. <el-form ref="form" label-width="80px" size="small">
  7. <el-form-item label="启用">
  8. <el-switch v-model="currentNode.enable"></el-switch>
  9. </el-form-item>
  10. <div class="handler-list">
  11. <el-tag v-for="(item, index) in currentNode.children" :key="index"
  12. :type="childIndex === index ? '' : 'info'" closable @close="handleTagDelete(index)"
  13. @click="handleTagClick(item, index)">
  14. {{ item.assigneeType | filterType }}
  15. </el-tag>
  16. <el-button v-show="currentNode.enable" icon="el-icon-plus" size="mini"
  17. style="margin-bottom: 10px;" @click="addTagList()"></el-button>
  18. </div>
  19. <el-form-item :label="formLabel">
  20. <el-radio-group v-model="currentNode.children[childIndex].assigneeType"
  21. :disabled="!currentNode.enable" @change="changeAssigneeType">
  22. <el-radio-button label="leader">管理员</el-radio-button>
  23. <el-radio-button label="user">指定人员</el-radio-button>
  24. <el-radio-button label="self">被考核人</el-radio-button>
  25. <el-radio-button label="post">岗位</el-radio-button>
  26. <el-radio-button label="deptLeader">部门</el-radio-button>
  27. </el-radio-group>
  28. </el-form-item>
  29. <el-form-item v-if="currentNode.children[childIndex].assigneeType === 'leader'">
  30. <el-select v-model="selected_manager_ids" placeholder="请选择管理员" :disabled="!currentNode.enable"
  31. filterable style="width: 300px;" @change="changeManagerIds">
  32. <el-option v-for="item in levelOptions" :key="item.value" :label="item.label"
  33. :value="item.value" style="width: 300px;"></el-option>
  34. </el-select>
  35. </el-form-item>
  36. <el-form-item v-if="currentNode.children[childIndex].assigneeType === 'user'">
  37. <el-select v-model="selected_employee_ids" placeholder="请选择指定人员" multiple
  38. :disabled="!currentNode.enable" filterable style="width: 300px;"
  39. @change="changeEmployeeIds">
  40. <el-option v-for="item in employeeMap" :key="item.id" :label="item.name" :value="item.id"
  41. style="width: 300px;"></el-option>
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item v-if="currentNode.children[childIndex].assigneeType === 'post'">
  45. <el-select v-model="selected_post_ids" placeholder="请选择岗位" multiple
  46. :disabled="!currentNode.enable" filterable style="width: 300px;" @change="changePostIds">
  47. <el-option v-for="item in postList" :key="item.id" :label="item.name" :value="item.id"
  48. style="width: 300px;"></el-option>
  49. </el-select>
  50. </el-form-item>
  51. <el-form-item v-if="currentNode.children[childIndex].assigneeType === 'deptLeader'">
  52. <el-cascader ref="deptSelectRef" v-model="selected_dept_ids" size="small" style="width: 300px;"
  53. :options="deptList" :props="cascaderProps" placeholder="请选择部门" filterable clearable
  54. @change="deptChange" :disabled="!currentNode.enable"></el-cascader>
  55. </el-form-item>
  56. <el-form-item label="多人时">
  57. <el-radio-group v-model="currentNode.children[childIndex].multipleType"
  58. :disabled="!currentNode.enable">
  59. <el-radio-button label="or">任一人确认(或签)</el-radio-button>
  60. <el-radio-button label="parallel">按顺序确认(会签)</el-radio-button>
  61. <el-radio-button label="sequence">同时确认(会签)</el-radio-button>
  62. </el-radio-group>
  63. </el-form-item>
  64. <el-form-item label="允许">
  65. <el-checkbox-group v-model="currentNode.children[childIndex].allows"
  66. :disabled="!currentNode.enable">
  67. <el-checkbox-button label="edit">修改指标</el-checkbox-button>
  68. <el-checkbox-button label="transfer">转交</el-checkbox-button>
  69. </el-checkbox-group>
  70. </el-form-item>
  71. </el-form>
  72. </div>
  73. <div slot="footer">
  74. <el-button type="primary" @click="submitForm" size="small">确 定</el-button>
  75. <el-button @click="handleCloseDialog" size="small">取 消</el-button>
  76. </div>
  77. </el-dialog>
  78. </div>
  79. </template>
  80. <script>
  81. import { mapGetters } from 'vuex';
  82. import EmployeeSelector from '@/components/EmployeeSelector'; // 选择部门组件
  83. // 引入lodash库
  84. import _ from 'lodash';
  85. export default {
  86. components: {
  87. EmployeeSelector,
  88. },
  89. model: {
  90. prop: 'targetConfirms',
  91. event: 'close-dialog'
  92. },
  93. props: {
  94. targetConfirms: {
  95. type: Boolean,
  96. default: false
  97. },
  98. dialogTitle: {
  99. type: String,
  100. default: ''
  101. },
  102. nodeType: {
  103. type: String,
  104. default: ''
  105. },
  106. formLabel: {
  107. type: String,
  108. default: ''
  109. },
  110. templateId: {
  111. type: String | Number,
  112. default: ''
  113. },
  114. indicatorId: {
  115. type: String | Number,
  116. default: ''
  117. },
  118. tagIndex: {
  119. type: String | Number,
  120. default: 0
  121. },
  122. selectNodes: {
  123. type: Array,
  124. default: () => []
  125. }
  126. },
  127. computed: {
  128. ...mapGetters(['user_info'])
  129. },
  130. data() {
  131. return {
  132. cascaderProps: {
  133. multiple: true, // 启用多选
  134. checkStrictly: true, // 父子节点不联动
  135. emitPath: false, // 选中值只返回当前节点的值
  136. },
  137. levelOptions: [
  138. {
  139. value: 1,
  140. label: '直接管理员'
  141. },
  142. {
  143. value: 2,
  144. label: '二级管理员'
  145. },
  146. {
  147. value: 3,
  148. label: '三级管理员'
  149. },
  150. {
  151. value: 4,
  152. label: '四级管理员'
  153. },
  154. {
  155. value: 5,
  156. label: '五级管理员'
  157. },
  158. {
  159. value: 6,
  160. label: '六级管理员'
  161. }
  162. ],
  163. deptList: JSON.parse(localStorage.getItem("deptList")), // 部门列表 - 树形结构
  164. dept_list: JSON.parse(localStorage.getItem("dept_list")), // 部门列表
  165. employeeMap: this.$getEmployeeMap(), // 员工列表
  166. postList: JSON.parse(localStorage.getItem("postList")), // 岗位列表
  167. selected_dept_ids: [], // 选择的部门列表
  168. selected_manager_ids: '', // 选择的管理员列表
  169. selected_post_ids: [], // 选择的岗位列表
  170. selected_employee_ids: [], // 选择的员工列表
  171. childIndex: 0,
  172. currentNode: null,
  173. }
  174. },
  175. filters: {
  176. filterType(v) {
  177. if (v == 'leader') return v = "管理员"
  178. if (v == 'self') return v = "被考核人"
  179. if (v == 'post') return v = "岗位"
  180. if (v == 'user') return v = "指定人员"
  181. if (v == 'deptLeader') return v = "部门"
  182. }
  183. },
  184. watch: {
  185. 'targetConfirms'(v) {
  186. if (v) this.initData()
  187. },
  188. },
  189. mounted() {
  190. this.initData();
  191. },
  192. methods: {
  193. initData() {
  194. this.selectNodes.forEach(select => {
  195. // 正在操作的节点
  196. if (select.type == this.nodeType) this.currentNode = _.cloneDeep(select)
  197. })
  198. this.selected_manager_ids = 1;
  199. this.selected_employee_ids = [];
  200. this.selected_post_ids = [];
  201. this.selected_dept_ids = [];
  202. this.childIndex = this.tagIndex;
  203. this.currentNode.children.forEach(child => {
  204. this.selected_employee_ids = child.assigneeType === 'user' ? child.assigneeIds : [];
  205. this.selected_post_ids = child.assigneeType === 'post' ? child.assigneeIds : [];
  206. this.selected_dept_ids = child.assigneeType === 'deptLeader' ? child.assigneeIds : [];
  207. });
  208. console.log("表单信息");
  209. console.log(this.currentNode);
  210. },
  211. // 选择管理员
  212. changeManagerIds(v) {
  213. this.currentNode.children[this.childIndex].assigneeIds = []
  214. this.currentNode.children[this.childIndex].leaderLevel = v ? v : 1
  215. },
  216. // 选择员工
  217. changeEmployeeIds(v) {
  218. this.currentNode.children[this.childIndex].assigneeIds = []
  219. this.currentNode.children[this.childIndex].assigneeIds = v ? v : []
  220. },
  221. // 选择岗位
  222. changePostIds(v) {
  223. this.currentNode.children[this.childIndex].assigneeIds = []
  224. this.currentNode.children[this.childIndex].assigneeIds = v ? v : []
  225. },
  226. // 选择部门
  227. deptChange(val) {
  228. // 获取当前选中的节点
  229. const checkedNodes = this.$refs.deptSelectRef.getCheckedNodes();
  230. this.selected_dept_ids = checkedNodes.map((node) => node.value);
  231. this.currentNode.children[this.childIndex].assigneeIds = []
  232. this.currentNode.children[this.childIndex].assigneeIds = this.selected_dept_ids.length ? this.selected_dept_ids : []
  233. },
  234. changeAssigneeType(v) {
  235. this.currentNode.children[this.childIndex].assigneeIds = []
  236. this.currentNode.children[this.childIndex].leaderLevel = 1
  237. this.selected_manager_ids = 1;
  238. this.selected_employee_ids = [];
  239. this.selected_post_ids = [];
  240. this.selected_dept_ids = [];
  241. this.currentNode.children.forEach((child, index) => {
  242. if (index == this.childIndex) {
  243. this.selected_manager_ids = child.assigneeType === 'leader' ? child.leaderLevel : 1;
  244. this.selected_employee_ids = child.assigneeType === 'user' ? child.assigneeIds : [];
  245. this.selected_post_ids = child.assigneeType === 'post' ? child.assigneeIds : [];
  246. this.selected_dept_ids = child.assigneeType === 'deptLeader' ? child.assigneeIds : [];
  247. }
  248. });
  249. },
  250. changeFormEnable(v) {
  251. this.currentNode.enable = v;
  252. },
  253. // 添加子节点
  254. addTagList() {
  255. let id, type;
  256. if (this.nodeType == 'targetConfirms') {
  257. id = "TC_" + Date.now() + Math.floor(Math.random() * 10000);
  258. type = "targetConfirm"
  259. }
  260. if (this.nodeType == 'scores') {
  261. id = "S_" + Date.now() + Math.floor(Math.random() * 10000);
  262. type = "score"
  263. }
  264. if (this.nodeType == 'reviews') {
  265. id = "R_" + Date.now() + Math.floor(Math.random() * 10000);
  266. type = "review"
  267. }
  268. let obj = {
  269. allows: [],
  270. assigneeIds: [],
  271. assigneeType: 'self',
  272. children: [],
  273. enable: true,
  274. id,
  275. leaderLevel: 1,
  276. multipleType: "or",
  277. type,
  278. weight: 0,
  279. }
  280. this.currentNode.children.push(obj);
  281. this.childIndex = this.currentNode.children.length - 1;
  282. this.selected_manager_ids = 1; // 选择的管理员
  283. this.selected_dept_ids = []; // 选择的部门列表
  284. this.selected_post_ids = [] // 选择的岗位列表
  285. this.selected_employee_ids = [] // 选择的员工列表
  286. },
  287. handleTagClick(item, index) {
  288. this.childIndex = index;
  289. this.selected_manager_ids = 1;
  290. this.selected_employee_ids = [];
  291. this.selected_post_ids = [];
  292. this.selected_dept_ids = []; // 选择的部门列表
  293. // 回显下拉框数据
  294. this.selected_employee_ids = item.assigneeType === 'user' ? item.assigneeIds : [];
  295. this.selected_post_ids = item.assigneeType === 'post' ? item.assigneeIds : [];
  296. this.selected_dept_ids = item.assigneeType === 'deptLeader' ? item.assigneeIds : [];
  297. },
  298. handleTagDelete(index) {
  299. // 最后一个不能删除
  300. if (this.currentNode && this.currentNode.children.length > 1) {
  301. let selectChildId = this.currentNode.children[this.childIndex].id;
  302. this.childIndex = 0;
  303. this.currentNode.children = this.currentNode.children.filter((_, i) => i !== index);
  304. if (selectChildId) {
  305. this.currentNode.children.forEach((child, i) => {
  306. if (child.id === selectChildId) this.childIndex = i;
  307. })
  308. }
  309. }
  310. },
  311. handleCloseDialog() {
  312. this.currentNode = null
  313. this.selected_manager_ids = 1;
  314. this.selected_employee_ids = [];
  315. this.selected_post_ids = [];
  316. this.selected_dept_ids = [];
  317. this.$emit('close-dialog', false)
  318. },
  319. submitForm() {
  320. // 验证表单数据
  321. if (this.currentNode.children && this.currentNode.children.length > 0) {
  322. for (let i = 0; i < this.currentNode.children.length; i++) {
  323. if (this.currentNode.children[i].assigneeType === 'self') {
  324. this.currentNode.children[i].assigneeIds.push(this.user_info.id);
  325. // 去重
  326. this.currentNode.children[i].assigneeIds = Array.from(new Set(this.currentNode.children[i].assigneeIds))
  327. }
  328. let flag = this.currentNode.children[i].assigneeIds && this.currentNode.children[i].assigneeIds.length > 0
  329. if (this.currentNode.children[i].assigneeType === 'leader') {
  330. if (!this.currentNode.children[i].leaderLevel) return this.$message.error("请选择管理员")
  331. }
  332. if (this.currentNode.children[i].assigneeType === 'deptLeader') {
  333. if (!flag) return this.$message.error("请选择部门")
  334. }
  335. if (this.currentNode.children[i].assigneeType === 'user') {
  336. if (!flag) return this.$message.error("请选择指定人员")
  337. }
  338. if (this.currentNode.children[i].assigneeType === 'post') {
  339. if (!flag) return this.$message.error("请选择岗位")
  340. }
  341. }
  342. }
  343. let nodes = []
  344. this.selectNodes.forEach(select => {
  345. // 正在操作的节点
  346. if (select.type == this.nodeType) {
  347. select = this.currentNode
  348. console.log(select)
  349. }
  350. nodes.push(select)
  351. })
  352. let data = {
  353. indicatorId: this.indicatorId, // 指标ID
  354. nodes
  355. }
  356. this.$emit("onConfirm", data);
  357. this.handleCloseDialog();
  358. },
  359. handleFormData() {
  360. }
  361. }
  362. }
  363. </script>
  364. <style lang="scss" scoped>
  365. .handler-list {
  366. width: 500px;
  367. margin: 0 auto 16px auto;
  368. border-radius: 6px;
  369. border: 1px solid #d7dae2;
  370. padding: 10px 0 0 10px;
  371. box-sizing: border-box;
  372. display: flex;
  373. flex-wrap: wrap;
  374. .el-tag {
  375. margin: 0 10px 10px 0;
  376. }
  377. }
  378. </style>