index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. <template>
  2. <!-- 面试日历 -->
  3. <div id="interviewCalendar" class="box">
  4. <div class="interviewCalendar">
  5. <el-calendar v-model="dayValue">
  6. </el-calendar>
  7. <div style="padding-left: 20px">
  8. <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
  9. <el-checkbox-group v-model="checkList" @change="statusChange">
  10. <div v-for="(item, index) in statusIndexList" :key="index" >
  11. <div style="padding: 5px 20px;font-size: 14px"><el-checkbox :key="index" :label="item">{{ statusList[index] }}</el-checkbox></div>
  12. </div>
  13. </el-checkbox-group>
  14. </div>
  15. <div style="padding: 20px">
  16. <el-button size="medium" type="primary">导出报表</el-button>
  17. </div>
  18. </div>
  19. <div style="min-width: 1050px">
  20. <div style="display: flex;justify-content: center;font-weight: bold;padding: 25px;font-size: 18px;letter-spacing: 5px">
  21. <div><i class="el-icon-arrow-left" style="cursor: pointer" @click="changeWeek(-1)"></i>{{weekDay1.getFullYear()}}年{{weekDay1.getMonth()+1}}月{{weekDay1.getDate()}}日-{{weekDay2.getMonth()+1}}月{{weekDay2.getDate()}}日
  22. <i class="el-icon-arrow-right" style="cursor: pointer" @click="changeWeek(1)"></i></div>
  23. </div>
  24. <div class="week_box" >
  25. <div v-if="weekDayList.length>0" v-for="(item, index) in weekDay" :key="index" :class="dayValue.getDate()==weekDayList[index].num?'selColor card_date':'card_date'">
  26. <div>{{ item }}</div>
  27. <div :class="dayValue.getDate()==weekDayList[index].num?'selCircle':'selNone'">{{ weekDayList[index].num }}</div>
  28. </div>
  29. </div>
  30. <div class="week_box week_container" id="weekContainer">
  31. <div v-if="dayInterviewVos.length>0" v-for="(item, index) in dayInterviewVos" :key="index" class="day_row">
  32. <div v-for="(item_c, index_c) in item.quantumList" :key="index_c" :class="index==0?'day_col day_row0':'day_col'">
  33. <div v-if="index==0" class="timeLine">
  34. {{timeline[index_c]}}
  35. </div>
  36. <el-popover
  37. width="450"
  38. v-if="item_c.recruitInterviewList.length>0"
  39. trigger="hover">
  40. <div>
  41. <div v-for="(val, key,i) in item_c.mergeObj" :key="i" >
  42. <div>
  43. {{key}}:
  44. <div v-for="(item_val, index_val) in val" :key="index_val" style="padding-left: 60px;display:flex ;justify-content: space-between;padding-bottom: 5px;align-items: center;">
  45. <div> {{item_val.recruitResumeVo.realname}} - {{item_val.recruitResumeVo.telphone}} - {{statusList[item_val.status]}}</div>
  46. <div>
  47. <el-button size="mini" type="primary" @click="updateStatue(item_val)">标注</el-button>
  48. <el-button size="mini" type="primary" @click="updateDate(item_val)">改期</el-button>
  49. </div>
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <div slot="reference" style="cursor: pointer;">
  55. <div style="font-size: 12px;text-align: left;">待面试:</div>
  56. <div v-for="(val, key,i) in item_c.mergeObj" :key="i" class="day_col_item">
  57. <div> <span class="color1">{{key}}*{{val.length}}</span></div>
  58. </div>
  59. </div>
  60. </el-popover>
  61. </div>
  62. </div>
  63. </div>
  64. </div>
  65. <el-dialog
  66. :visible.sync="dateDialogVisible"
  67. width="30%"
  68. center>
  69. <div style="margin-top: 30px">
  70. <div style="text-align: center"> {{dateForm.recruitResumeVo.realname}} - {{dateForm.job}}</div>
  71. <div style="text-align: center;margin-top: 20px">
  72. <el-date-picker type="datetime" placeholder="选择时间" v-model="dateForm.resumeTime" value-format="timestamp"></el-date-picker>
  73. </div>
  74. </div>
  75. <span slot="footer" class="dialog-footer">
  76. <el-button @click="dateDialogVisible = false">取 消</el-button>
  77. <el-button type="primary" @click="submitForm(1)">确认</el-button>
  78. </span>
  79. </el-dialog>
  80. <el-dialog
  81. :visible.sync="statusDialogVisible"
  82. width="30%"
  83. center>
  84. <div style="margin-top: 30px">
  85. <div style="text-align: center"> {{statusForm.recruitResumeVo.realname}} - {{statusForm.job}}</div>
  86. <div style="text-align: center;margin-top: 20px">
  87. <el-select v-model="value" placeholder="请选择">
  88. <el-option
  89. v-for="item in options"
  90. :key="item.value"
  91. :label="item.label"
  92. :value="item.value">
  93. </el-option>
  94. </el-select>
  95. </div>
  96. </div>
  97. <span slot="footer" class="dialog-footer">
  98. <el-button @click="statusDialogVisible = false">取 消</el-button>
  99. <el-button type="primary" @click="submitForm(0)">确认</el-button>
  100. </span>
  101. </el-dialog>
  102. </div>
  103. </template>
  104. <script>
  105. export default {
  106. data() {
  107. return {
  108. options: [{
  109. value: 0,
  110. label: '已投递'
  111. }, {
  112. value: 1,
  113. label: '已发邀请'
  114. }, {
  115. value: 2,
  116. label: '已确定'
  117. }, {
  118. value: 3,
  119. label: '已谢绝'
  120. }, {
  121. value: 4,
  122. label: '初试通过'
  123. }, {
  124. value: 5,
  125. label: '初试不通过'
  126. }, {
  127. value: 6,
  128. label: '复试通过'
  129. }, {
  130. value: 7,
  131. label: '复试不通过'
  132. }, {
  133. value: 8,
  134. label: '已发offer'
  135. }, {
  136. value: 9,
  137. label: '爽约'
  138. }, {
  139. value: 10,
  140. label: '淘汰'
  141. }, {
  142. value: 11,
  143. label: '放弃'
  144. }, {
  145. value: 12,
  146. label: '转正'
  147. }],
  148. statusForm:{
  149. recruitResumeVo:''
  150. },
  151. value:'',
  152. statusDialogVisible:false,
  153. dateForm:{
  154. recruitResumeVo:''
  155. },
  156. dateDialogVisible:false,
  157. isIndeterminate: false,
  158. checkAll: true,
  159. checkList:[0,1,2,3,4,5,6,7,8,9,10,11,12],
  160. dayValue: new Date(),
  161. loading: false, //当前表单加载是否加载动画
  162. weekDay:['周一','周二','周三','周四','周五','周六','周日'],
  163. weekDayList:[],
  164. date_num: [],
  165. currIndex:0,
  166. dayInterviewVos:[],
  167. timeline:['凌晨0点','凌晨1点','凌晨2点','凌晨3点','凌晨4点','凌晨5点','上午6点','上午7点','上午8点','上午9点','上午10点','上午11点','中午12点','下午1点',
  168. '下午2点','下午3点','下午4点','下午5点','下午6点','晚上7点','晚上8点','晚上9点','晚上10点','晚上11点'],
  169. weekDay1:new Date(),
  170. weekDay2:new Date(),
  171. statusList:['已投递','已发邀请','已确认','已谢绝','初试通过','初试不通过','复试通过','复试不通过','已发Offer','爽约','淘汰(试用公司辞退)','放弃(试用期个人离职)','转正'],
  172. statusIndexList:[0,1,2,3,4,5,6,7,8,9,10,11,12],
  173. statusRadio: 0
  174. };
  175. },
  176. mounted() {
  177. this.search();
  178. },
  179. methods: {
  180. editrecruitinterviewStatus(){
  181. let data = {}
  182. data.status = this.value
  183. data.interviewId = this.statusForm.interviewId
  184. let that = this
  185. this.$api.editrecruitinterview(data).then((res) => {
  186. if(res.code==200){
  187. that.statusDialogVisible = false
  188. that.search();
  189. }
  190. });
  191. },
  192. editrecruitinterview(){
  193. let data = {}
  194. data.resumeTime = parseInt(this.dateForm.resumeTime/1000)
  195. data.interviewId = this.dateForm.interviewId
  196. let that = this
  197. this.$api.editrecruitinterview(data).then((res) => {
  198. if(res.code==200){
  199. that.dateDialogVisible = false
  200. that.search();
  201. }
  202. });
  203. },
  204. submitForm(type){
  205. if(type==0){
  206. this.editrecruitinterviewStatus()
  207. }
  208. if(type==1){
  209. this.editrecruitinterview()
  210. }
  211. },
  212. updateStatue(val){
  213. this.statusDialogVisible = true
  214. this.statusForm = JSON.parse(JSON.stringify(val));
  215. this.value = this.statusForm.status
  216. },
  217. updateDate(val){
  218. this.dateDialogVisible = true
  219. this.dateForm = JSON.parse(JSON.stringify(val));
  220. this.dateForm.resumeTime = this.dateForm.resumeTime*1000
  221. },
  222. handleCheckAllChange(val){
  223. this.checkList = val ? this.statusIndexList : [];
  224. this.isIndeterminate = false;
  225. console.log(this.checkList)
  226. this.search();
  227. },
  228. statusChange(value){
  229. let checkedCount = value.length;
  230. this.checkAll = checkedCount === this.statusList.length;
  231. this.isIndeterminate = checkedCount > 0 && checkedCount < this.statusList.length;
  232. this.search();
  233. console.log(this.checkList,99)
  234. },
  235. changeWeek(index){
  236. if(index==-1){
  237. this.dayValue.setTime(this.dayValue.getTime()-7*24*60*60*1000)
  238. }
  239. if(index==1){
  240. this.dayValue.setTime(this.dayValue.getTime()+7*24*60*60*1000)
  241. }
  242. let d = new Date()
  243. d.setTime(this.dayValue.getTime())
  244. this.dayValue = d
  245. this.search()
  246. },
  247. search() {
  248. let that = this
  249. this.loading = true;
  250. var data = {
  251. year: this.dayValue.getFullYear(),
  252. month: this.dayValue.getMonth()+1,
  253. day: this.dayValue.getDate(),
  254. statusIds:this.checkList.toString()
  255. };
  256. this.$api.recruitinterviewlist(data).then((res) => {
  257. if(res.code==200){
  258. that.dayInterviewVos = res.data.dayInterviewVos
  259. that.weekDayList = []
  260. for(let i = 0; i < that.dayInterviewVos.length; i++) {
  261. if(res.data.dayInterviewVos[i].date==that.dayValue.getDate()){
  262. that.currIndex = i
  263. }
  264. let weekDay = {
  265. num:that.dayInterviewVos[i].date
  266. }
  267. that.weekDayList.push(weekDay)
  268. that.dealDayList(that.dayInterviewVos[i].quantumList)
  269. }
  270. for(let i = 0; i < that.weekDayList.length; i++) {
  271. var d=new Date();
  272. d.setTime(that.dayValue.getTime()+(i-that.currIndex)*24*60*60*1000)
  273. that.weekDayList[i].day = d
  274. if(i==0){
  275. that.weekDay1 = d
  276. }
  277. if(i==6){
  278. that.weekDay2 = d
  279. }
  280. }
  281. that.$nextTick(function(){
  282. document.getElementById('weekContainer').scrollTop = 479
  283. });
  284. }
  285. });
  286. this.loading = false;
  287. },
  288. dealDayList(quantumList){
  289. for(let i =0;i<quantumList.length;i++){
  290. let item = quantumList[i]
  291. let mergeObj = {}
  292. for(let j =0;j<item.recruitInterviewList.length;j++){
  293. let dayItem = item.recruitInterviewList[j]
  294. if(mergeObj.hasOwnProperty(dayItem.job)){
  295. let valueList = mergeObj[dayItem.job]
  296. valueList.push(dayItem)
  297. }else{
  298. let valueList = []
  299. valueList.push(dayItem)
  300. mergeObj[dayItem.job] = valueList
  301. }
  302. }
  303. item.mergeObj = mergeObj
  304. }
  305. },
  306. },
  307. watch:{
  308. dayValue(val, oldVal){//普通的watch监听
  309. this.search()
  310. }
  311. }
  312. };
  313. </script>
  314. <style >
  315. .interviewCalendar .el-calendar-table .el-calendar-day{
  316. height: auto;
  317. }
  318. .interviewCalendar .el-calendar-table tr:first-child td{
  319. border-top: none;
  320. }
  321. .interviewCalendar .el-calendar-table td{
  322. border-bottom: none;
  323. border-right: none;
  324. }
  325. .interviewCalendar .el-calendar-table tr td:first-child{
  326. border-left: none;
  327. }
  328. .interviewCalendar .el-button--mini, .el-button--mini.is-round{
  329. padding: 7px;
  330. }
  331. </style>
  332. <style lang="less" scoped>
  333. .color1{
  334. color: #ffffff;
  335. background-color: #E6A23C;
  336. padding: 2px 5px;
  337. border-radius: 4px;
  338. }
  339. .day_col_item{
  340. color: #666666;
  341. font-size: 12px;
  342. padding: 5px;
  343. overflow: hidden;
  344. }
  345. .timeLine{
  346. position: absolute;
  347. left: -55px;
  348. top: 20px;
  349. color: #666666;
  350. font-size: 12px;
  351. }
  352. .day_row0{
  353. border-left: 1px solid #EBEEF5;
  354. }
  355. .day_col:first-child{
  356. border-top: 1px solid #EBEEF5;
  357. }
  358. .day_col{
  359. width: 100%;
  360. height: 60px;
  361. border-bottom: 1px solid #EBEEF5;
  362. border-right: 1px solid #EBEEF5;
  363. position: relative;
  364. }
  365. .day_row{
  366. width: 14%;
  367. text-align: center;
  368. }
  369. .selNone {
  370. margin-top: 20px
  371. }
  372. .selCircle {
  373. border-radius: 50%;
  374. width: 50px;
  375. height: 50px;
  376. color: #ffffff !important;
  377. background-color: #3494F7;
  378. text-align: center;
  379. line-height: 50px;
  380. margin: 0 auto;
  381. }
  382. .selColor{
  383. color: #3494F7 !important;
  384. }
  385. .week_container{
  386. height: 600px;
  387. overflow-y: auto;
  388. margin-bottom: 50px;
  389. }
  390. .week_container::-webkit-scrollbar {
  391. display: none; /* Chrome Safari */
  392. }
  393. .week_box{
  394. min-width: 1050px;
  395. display: flex;
  396. justify-content:center;
  397. margin-top: 20px;
  398. padding-left: 50px;
  399. }
  400. .card_date {
  401. width: 14%;
  402. text-align: center;
  403. color: #000;
  404. }
  405. .box{
  406. display: flex;
  407. width: 100%;
  408. min-width: 1350px;
  409. }
  410. .interviewCalendar{
  411. width: 300px;
  412. height: 350px;
  413. }
  414. </style>