index.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. <?php
  2. use common\helpers\ComponentHelper;
  3. ComponentHelper::loadComponentView("select-user", __DIR__);
  4. ?>
  5. <div id="app" v-cloak>
  6. <el-card shadow="never" style="border:0" body-style="background-color: #f3f3f3;padding: 10px 0 0;">
  7. <div slot="header">
  8. <span>部门列表</span>
  9. <div style="float: right;margin-top: -5px">
  10. <el-button type="primary" @click="handle('editDepartment')" size="small">添加部门</el-button>
  11. </div>
  12. </div>
  13. <div class="table-body">
  14. <el-table :data="list" border v-loading="loading" size="small" style="margin-bottom: 15px;">
  15. <el-table-column prop="id" min-width="80" label="部门ID" align="center"></el-table-column>
  16. <el-table-column label="名称" align="center" min-width="200">
  17. <template slot-scope="scope">
  18. <el-popover
  19. placement="bottom"
  20. width="300"
  21. @show="handle('popPosition', scope.row)"
  22. >
  23. <div>
  24. <el-table
  25. :data="scope.row.departmentPosition"
  26. size="small"
  27. v-loading="positionLoading"
  28. >
  29. <el-table-column prop="scope.row.departmentPosition.name" label="职位" align="center">
  30. <template slot-scope="position">
  31. {{position.row.name}}
  32. </template>
  33. </el-table-column>
  34. <el-table-column prop="scope.row.departmentPosition.is_default_position" label="默认职位" align="center">
  35. <template slot-scope="position">
  36. <el-switch @change="(val) => changeIsDefaultPosition(position.row.id, val)" v-model="position.row.is_default_position" :active-value="1" :inactive-value="0" class="input-with-select">
  37. </el-switch>
  38. </template>
  39. </el-table-column>
  40. <el-table-column
  41. prop="address"
  42. align="center"
  43. label="操作">
  44. <template slot-scope="position">
  45. <el-button type="text" size="mini" circle style="margin-left: 10px;margin-top: 10px"
  46. @click.native="handle('editPosition', position.row, scope.row, scope.$index, position.$index)">
  47. 编辑
  48. </el-button>
  49. </template>
  50. </el-table-column>
  51. </el-table>
  52. </div>
  53. <div style="text-align: right; margin: 0">
  54. <!-- <el-button size="mini" type="text" @click="visible = false">取消</el-button>
  55. <el-button type="primary" size="mini" @click="visible = false">确定</el-button> -->
  56. </div>
  57. <!-- <el-button slot="reference">删除</el-button> -->
  58. <el-button slot="reference">
  59. <span>{{scope.row.name}}</span>
  60. <i class="el-icon-arrow-down"></i>
  61. </el-button>
  62. </el-popover>
  63. <!-- <span>{{scope.row.name}}</span>
  64. <i class="el-icon-arrow-right"></i> -->
  65. </template>
  66. </el-table-column>
  67. <el-table-column label="排序" min-width="150" prop="sort" align="center"></el-table-column>
  68. <el-table-column label="时间" min-width="200" align="center">
  69. <template slot-scope="scope">
  70. <div>{{scope.row.created_at|dateTimeFormat('Y-m-d H:i:s')}}</div>
  71. </template>
  72. </el-table-column>
  73. <el-table-column label="操作" min-width="300" align="center">
  74. <template slot-scope="scope">
  75. <el-button type="text" size="mini" circle style="margin-top: 10px" @click="$navigate({r: 'business-card/department/member', department_id: scope.row.id})">查看部门人员</el-button>
  76. <el-button type="text" size="mini" circle style="margin-left: 10px;margin-top: 10px" @click.native="handle('editDepartment', scope.row)">编辑</el-button>
  77. <el-button type="text" size="mini" circle style="margin-left: 10px;margin-top: 10px">
  78. <template>
  79. <select-user :department_id="scope.row.id"
  80. :position_list="scope.row.departmentPosition"
  81. :department_name="scope.row.name"
  82. :multiple="false"
  83. @selected="send('userSelect', $event,scope.row.id)"
  84. title="新增部门成员">新增部门成员
  85. </select-user>
  86. </template>
  87. </el-button>
  88. <el-button type="text" size="mini" circle style="margin-left: 10px;margin-top: 10px" @click.native="handle('addPosition', scope.row, scope.$index)">增加职位</el-button>
  89. <el-button type="text" size="mini" circle style="margin-left: 10px;margin-top: 10px" @click.native="del(scope.row.id)">删除</el-button>
  90. </template>
  91. </el-table-column>
  92. </el-table>
  93. <div flex="box:last cross:center">
  94. <div></div>
  95. <div>
  96. <el-pagination v-if="pagination" :page-size="pagination.defaultPageSize"
  97. style="display: inline-block;float: right;" background @current-change="handle('pageChange', $event)"
  98. layout="prev, pager, next" :total="pagination.totalCount">
  99. </el-pagination>
  100. </div>
  101. </div>
  102. </div>
  103. </el-card>
  104. <el-dialog
  105. title="编辑职位"
  106. :visible.sync="editPositionLoading"
  107. width="30%"
  108. >
  109. <el-form>
  110. <el-form-item label="职位" label-width="150px">
  111. <el-input style="width:70%;" v-model="positionInfo.name"></el-input>
  112. </el-form-item>
  113. <el-form-item label="默认职位" label-width="150px">
  114. <el-switch v-model="positionInfo.is_default_position" :active-value="1" :inactive-value="0" class="input-with-select">
  115. </el-switch>
  116. </el-form-item>
  117. </el-form>
  118. <span slot="footer" class="dialog-footer">
  119. <el-button @click="editPositionLoading = false">取 消</el-button>
  120. <el-button type="primary" @click="send('editPosition')" v-loading="postPosition">确 定</el-button>
  121. </span>
  122. </el-dialog>
  123. <el-dialog
  124. title="编辑部门"
  125. :visible.sync="addDepartmentLoading"
  126. width="30%"
  127. >
  128. <el-form>
  129. <el-form-item label="部门" label-width="150px">
  130. <el-input style="width:70%;" v-model="departmentInfo.name"></el-input>
  131. </el-form-item>
  132. <el-form-item label="职位" label-width="150px">
  133. <div class="position_content">
  134. <div class="position_item" v-for="(item,index) in departmentInfo.position" :key="index">
  135. <el-input style="width:70%;" v-model.trim="item.name"></el-input>
  136. <el-button type="danger" circlesize="small" @click="delDepartmentPosition(item, index)" v-if="item.id==null">-</el-button>
  137. </div>
  138. <el-button type="primary" size="small" @click="addDepartmentPosition">+</el-button>
  139. </div>
  140. </el-form-item>
  141. <el-form-item label="排序" label-width="150px">
  142. <el-input style="width:70%;" onkeyup="value=value.replace(/[^\d]/g,'')" v-model="departmentInfo.sort"></el-input>
  143. </el-form-item>
  144. </el-form>
  145. <span slot="footer" class="dialog-footer">
  146. <el-button @click="addDepartmentLoading = false">取 消</el-button>
  147. <el-button type="primary" @click="send('editDepartment')" v-loading="postPosition">确 定</el-button>
  148. </span>
  149. </el-dialog>
  150. <el-dialog title="新增职位" :visible.sync="addPositionLoading" width="40%">
  151. <el-form label-width="80px" ref="positionForm">
  152. <el-form-item label="部门" prop="department_name">
  153. <div>{{positionForm.department_name}}</div>
  154. </el-form-item>
  155. <el-form-item label="职位" prop="name">
  156. <el-input style="width: 30%;" placeholder="输入职位名" v-model="positionForm.name" class="input-with-select">
  157. </el-input>
  158. </el-form-item>
  159. <el-form-item label="默认职位" prop="is_default_position">
  160. <el-switch v-model="positionForm.is_default_position" :active-value="1" :inactive-value="0" class="input-with-select">
  161. </el-switch>
  162. </el-form-item>
  163. </el-form>
  164. <div slot="footer" class="dialog-footer">
  165. <el-button :loading="postPosition" type="primary" @click="send('addPosition')">保存</el-button>
  166. </div>
  167. </el-dialog>
  168. </div>
  169. <script>
  170. const app = new Vue({
  171. el: '#app',
  172. data: {
  173. list: [],
  174. positionInfo: {name: "", id: 0, parent_id: 0, is_default_position: 0},
  175. positionForm: {department_name: "", name: "", parent_id: 0, is_default_position: 0},
  176. departmentInfo: {name: "", sort: 99, id: 0, position: []},
  177. page: 1,
  178. pagination: null,
  179. loading: false,
  180. positionLoading: false,//查看部门对应职位
  181. editPositionLoading: false,//修改职位弹窗
  182. addPositionLoading: false,//新增职位弹窗
  183. postPosition: false,//提交职位,提交部门
  184. addDepartmentLoading: false,//添加,编辑部门弹窗
  185. listIndex: 0,//部门列表索引
  186. positionIndex: 0//职位列表索引
  187. },
  188. mounted() {
  189. this.send('getData');
  190. },
  191. methods: {
  192. send(type, param1 = null, param2 = null, param3 = null) {
  193. switch(type) {
  194. //获取数据
  195. case 'getData':
  196. this.loading = true;
  197. request({
  198. params: {r: 'business-card/department/index', page: this.page},
  199. }).then(e=>{
  200. if (e.data.code == 0) {
  201. this.list = e.data.data.list;
  202. this.pagination = e.data.data.pagination;
  203. } else {
  204. this.$message.error(e.data.msg);
  205. }
  206. this.loading = false;
  207. }).catch(e=>{
  208. this.loading = false;
  209. this.$message.error(e.data.msg);
  210. })
  211. break;
  212. //编辑职位
  213. case 'editPosition':
  214. this.postPosition = true;
  215. this.loading = true;
  216. request({
  217. params: {r: 'business-card/department/edit-position'},
  218. data: this.positionInfo,
  219. method: 'post',
  220. }).then(e=>{
  221. if (e.data.code == 0) {
  222. this.$message.success(e.data.msg);
  223. this.send('getData');
  224. } else {
  225. this.$message.error(e.data.msg);
  226. }
  227. this.list[this.listIndex]['departmentPosition'][this.positionIndex]['name'] = this.positionInfo.name;
  228. this.loading = false;
  229. this.postPosition = false;
  230. this.editPositionLoading = false;
  231. }).catch(e=>{
  232. this.$message.error(e.data.msg);
  233. this.loading = false;
  234. this.postPosition = false;
  235. this.editPositionLoading = false;
  236. })
  237. break;
  238. //编辑部门
  239. case 'editDepartment':
  240. let first_name = this.departmentInfo.position[0].name;
  241. if(first_name === '' || first_name === undefined || first_name === null) {
  242. return this.$message.error("部门职位必须填写一个!");
  243. }
  244. request({
  245. params: {r: 'business-card/department/edit-department'},
  246. data: this.departmentInfo,
  247. method: 'post',
  248. }).then(e=>{
  249. if (e.data.code == 0) {
  250. this.$message({
  251. type: 'success',
  252. message: e.data.msg,
  253. duration: 2000,
  254. onClose: function () {
  255. window.location.reload();
  256. }
  257. })
  258. } else {
  259. this.$message.error(e.data.msg);
  260. }
  261. //location. reload();
  262. }).catch(e=>{
  263. this.$message.error("操作失败");
  264. })
  265. break;
  266. //新增职位
  267. case 'addPosition':
  268. this.loading = true;
  269. this.postPosition = true;
  270. request({
  271. params: {r: 'business-card/department/edit-position'},
  272. data: this.positionForm,
  273. method: 'post',
  274. }).then(e=>{
  275. if (e.data.code == 0) {
  276. let obj = {id: e.data.data.id, name: this.positionForm.name};
  277. this.list[this.listIndex]['departmentPosition'].push(JSON.parse(JSON.stringify(obj)));
  278. this.send('getData');
  279. this.$message.success(e.data.msg);
  280. } else {
  281. this.$message.error(e.data.msg);
  282. }
  283. this.loading = false;
  284. this.postPosition = false;
  285. this.addPositionLoading = false;
  286. }).catch(e=>{
  287. this.$message.error(e.data.msg);
  288. this.loading = false;
  289. this.postPosition = false;
  290. this.addPositionLoading = false;
  291. });
  292. break;
  293. //部门新增成员
  294. case 'userSelect':
  295. if (!param1.position_id) {
  296. this.$message.error('请选择职位');
  297. return false;
  298. }
  299. if (!param1.role_type) {
  300. this.$message.error('请选择角色');
  301. return false;
  302. }
  303. if (param1.user_ids.length == 0) {
  304. this.$message.error('请选择用户');
  305. return false;
  306. }
  307. param1.department_id = param2;
  308. this.loading = true;
  309. request({
  310. params: {r: 'business-card/department/edit-department-member'},
  311. data: param1,
  312. method: 'post'
  313. }).then(e=>{
  314. if (e.data.code == 0) {
  315. this.$message.success(e.data.msg);
  316. } else {
  317. this.$message.error("操作失败");
  318. }
  319. this.loading = false;
  320. }).catch(e=>{
  321. this.$message.error(e.data.msg);
  322. this.loading = false;
  323. })
  324. break;
  325. }
  326. },
  327. handle(type, param1 = null, param2 = null, param3 = null, param4 = null) {
  328. switch (type) {
  329. //点击编辑职位
  330. case 'editPosition':
  331. this.editPositionLoading = true;
  332. let positionInfo = {name: param1.name, id: param1.id, parent_id: param2.id, is_default_position: param1.is_default_position};
  333. this.positionInfo = positionInfo;
  334. this.listIndex = param3;
  335. this.positionIndex = param4;
  336. break;
  337. //新增,编辑部门弹窗
  338. case 'editDepartment':
  339. this.addDepartmentLoading = true;
  340. if (param1 != null) {
  341. this.addDepartmentLoading = true;
  342. this.departmentInfo.name = param1.name;
  343. this.departmentInfo.id = param1.id;
  344. this.departmentInfo.sort = param1.sort;
  345. let position_list = [];
  346. param1.departmentPosition.forEach(function (item, index) {
  347. position_list.push({name: item.name, id: item.id})
  348. })
  349. this.departmentInfo.position = position_list;
  350. }else{
  351. this.departmentInfo.name = '';
  352. this.departmentInfo.id = '';
  353. this.departmentInfo.sort = '99';
  354. this.departmentInfo.position = [{name: null, id: null}];
  355. }
  356. break;
  357. //新增职位弹窗
  358. case 'addPosition':
  359. this.addPositionLoading = true;
  360. this.positionForm.department_name = param1.name;
  361. this.positionForm.parent_id = param1.id;
  362. this.positionForm.name = '';
  363. this.listIndex = param2;
  364. break;
  365. case 'pageChange':
  366. this.page = param1;
  367. this.send('getData');
  368. break;
  369. }
  370. },
  371. del(id) {
  372. request({
  373. params: {r: 'business-card/department/del'},
  374. data: {
  375. "id":id
  376. },
  377. method: 'post',
  378. }).then(e=>{
  379. if (e.data.code == 0) {
  380. this.$message.success(e.data.msg);
  381. this.send('getData');
  382. } else {
  383. this.$message.error(e.data.msg);
  384. }
  385. // location. reload();
  386. }).catch(e=>{
  387. this.$message.error("操作失败");
  388. })
  389. },
  390. userSelect(param) {
  391. },
  392. addDepartmentPosition() {// 添加部门职位
  393. this.departmentInfo.position.push({name: null, id: null});
  394. },
  395. delDepartmentPosition(item, index) {// 删除部门职位
  396. if(this.departmentInfo.position.length <=1 ) return false;
  397. this.departmentInfo.position.splice(index, 1);
  398. },
  399. changeIsDefaultPosition(id, is_default_position) {
  400. request({
  401. params: {r: 'business-card/department/change-is-default-position'},
  402. data: {
  403. id,
  404. is_default_position
  405. },
  406. method: 'post',
  407. }).then(e=>{
  408. if (e.data.code == 0) {
  409. this.$message.success(e.data.msg);
  410. this.send('getData');
  411. } else {
  412. this.$message.error(e.data.msg);
  413. }
  414. }).catch(e=>{
  415. this.$message.error("操作失败");
  416. })
  417. }
  418. }
  419. })
  420. </script>
  421. <style>
  422. .el-tabs__header {
  423. font-size: 16px;
  424. }
  425. .table-body {
  426. padding: 20px;
  427. background-color: #fff;
  428. }
  429. .table-body .el-button {
  430. padding: 0 !important;
  431. border: 0;
  432. margin: 0 5px;
  433. }
  434. .input-item {
  435. width: 250px;
  436. margin: 0 0 20px;
  437. display: inline-block;
  438. }
  439. .input-item .el-input__inner {
  440. border-right: 0;
  441. }
  442. .input-item .el-input__inner:hover {
  443. border: 1px solid #dcdfe6;
  444. border-right: 0;
  445. outline: 0;
  446. }
  447. .input-item .el-input__inner:focus {
  448. border: 1px solid #dcdfe6;
  449. border-right: 0;
  450. outline: 0;
  451. }
  452. .input-item .el-input-group__append {
  453. background-color: #fff;
  454. border-left: 0;
  455. width: 10%;
  456. padding: 0;
  457. }
  458. .input-item .el-input-group__append .el-button {
  459. padding: 0;
  460. }
  461. .input-item .el-input-group__append .el-button {
  462. margin: 0;
  463. }
  464. .batch {
  465. margin: 0 0 20px;
  466. display: inline-block;
  467. }
  468. .batch .el-button {
  469. padding: 9px 15px !important;
  470. }
  471. .el-table th>.cell{
  472. color: #333;
  473. font-weight: bold;
  474. font-size: 14px;
  475. }
  476. .el-table__footer-wrapper, .el-table__header-wrapper{
  477. /*border-bottom: 1.4px solid #D6D6D6;*/
  478. }
  479. .el-table .warning-row {
  480. background: #F5F7FC;
  481. }
  482. .el-table .success-row {
  483. background: #ffffff;
  484. }
  485. .position_content .position_item{
  486. margin: 5px 0;
  487. }
  488. .position_content .position_item .el-button{
  489. margin-left: 5px;
  490. }
  491. </style>