staffManager.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. <template>
  2. <div class='m-container'>
  3. <h2>
  4. <div class="squrt"></div>员工管理
  5. </h2>
  6. <div class="m-core">
  7. <div @click="roleOperation('create')"
  8. v-permission="'employee/add'"
  9. class='newBand'>添加</div>
  10. <el-form :inline="true"
  11. class="searchForm"
  12. @submit.native.prevent
  13. v-model.trim="searchForm">
  14. <el-form-item>
  15. <el-input type="text"
  16. v-model.trim="searchForm.search"
  17. @keyup.enter.native='search'
  18. placeholder="姓名或手机号"></el-input>
  19. </el-form-item>
  20. <el-form-item>
  21. <el-select v-model.trim="searchForm.jobNature"
  22. clearable
  23. filterable
  24. placeholder="请选择工作类型">
  25. <el-option label="全职"
  26. value="FULL_TIME"></el-option>
  27. <el-option label="兼职"
  28. value="PART_TIME"></el-option>
  29. <el-option label="临时"
  30. value="TEMPORARY"></el-option>
  31. </el-select>
  32. </el-form-item>
  33. <el-form-item>
  34. <el-select v-model.trim="searchForm.organId"
  35. clearable
  36. filterable
  37. placeholder="请选择分部">
  38. <el-option v-for="item in branchList"
  39. :key="item.value"
  40. :label="item.label"
  41. :value="item.value"></el-option>
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item>
  45. <!-- multiple -->
  46. <el-select v-model.trim="searchForm.roleId"
  47. clearable
  48. filterable
  49. placeholder="请选择角色">
  50. <el-option v-for="item in roleList"
  51. :key="item.value"
  52. :label="item.label"
  53. :value="item.value"></el-option>
  54. </el-select>
  55. <!-- collapse-tags -->
  56. </el-form-item>
  57. <el-form-item>
  58. <el-button @click="search"
  59. type="danger">搜索</el-button>
  60. </el-form-item>
  61. </el-form>
  62. <!-- 列表 -->
  63. <div class="tableWrap">
  64. <el-table :data='tableList'
  65. :header-cell-style="{background:'#EDEEF0',color:'#444'}">
  66. <el-table-column align='center'
  67. prop="id"
  68. label="员工编号">
  69. </el-table-column>
  70. <el-table-column align='center'
  71. prop="realName"
  72. label="姓名">
  73. </el-table-column>
  74. <el-table-column align='center'
  75. prop="phone"
  76. label="手机号">
  77. </el-table-column>
  78. <el-table-column align='center'
  79. label="角色分类">
  80. <template slot-scope="scope">
  81. <span style="max-height: 68px;display: block;"
  82. :title="scope.row.roleNames | joinArray(',')">{{ scope.row.roleNames | joinArray(',') }}</span>
  83. </template>
  84. </el-table-column>
  85. <el-table-column align='center'
  86. prop="jobNature"
  87. label="工作类型">
  88. <template slot-scope="scope">
  89. {{ scope.row.jobNature | jobNature }}
  90. </template>
  91. </el-table-column>
  92. <el-table-column align='center'
  93. label="所属部门">
  94. <span style="display: inline-block;width: 100%;overflow: hidden;white-space: nowrap; text-overflow: ellipsis;"
  95. slot-scope="scope">
  96. <el-popover placement="top-start"
  97. width="200"
  98. trigger="hover"
  99. :content="scope.row.organNameList | joinArray(',')">
  100. <span slot="reference">{{ scope.row.organNameList | joinArray(',') }}</span>
  101. </el-popover>
  102. </span>
  103. </el-table-column>
  104. <el-table-column align='center'
  105. label="状态"
  106. :formatter="formatLockFlag">
  107. </el-table-column>
  108. <el-table-column align='center'
  109. label="入职时间">
  110. <template slot-scope="scope">
  111. {{ scope.row.entryDate | formatTimer }}
  112. </template>
  113. </el-table-column>
  114. <el-table-column align='center'
  115. label="离职时间">
  116. <template slot-scope="scope">
  117. {{ scope.row.demissionDate | formatTimer }}
  118. </template>
  119. </el-table-column>
  120. <el-table-column align='center'
  121. width="250px"
  122. label="操作">
  123. <template slot-scope="scope">
  124. <el-button @click="roleOperation('update', scope.row)"
  125. v-permission="'employee/update'"
  126. type="text">修改</el-button>
  127. <el-button @click="onStaffOperation('RESET_PASSWORD', scope.row)"
  128. v-permission="'employee/employeeOperate'"
  129. type="text">重置密码</el-button>
  130. <el-button @click="onStaffOperation('LOCK_UNLOCK', scope.row)"
  131. v-permission="'employee/employeeOperate'"
  132. type="text">{{ scope.row.lockFlag == 1 ? '解冻' : '冻结' }}</el-button>
  133. <el-button @click="onStaffOperation('DEMISSION', scope.row)"
  134. v-permission="'employee/employeeOperate'"
  135. type="text">{{ scope.row.demissionDate ? '复职' : '离职' }}</el-button>
  136. </template>
  137. </el-table-column>
  138. </el-table>
  139. <pagination :total="pageInfo.total"
  140. :page.sync="pageInfo.page"
  141. :limit.sync="pageInfo.limit"
  142. :page-sizes="pageInfo.page_size"
  143. @pagination="getList" />
  144. </div>
  145. </div>
  146. <el-dialog :title="formTitle[formActionTitle]"
  147. :visible.sync="roleStatus"
  148. @close="onFormClose('ruleForm')"
  149. width="500px">
  150. <el-form :model="form"
  151. :rules="rules"
  152. ref="ruleForm">
  153. <el-form-item label="姓名"
  154. prop="realName"
  155. :label-width="formLabelWidth">
  156. <el-input v-model.trim="form.realName"
  157. autocomplete="off"></el-input>
  158. </el-form-item>
  159. <el-form-item label="性别"
  160. prop="gender"
  161. :label-width="formLabelWidth">
  162. <el-select v-model.trim="form.gender"
  163. clearable
  164. filterable>
  165. <el-option label="男"
  166. :value="1"></el-option>
  167. <el-option label="女"
  168. :value="0"></el-option>
  169. </el-select>
  170. </el-form-item>
  171. <el-form-item label="手机号"
  172. prop="phone"
  173. :label-width="formLabelWidth">
  174. <el-input v-model.trim.number="form.phone"
  175. autocomplete="off"></el-input>
  176. </el-form-item>
  177. <el-form-item label="角色分类"
  178. prop="roleIds"
  179. :label-width="formLabelWidth">
  180. <el-select v-model.trim="form.roleIds"
  181. clearable
  182. filterable
  183. multiple>
  184. <el-option v-for="item in roleList"
  185. :key="item.value"
  186. :label="item.label"
  187. :value="item.value"></el-option>
  188. </el-select>
  189. <!-- collapse-tags -->
  190. </el-form-item>
  191. <el-form-item label="所属部门"
  192. prop="organIdLists"
  193. :label-width="formLabelWidth">
  194. <el-select style="width: calc(100% - 75px) !important;"
  195. filterable
  196. clearable
  197. v-model.trim="form.organIdLists"
  198. multiple>
  199. <el-option v-for="item in branchList"
  200. :key="item.value"
  201. :label="item.label"
  202. :value="item.value"></el-option>
  203. </el-select>
  204. <el-button @click="onBranchCheckAll">全选</el-button>
  205. </el-form-item>
  206. <el-form-item label="工作类型"
  207. prop="jobNature"
  208. :label-width="formLabelWidth">
  209. <el-select v-model.trim="form.jobNature"
  210. clearable
  211. filterable>
  212. <el-option label="全职"
  213. value="FULL_TIME"></el-option>
  214. <el-option label="兼职"
  215. value="PART_TIME"></el-option>
  216. <el-option label="临时"
  217. value="TEMPORARY"></el-option>
  218. </el-select>
  219. </el-form-item>
  220. <el-form-item label="入职时间"
  221. prop="entryDate"
  222. :label-width="formLabelWidth">
  223. <el-date-picker v-model.trim="form.entryDate"
  224. type="date"
  225. :picker-options="{
  226. firstDayOfWeek:1
  227. }"
  228. value-format="yyyy-MM-dd HH:mm:ss"
  229. placeholder="选择日期">
  230. </el-date-picker>
  231. </el-form-item>
  232. <el-form-item label="通讯地址"
  233. prop="contactAddress"
  234. :label-width="formLabelWidth">
  235. <el-input v-model.trim="form.contactAddress"
  236. autocomplete="off"></el-input>
  237. </el-form-item>
  238. <el-form-item label="邮政编码"
  239. prop="postalCode"
  240. :label-width="formLabelWidth">
  241. <el-input v-model.trim="form.postalCode"
  242. autocomplete="off"></el-input>
  243. </el-form-item>
  244. </el-form>
  245. <span slot="footer"
  246. class="dialog-footer">
  247. <el-button @click="roleStatus = false">取 消</el-button>
  248. <el-button @click="onRoleSubmit('ruleForm')"
  249. type="primary">确 定</el-button>
  250. </span>
  251. </el-dialog>
  252. <el-dialog title="教务交接"
  253. width="400px"
  254. destroy-on-close
  255. close-on-click-modal
  256. :visible.sync="educationViseble">
  257. <el-form :model="educationForm"
  258. :inline="true"
  259. ref="educationForm">
  260. <el-form-item label="教务老师"
  261. :rules="[{
  262. required:
  263. true,
  264. message: '请选择教务老师'
  265. ,
  266. trigger: 'blur'
  267. }]">
  268. <el-select v-model.trim="
  269. educationForm.targetUserId"
  270. clearable
  271. filterable>
  272. <el-option v-for="item in educationList"
  273. :key="item.userId"
  274. :label="item.userName"
  275. :value="item.userId"></el-option>
  276. </el-select>
  277. </el-form-item>
  278. </el-form>
  279. <span slot="footer"
  280. class="dialog-footer">
  281. <el-button @click="educationViseble = false">取 消</el-button>
  282. <el-button @click="submitEducation"
  283. type="primary">确 定</el-button>
  284. </span>
  285. </el-dialog>
  286. </div>
  287. </template>
  288. <script>
  289. import pagination from '@/components/Pagination/index'
  290. import { queryEmployByOrganId, employeeOperate, getUserRole, employeeAdd, employeeUpdate, hasCourseGroupRelation, updateEducationTeacherId } from '@/api/systemManage'
  291. import { branchQueryPage, findEducationTeacher } from '@/api/specialSetting'
  292. import { findEducationUsers } from '@/api/buildTeam'
  293. import store from '@/store'
  294. import { isvalidPhone } from '@/utils/validate'
  295. let validPhone = (rule, value, callback) => {
  296. if (!value) {
  297. callback(new Error('请输入电话号码'))
  298. } else if (!isvalidPhone(value)) {
  299. callback(new Error('请输入正确的11位手机号码'))
  300. } else {
  301. callback()
  302. }
  303. }
  304. export default {
  305. name: 'staffManager',
  306. components: { pagination },
  307. data () {
  308. return {
  309. tableList: [],
  310. educationList: [],
  311. educationForm: {
  312. targetUserId: ''
  313. },
  314. educationViseble: false,
  315. activeRow: null,
  316. pageInfo: {
  317. // 分页规则
  318. limit: 10, // 限制显示条数
  319. page: 1, // 当前页
  320. total: 0, // 总条数
  321. page_size: [10, 20, 40, 50] // 选择限制显示条数
  322. },
  323. roleStatus: false,
  324. formActionTitle: 'create',
  325. roleList: [], // 角色列表
  326. branchList: [], // 分部列表
  327. formTitle: {
  328. create: '添加员工',
  329. update: '修改员工'
  330. },
  331. formLabelWidth: '100px',
  332. form: {
  333. realName: null,
  334. gender: null,
  335. phone: null,
  336. roleIds: [],
  337. organIdLists: [],
  338. jobNature: null,
  339. entryDate: null,
  340. contactAddress: null,
  341. postalCode: null
  342. },
  343. rules: {
  344. realName: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
  345. gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
  346. phone: [{ type: 'number', required: true, validator: validPhone, trigger: 'blur' }, { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }],
  347. roleIds: [{ type: 'array', required: true, message: '请选择分类', trigger: 'change' }],
  348. organIdLists: [{ type: 'array', required: true, message: '请选择所属部门', trigger: 'change' }],
  349. jobNature: [{ required: true, message: '请选择工作类型', trigger: 'change' }],
  350. entryDate: [{ required: true, message: '请选择入职时间', trigger: 'blur' }],
  351. },
  352. searchForm: {
  353. search: null,
  354. jobNature: null,
  355. organId: null,
  356. roleId: null
  357. }
  358. }
  359. },
  360. mounted () {
  361. this.getList()
  362. this.getRoleList()
  363. },
  364. activated () {
  365. this.getList()
  366. this.getRoleList()
  367. },
  368. methods: {
  369. onBranchCheckAll () {
  370. this.form.organIdLists = []
  371. this.branchList.forEach(item => {
  372. this.form.organIdLists.push(item.value)
  373. })
  374. },
  375. onRoleSubmit (formName) {
  376. this.$refs[formName].validate((valid) => {
  377. if (valid) {
  378. this.form.organIdList = this.form.organIdLists.join(',')
  379. if (this.formActionTitle == 'create') {
  380. if (this.form.id) { // 判断有没有Id,如果有则删除
  381. delete this.form.id
  382. }
  383. employeeAdd(this.form).then(res => {
  384. this.messageTips('添加', res)
  385. })
  386. } else if (this.formActionTitle == 'update') {
  387. employeeUpdate(this.form).then(res => {
  388. this.messageTips('修改', res)
  389. })
  390. }
  391. } else {
  392. return
  393. }
  394. })
  395. },
  396. messageTips (title, res) {
  397. if (res.code == 200) {
  398. this.$message.success(title + '成功')
  399. this.roleStatus = false
  400. this.getList()
  401. } else {
  402. this.$message.error(res.msg)
  403. }
  404. },
  405. search () {
  406. this.pageInfo.page = 1
  407. this.getList()
  408. },
  409. getList () {
  410. let searchForm = this.searchForm
  411. let params = {
  412. search: searchForm.search ? searchForm.search : null,
  413. jobNature: searchForm.jobNature ? searchForm.jobNature : null,
  414. organId: searchForm.organId ? searchForm.organId : null,
  415. roleId: searchForm.roleId ? searchForm.roleId : null,
  416. rows: this.pageInfo.limit,
  417. page: this.pageInfo.page
  418. }
  419. queryEmployByOrganId(params).then(res => {
  420. if (res.code == 200 && res.data) {
  421. this.tableList = res.data.rows
  422. this.pageInfo.total = res.data.total
  423. }
  424. })
  425. },
  426. getRoleList () { // 获取角色
  427. getUserRole({ delFlag: 0, rows: 9999 }).then(res => {
  428. let result = res.data
  429. if (res.code == 200 && result && result.rows.length > 0) {
  430. this.roleList = []
  431. result.rows.forEach(item => {
  432. this.roleList.push({
  433. label: item.roleName,
  434. value: item.id
  435. })
  436. })
  437. }
  438. })
  439. branchQueryPage({ // 获取分部
  440. delFlag: 0,
  441. rows: 9999
  442. }).then(res => {
  443. if (res.code == 200 && res.data && res.data.rows) {
  444. this.branchList = []
  445. res.data.rows.forEach(item => {
  446. this.branchList.push({
  447. label: item.name,
  448. value: item.id
  449. })
  450. })
  451. }
  452. })
  453. },
  454. roleOperation (type, data) {
  455. this.formActionTitle = type
  456. this.roleStatus = true
  457. // 修改的时候
  458. if (type == 'update') {
  459. this.form = {
  460. id: data.id,
  461. realName: data.realName,
  462. gender: data.gender,
  463. phone: Number(data.phone),
  464. roleIds: data.roleIds,
  465. organIdLists: data.organIdList ? data.organIdList : [],
  466. jobNature: data.jobNature,
  467. entryDate: data.entryDate,
  468. contactAddress: data.contactAddress,
  469. postalCode: data.postalCode
  470. }
  471. }
  472. },
  473. onFormClose (formName) { // 关闭弹窗重置验证
  474. this.form = {
  475. realName: null,
  476. gender: null,
  477. phone: null,
  478. roleName: null,
  479. organIdLists: [],
  480. jobNature: null,
  481. entryDate: null
  482. }
  483. this.$refs[formName].resetFields()
  484. },
  485. formatLockFlag (row) {
  486. let reuslt = ['正常', '冻结']
  487. if (row.demissionDate) {
  488. return '离职'
  489. } else {
  490. return reuslt[row.lockFlag]
  491. }
  492. },
  493. async checkStatus (data) {
  494. let status;
  495. await hasCourseGroupRelation({ employeeId: data.id }).then(async res => {
  496. if (res.code === 200) {
  497. if (res.data.hasCourseSchedule) {
  498. this.$message.error('请先交接指导老师课程')
  499. status = false
  500. } else {
  501. if (res.data.hasCourseGroupRelation) {
  502. let userId = data.id
  503. await findEducationTeacher({ userId }).then(res => {
  504. if (res.code === 200) {
  505. this.educationList = res.data;
  506. this.educationViseble = true
  507. status = false
  508. }
  509. })
  510. } else {
  511. // 1 要弹出
  512. status = true
  513. }
  514. }
  515. }
  516. })
  517. return status
  518. },
  519. onStaffOperation (type, data) {
  520. const tempStatus = type == 'RESET_PASSWORD' ? true : false
  521. this.$confirm(`您确定${tempStatus ? '重置密码' : '修改员工状态'}?`, "提示", {
  522. confirmButtonText: "确定",
  523. cancelButtonText: "取消",
  524. type: "warning"
  525. }).then(async () => {
  526. if (type === 'DEMISSION' && !data.demissionDate) {
  527. this.activeRow = data;
  528. // 1.点击的是离职按钮
  529. // 2.判断该考级是否存在教务老师
  530. const status = await this.checkStatus(data)
  531. if (!status) {
  532. return
  533. }
  534. }
  535. employeeOperate({
  536. employeeId: data.id,
  537. operate: type
  538. }).then(res => {
  539. if (res.code == 200) {
  540. this.$message.success(tempStatus ? '重置密码成功' : '更改成功')
  541. this.roleStatus = false
  542. this.getList()
  543. } else {
  544. this.$message.error(res.msg)
  545. }
  546. })
  547. }).catch(err => { })
  548. },
  549. submitEducation () {
  550. // 发请求 提交信息
  551. updateEducationTeacherId({ currentUserId: this.activeRow.id, targetUserId: this.educationForm.targetUserId }).then(res => {
  552. if (res.code === 200) {
  553. const type = 'DEMISSION'
  554. const data = this.activeRow;
  555. employeeOperate({
  556. employeeId: data.id,
  557. operate: type
  558. }).then(res => {
  559. if (res.code == 200) {
  560. this.$message.success('更改成功')
  561. this.roleStatus = false
  562. this.educationViseble = false
  563. this.getList()
  564. } else {
  565. this.$message.error(res.msg)
  566. }
  567. })
  568. }
  569. })
  570. },
  571. },
  572. watch: {
  573. educationViseble (val) {
  574. if (!val) {
  575. this.educationForm.targetUserId = ''
  576. this.$refs['educationForm'].resetFields()
  577. }
  578. }
  579. }
  580. }
  581. </script>
  582. <style lang="scss" scoped>
  583. /deep/.el-button--primary {
  584. background: #14928a;
  585. border-color: #14928a;
  586. color: #fff;
  587. &:hover,
  588. &:active,
  589. &:focus {
  590. background: #14928a;
  591. border-color: #14928a;
  592. color: #fff;
  593. }
  594. }
  595. /deep/.el-dialog__body {
  596. padding: 0 20px;
  597. }
  598. /deep/.el-select,
  599. /deep/.el-date-editor.el-input {
  600. width: 100% !important;
  601. }
  602. </style>