index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. <template>
  2. <d2-container>
  3. <template slot="header"
  4. style="padding: 5px;">
  5. <el-form :model="dutyDetail">
  6. <el-row>
  7. <el-col :span="10">
  8. <el-form-item label="标题"
  9. label-width="120px">
  10. {{dutyDetail.Title}}
  11. </el-form-item>
  12. </el-col>
  13. </el-row>
  14. <el-row>
  15. <el-col :span="10">
  16. <el-form-item label="学年"
  17. label-width="120px">
  18. {{dutyDetail.Year}}年
  19. </el-form-item>
  20. </el-col>
  21. </el-row>
  22. <el-row>
  23. <el-col :span="10">
  24. <el-form-item label="学期"
  25. label-width="120px">
  26. {{this.termName}}
  27. </el-form-item>
  28. </el-col>
  29. </el-row>
  30. <el-row>
  31. <el-form-item label="地点"
  32. size="mini"
  33. label-width="120px">
  34. <el-checkbox-group v-model="selectLocal">
  35. <el-checkbox-button v-for="item in LocalList"
  36. :label="item.ItemValue"
  37. :key="item.ItemValue"
  38. style="float:left">{{item.ItemName}}</el-checkbox-button>
  39. </el-checkbox-group>
  40. </el-form-item>
  41. </el-row>
  42. <el-row>
  43. <el-form-item label="值班时间"
  44. size="mini"
  45. label-width="120px">
  46. <el-checkbox-group v-model="selectTime">
  47. <el-checkbox-button v-for="item in TimeList"
  48. :label="item.ItemValue"
  49. :key="item.ItemValue"
  50. style="float:left">{{item.ItemName}}</el-checkbox-button>
  51. </el-checkbox-group>
  52. </el-form-item>
  53. </el-row>
  54. <el-row>
  55. <el-form-item label="值班人员"
  56. size="mini"
  57. label-width="120px">
  58. <el-button @click="personClick(item.Id)"
  59. v-for="item in PeopleList"
  60. :key="item.Id"
  61. :label="item.Id"
  62. style="float:left">{{item.PersonnelName}}</el-button>
  63. </el-form-item>
  64. </el-row>
  65. <el-row :gutter="24">
  66. <el-col :span="16">
  67. &nbsp;
  68. </el-col>
  69. <el-col :span="2">
  70. <el-button size="mini"
  71. @click="addList()"
  72. type="success">生成值班表</el-button>
  73. </el-col>
  74. <el-col :span="2">
  75. <el-button size="mini"
  76. type="primary"
  77. @click="addDuytDetail()">保存值班表</el-button>
  78. </el-col>
  79. <el-col :span="2">
  80. <el-button size="mini"
  81. type="warning"
  82. @click="exportExcel()">导出</el-button>
  83. </el-col>
  84. <el-col :span="1">
  85. <el-button size="mini"
  86. type="danger"
  87. Updated
  88. upstream
  89. @click="back()">关闭</el-button>
  90. </el-col>
  91. </el-row>
  92. </el-form>
  93. </template>
  94. <el-table :data="list"
  95. border
  96. fit
  97. tooltip-effect="dark"
  98. style="width: 100%"
  99. height="100%"
  100. @cell-click="cellclick"
  101. @header-click="headclick"
  102. :cell-class-name="cellBg"
  103. :key="refresh"
  104. id="out-table">
  105. <el-table-column fit
  106. prop="Local"
  107. min-width="160px"
  108. label="地点"
  109. align="center"
  110. show-overflow-tooltip
  111. :formatter="formatLocal"></el-table-column>
  112. <el-table-column prop="Time"
  113. label="时间段"
  114. align="center"
  115. min-width="120px"
  116. show-overflow-tooltip
  117. :formatter="formatTime"></el-table-column>
  118. <el-table-column prop="Monday"
  119. label="周一"
  120. align="center"
  121. min-width="120px"
  122. show-overflow-tooltip
  123. :formatter="formatPerson"></el-table-column>
  124. <el-table-column prop="Tuesday"
  125. label="周二"
  126. align="center"
  127. min-width="120px"
  128. show-overflow-tooltip
  129. :formatter="formatPerson"></el-table-column>
  130. <el-table-column prop="Wednesday"
  131. label="周三"
  132. align="center"
  133. min-width="120px"
  134. show-overflow-tooltip
  135. :formatter="formatPerson"></el-table-column>
  136. <el-table-column prop="Thursday"
  137. label="周四"
  138. align="center"
  139. min-width="120px"
  140. show-overflow-tooltip
  141. :formatter="formatPerson"></el-table-column>
  142. <el-table-column prop="Friday"
  143. label="周五"
  144. align="center"
  145. min-width="120px"
  146. show-overflow-tooltip
  147. :formatter="formatPerson"></el-table-column>
  148. <el-table-column prop="Saturday"
  149. label="周六"
  150. align="center"
  151. min-width="120px"
  152. show-overflow-tooltip
  153. :formatter="formatPerson"></el-table-column>
  154. <el-table-column prop="Sunday"
  155. label="周日"
  156. align="center"
  157. min-width="120px"
  158. show-overflow-tooltip
  159. :formatter="formatPerson"></el-table-column>
  160. <el-table-column label="操作"
  161. width="80px"
  162. align="center">
  163. <template slot-scope="scope">
  164. <el-button size="mini"
  165. type="danger"
  166. title="删除"
  167. @click="deleteRow(scope.$index,list)"
  168. style="margin-left:3px;"
  169. icon="el-icon-delete"
  170. circle></el-button>
  171. </template>
  172. </el-table-column>
  173. </el-table>
  174. </d2-container>
  175. </template>
  176. <script>
  177. // 总列数
  178. import { mapState, mapActions } from 'vuex'
  179. import DutyApi from '@/api/duty'
  180. import itemDetailApi from '@/api/sysadmin/itemdetail'
  181. import PersonnelApi from '@/api/personnel'
  182. import FileSaver from 'file-saver'
  183. import XLSX from 'xlsx'
  184. const columnNum = 9
  185. // 固定列数
  186. const fixRowHeadNum = 2
  187. // todo 欠优化 列属性对应
  188. const columnProperty = [
  189. 'Local',
  190. 'Time',
  191. 'Monday',
  192. 'Tuesday',
  193. 'Wednesday',
  194. 'Thursday',
  195. 'Friday',
  196. 'Saturday',
  197. 'Sunday'
  198. ]
  199. export default {
  200. name: 'dutyEdit',
  201. data () {
  202. return {
  203. LocalList: [],
  204. PeopleList: [],
  205. TimeList: [],
  206. termList: [],
  207. termName: '',
  208. selectLocal: [],
  209. selectTime: [],
  210. dutyDetail: {
  211. Id: -1,
  212. Year: -1,
  213. Term: -1
  214. },
  215. year: '',
  216. years: [],
  217. dialogvisible: false,
  218. // 刷新标志 刷新表格样式
  219. refresh: 123,
  220. // 已选列表
  221. selectcell: new Map(),
  222. // 数据列表
  223. list: []
  224. }
  225. },
  226. computed: {
  227. ...mapState('d2admin/page', [
  228. 'opened',
  229. 'current' // 用户获取当前页面的地址,用于关闭
  230. ])
  231. },
  232. mounted () {
  233. this.getLocal()
  234. this.getPeople()
  235. this.getDutyTime()
  236. let _this = this
  237. _this.dutyDetail = _this.$route.query.duty
  238. _this.termList = _this.$route.query.term
  239. this.getTerm()
  240. this.getDetailData()
  241. },
  242. methods: {
  243. // 导出excel
  244. exportExcel () {
  245. /* out-table关联导出的dom节点 */
  246. var wb = XLSX.utils.table_to_book(document.querySelector('#out-table'))
  247. /* get binary string as output */
  248. var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' })
  249. try {
  250. FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), '值班表.xlsx')
  251. } catch (e) { if (typeof console !== 'undefined') console.log(e, wbout) }
  252. return wbout
  253. },
  254. // 初始化单选框
  255. selectCheckBox () {
  256. let selectLocal = new Map()
  257. let selectTime = new Map()
  258. for (var i = 0; i < this.list.length; i++) {
  259. if (selectLocal.get(this.list[i].Local + '') !== true) {
  260. this.selectLocal.push(this.list[i].Local + '')
  261. }
  262. if (selectTime.get(this.list[i].Time + '') !== true) {
  263. this.selectTime.push(this.list[i].Time + '')
  264. }
  265. selectLocal.set(this.list[i].Local + '', true)
  266. selectTime.set(this.list[i].Time + '', true)
  267. }
  268. },
  269. // 获取值班子表表格
  270. getDetailData () {
  271. let _this = this
  272. DutyApi.getDetailByDutyId({
  273. DutyId: _this.dutyDetail.Id
  274. }).then(res => {
  275. if (res.length > 0) {
  276. _this.list = res
  277. _this.selectCheckBox()
  278. }
  279. })
  280. },
  281. // 新增表格
  282. addList () {
  283. if (this.selectLocal == 0 && this.selectTime.length == 0) {
  284. return
  285. }
  286. // 清空已选择
  287. this.selectcell = new Map()
  288. let _this = this; let listMap = new Map(); let newList = []
  289. this.list.forEach(row => {
  290. listMap.set(row.Local + '_' + row.Time, row)
  291. })
  292. this.selectLocal.forEach(function (value, key) {
  293. _this.selectTime.forEach(function (valuee, keyy) {
  294. if (listMap.get(value + '_' + valuee)) {
  295. newList.push(listMap.get(value + '_' + valuee))
  296. } else {
  297. newList.push({
  298. DutyId: _this.dutyDetail.Id,
  299. Local: value,
  300. Time: valuee,
  301. Monday: 0,
  302. Tuesday: 0,
  303. Wednesday: 0,
  304. Thursday: 0,
  305. Friday: 0,
  306. Saturday: 0,
  307. Sunday: 0
  308. })
  309. }
  310. })
  311. })
  312. this.list = newList
  313. },
  314. // 保存值班子表信息
  315. addDuytDetail () {
  316. if (this.dutyDetail.Id) {
  317. DutyApi.Saves({ DataList: this.list, DutyId: this.dutyDetail.Id })
  318. .then(res => {
  319. })
  320. .catch(err => {
  321. // handle error
  322. console.error(err)
  323. })
  324. } else {
  325. console.log('error submit!!')
  326. return false
  327. }
  328. },
  329. // 删除一行
  330. deleteRow (index, rows) {
  331. rows.splice(index, 1)
  332. },
  333. // 获取字典表地点
  334. getLocal () {
  335. let _this = this
  336. itemDetailApi.getItemDetailByItemCode({ ItemCode: 'Local' })
  337. .then(res => {
  338. _this.LocalList = res
  339. })
  340. .catch(err => {
  341. console.error(err)
  342. })
  343. },
  344. // 多选框回显
  345. change (index, item) {
  346. },
  347. // 获取字典表值班人员
  348. getPeople () {
  349. let _this = this
  350. PersonnelApi.getAllPersonnel({ current: 1, size: 999 })
  351. .then(res => {
  352. _this.PeopleList = res.records
  353. })
  354. .catch(err => {
  355. console.error(err)
  356. })
  357. },
  358. // 获取字典表课程时间段
  359. getDutyTime () {
  360. let _this = this
  361. itemDetailApi.getItemDetailByItemCode({ ItemCode: 'DutyTime' })
  362. .then(res => {
  363. _this.TimeList = res
  364. })
  365. .catch(err => {
  366. console.error(err)
  367. })
  368. },
  369. // 单元格、行选中
  370. cellclick (row, column, cell, event) {
  371. // 第3列开始可以选中
  372. // 单击单元格选中
  373. // 取消操作行选中
  374. if (cell.cellIndex >= columnNum) {
  375. return
  376. }
  377. if (cell.cellIndex >= fixRowHeadNum) {
  378. if (this.selectcell.get(row.Local + '_' + row.Time + '_' + column.property)) {
  379. this.selectcell.set(row.Local + '_' + row.Time + '_' + column.property, false)
  380. } else {
  381. this.selectcell.set(row.Local + '_' + row.Time + '_' + column.property, this.list[row.index])
  382. }
  383. }
  384. // 第三列之前选中整行
  385. // 行选中
  386. var currentcolumnindex = column.index
  387. if (cell.cellIndex < fixRowHeadNum) {
  388. for (var i = cell.cellIndex; i < columnNum - 1; i++) {
  389. currentcolumnindex = currentcolumnindex + 1
  390. var nextSibling = cell.nextSibling
  391. cell = nextSibling
  392. if (i >= fixRowHeadNum - 1) {
  393. if (this.selectcell.get(row.Local + '_' + row.Time + '_' + columnProperty[currentcolumnindex])) {
  394. this.selectcell.set(row.Local + '_' + row.Time + '_' + columnProperty[currentcolumnindex], false)
  395. } else {
  396. this.selectcell.set(row.Local + '_' + row.Time + '_' + columnProperty[currentcolumnindex], this.list[row.index])
  397. }
  398. }
  399. }
  400. }
  401. this.refresh = Math.random()
  402. },
  403. // 列选中
  404. headclick (column, event) {
  405. // 判断是否为可选列
  406. // 取消操作列选中
  407. if (column.index >= columnNum) {
  408. return
  409. }
  410. if (column.index > fixRowHeadNum - 1) {
  411. for (var i = 0; i < this.list.length; i++) {
  412. if (this.selectcell.get(this.list[i].Local + '_' + this.list[i].Time + '_' + column.property)) {
  413. this.selectcell.set(this.list[i].Local + '_' + this.list[i].Time + '_' + column.property, false)
  414. } else {
  415. this.selectcell.set(this.list[i].Local + '_' + this.list[i].Time + '_' + column.property, this.list[i])
  416. }
  417. }
  418. }
  419. this.refresh = Math.random()
  420. },
  421. // 选择值班人员
  422. personClick (person) {
  423. this.selectcell.forEach(function (value, key) {
  424. if (value) {
  425. var property = key.split('_')
  426. value[property[2]] = person
  427. }
  428. })
  429. this.selectcell = new Map()
  430. },
  431. // 更新背景
  432. cellBg ({ row, column, rowIndex, columnIndex }) {
  433. row.index = rowIndex
  434. column.index = columnIndex
  435. let _this = this
  436. // 注意这里是解构
  437. // 利用单元格的 className 的回调方法,给行列索引赋值
  438. if (_this.selectcell.get(row.Local + '_' + row.Time + '_' + column.property)) {
  439. return 'selectedCell'
  440. }
  441. },
  442. // 匹配学期
  443. formatTerm (row, column) {
  444. for (var i = 0; i < this.termList.length; i++) {
  445. if (parseInt(this.termList[i].ItemValue) === parseInt(row.Term)) {
  446. return this.termList[i].ItemName
  447. }
  448. }
  449. },
  450. // 获取学期名称
  451. getTerm () {
  452. let _this = this
  453. _this.termList.forEach(function (value, key) {
  454. if (_this.dutyDetail.Term == value.ItemValue) {
  455. _this.termName = value.ItemName
  456. }
  457. })
  458. },
  459. formatPerson (row, column, cellValue, index) {
  460. let label = '休息'
  461. for (var i = 0; i < this.PeopleList.length; i++) {
  462. if (this.PeopleList[i].Id == cellValue) {
  463. return this.PeopleList[i].PersonnelName
  464. }
  465. }
  466. return label
  467. },
  468. formatLocal (row, column, cellValue, index) {
  469. for (var i = 0; i < this.LocalList.length; i++) {
  470. if (this.LocalList[i].ItemValue == cellValue) {
  471. return this.LocalList[i].ItemName
  472. }
  473. }
  474. },
  475. formatTime (row, column, cellValue, index) {
  476. for (var i = 0; i < this.TimeList.length; i++) {
  477. if (this.TimeList[i].ItemValue == cellValue) {
  478. return this.TimeList[i].ItemName
  479. }
  480. }
  481. },
  482. // 关闭页面
  483. ...mapActions('d2admin/page', [
  484. 'close_return'
  485. ]),
  486. // 关闭
  487. back () {
  488. this.close_return({
  489. tagName: this.$route.fullPath,
  490. returnTagName: '/duty'
  491. })
  492. }
  493. }
  494. }
  495. </script>
  496. <style>
  497. .selectedCell {
  498. transition: background-color 2s;
  499. -webkit-transition: background-color 2s; /* Safari */
  500. background-color: green !important;
  501. color: white;
  502. }
  503. </style>