staffManager.vue 22 KB

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