index.vue 16 KB

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