CpdmLeave.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. <script lang="ts" setup>
  2. import { ref, reactive, defineExpose } from 'vue'
  3. import { ElMessage, formatter, type ComponentSize, type FormInstance, type FormRules } from 'element-plus'
  4. import { leaveRecordApi, subLeaveApi } from '@/api/login';
  5. //格式化时间格式
  6. import { format } from 'date-fns/format';
  7. import CpdmLeaveEdit from './CpdmLeaveEdit.vue';
  8. const editFlag = ref<any>()
  9. const leave_visible = ref<boolean>(false)
  10. const open = () => {
  11. leave_visible.value = true;
  12. }
  13. const type = ref<string>('1')
  14. //************表单数据******************/
  15. //设置表单大小
  16. const formSize = ref<ComponentSize>('default')
  17. const ruleFormRef = ref<any>()
  18. interface RuleForm {
  19. leaveType: string
  20. userPhone: string
  21. monitorName: string
  22. dormitory: string
  23. destination: string
  24. reason: string
  25. isKnow: string
  26. companionsPhone: string
  27. motherPhone: string
  28. fatherPhone: string
  29. travelMode: string
  30. startTime: string
  31. endTime: string
  32. }
  33. const ruleForm = reactive<RuleForm>({
  34. //是否离郑
  35. leaveType: '0',
  36. //本人手机号
  37. userPhone: '',
  38. //班长姓名
  39. monitorName: '',
  40. //宿舍:
  41. dormitory: '',
  42. //出行方式
  43. destination: '',
  44. //请假原因
  45. reason: '',
  46. //父母是否知情
  47. isKnow: '1',
  48. //同行人电话
  49. companionsPhone: '',
  50. //母亲电话
  51. motherPhone: '',
  52. //父亲电话
  53. fatherPhone: '',
  54. //出行方式
  55. travelMode: '',
  56. //请假时间
  57. startTime: '',
  58. //返校时间
  59. endTime: ''
  60. })
  61. const rules = reactive<FormRules<RuleForm>>({
  62. leaveType: [
  63. { required: true, message: '请填写是否离郑', trigger: 'blur' },
  64. ],
  65. userPhone: [
  66. { required: true, message: '请填写手机号', trigger: 'blur' },
  67. { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' }
  68. ],
  69. monitorName: [
  70. { required: false, message: '请填写班长姓名', trigger: 'blur' },
  71. ],
  72. dormitory: [
  73. { required: true, message: '请填写宿舍信息', trigger: 'blur' },
  74. { min: 1, max: 200, message: '宿舍信息不能超过200字', trigger: 'blur' },
  75. ],
  76. destination: [
  77. { required: true, message: '请填写出行目的', trigger: 'blur' },
  78. { min: 1, max: 200, message: '出行目的不能超过200字', trigger: 'blur' },
  79. ],
  80. reason: [
  81. { required: true, message: '请填写请假原因', trigger: 'blur' },
  82. { min: 1, max: 20, message: '请假原因不能超过200字', trigger: 'blur' },
  83. ],
  84. isKnow: [
  85. { required: true, message: '请填写父母是否知情', trigger: 'blur' },
  86. ],
  87. companionsPhone: [
  88. { required: false, message: '请填写同行人电话', trigger: 'blur' },
  89. { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' }
  90. ],
  91. motherPhone: [
  92. { required: true, message: '请填写母亲电话', trigger: 'blur' },
  93. { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' }
  94. ],
  95. fatherPhone: [
  96. { required: true, message: '请填写父亲电话', trigger: 'blur' },
  97. { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' }
  98. ],
  99. travelMode: [
  100. { required: true, message: '请填写出行方式', trigger: 'blur' },
  101. ],
  102. startTime: [
  103. { required: true, message: '请填写请假时间', trigger: 'change' },
  104. {
  105. validator: function (rule, value, callback) {
  106. if (value !== '' && ruleForm.endTime !== '') {
  107. let startTime = new Date(value).getTime();
  108. let endTime = new Date(ruleForm.endTime).getTime()
  109. //先判断都不为空
  110. if (startTime >= endTime) {
  111. callback(new Error('请假时间应小于返校时间'))
  112. } else {
  113. callback()
  114. }
  115. } else {
  116. callback()
  117. }
  118. }, trigger: 'change'
  119. },
  120. ],
  121. endTime: [
  122. { required: true, message: '请填写返校时间', trigger: 'change' },
  123. {
  124. validator: function (rule, value, callback) {
  125. if (value !== '' && ruleForm.startTime !== '') {
  126. let startTime = new Date(ruleForm.startTime).getTime();
  127. let endTime = new Date(value).getTime()
  128. if (endTime <= startTime) {
  129. callback(new Error('返校时间应大于请假时间'))
  130. } else {
  131. callback()
  132. }
  133. } else {
  134. callback()
  135. }
  136. //
  137. }, trigger: 'change'
  138. },
  139. ],
  140. })
  141. //提交表单
  142. //按钮状态改变
  143. const buttonStatus = ref<boolean>(false)
  144. const submitForm = async (formEl: FormInstance | undefined) => {
  145. buttonStatus.value = true
  146. //设置单独校验的字段
  147. if (!formEl) {
  148. buttonStatus.value = false
  149. return
  150. }
  151. await formEl.validate(async (valid, fields) => {
  152. if (valid) {
  153. console.log('submit!')
  154. //调用用户提交信息的代码
  155. //判断返校时间是否大于请假时间
  156. let leaveTime = new Date()
  157. subLeaveInfo()
  158. } else {
  159. buttonStatus.value = false
  160. console.log('error submit!', fields)
  161. }
  162. })
  163. }
  164. //时间格式化
  165. //提交表单信息
  166. const subLeaveInfo = async () => {
  167. //提交表单信息
  168. //组装该用户需要提交的信息
  169. let params = {}
  170. //判断当前的状态是否离郑
  171. //1是不离郑
  172. if (ruleForm.leaveType == '0') {
  173. params = {
  174. userPhone: ruleForm.userPhone, //本人手机号
  175. destination: ruleForm.destination,//出行目的地
  176. dormitory: ruleForm.dormitory,//宿舍
  177. endTime: format(ruleForm.endTime, 'yyyy-MM-dd HH:mm:ss'),//返校时间
  178. fatherPhone: ruleForm.fatherPhone,//父亲手机号
  179. isKnow: ruleForm.isKnow,//父母是否知情
  180. leaveType: ruleForm.leaveType,//请假类型--离郑不离郑
  181. // monitorName: ruleForm.monitorName,//班长名字
  182. motherPhone: ruleForm.motherPhone,//母亲电话
  183. reason: ruleForm.reason,//请假原因
  184. startTime: format(ruleForm.startTime, 'yyyy-MM-dd HH:mm:ss'),//请假开始时间
  185. travelMode: ruleForm.travelMode,//出行方式
  186. // companionsPhone: ruleForm.companionsPhone, //同行人电话
  187. }
  188. } else {
  189. params = {
  190. userPhone: ruleForm.userPhone, //本人手机号
  191. destination: ruleForm.destination,//出行目的地
  192. dormitory: ruleForm.dormitory,//宿舍
  193. endTime: format(ruleForm.endTime, 'yyyy-MM-dd HH:mm:ss'),//返校时间
  194. fatherPhone: ruleForm.fatherPhone,//父亲手机号
  195. isKnow: ruleForm.isKnow,//父母是否知情
  196. leaveType: ruleForm.leaveType,//请假类型--离郑不离郑
  197. monitorName: ruleForm.monitorName,//班长名字
  198. motherPhone: ruleForm.motherPhone,//母亲电话
  199. reason: ruleForm.reason,//请假原因
  200. startTime: format(ruleForm.startTime, 'yyyy-MM-dd HH:mm:ss'),//请假开始时间
  201. travelMode: ruleForm.travelMode,//出行方式
  202. companionsPhone: ruleForm.companionsPhone, //同行人电话
  203. }
  204. }
  205. let res: any = await subLeaveApi(params)
  206. console.log(res)
  207. //跳转测试记录
  208. if (res.code == 200) {
  209. //结束了
  210. buttonStatus.value = false
  211. ElMessage({
  212. type: 'success',
  213. message: '提交成功'
  214. })
  215. //跳转到请假记录
  216. type.value = '2'
  217. leaveRecord()
  218. //开始查询请假记录的字段
  219. //
  220. } else {
  221. buttonStatus.value = false
  222. }
  223. }
  224. //清除表单的校验
  225. const resetData = (formEl: FormInstance | undefined) => {
  226. if (!formEl) return
  227. formEl.resetFields()
  228. }
  229. //是否离郑状态改变
  230. const leaveStatus = (val: string) => {
  231. // resetData(ruleFormRef)
  232. if (val == '1') {
  233. rules.monitorName = [
  234. { required: true, message: '请填写班长姓名', trigger: 'blur' },
  235. ]
  236. rules.companionsPhone = [
  237. { required: true, message: '请填写同行人电话', trigger: 'blur' },
  238. { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' }
  239. ]
  240. //这样回触发校验
  241. // rules!.monitorName[0].required = true;
  242. // rules!.companionsPhone[0].required = true
  243. }
  244. ruleFormRef.value.clearValidate()
  245. }
  246. //类型方法
  247. const typeFun = (val: string) => {
  248. type.value = val;
  249. if (val == '1') {
  250. //清空表单
  251. ruleFormRef.value.clearValidate()
  252. ruleFormRef.value.resetFields()
  253. } else {
  254. //查询记录列表
  255. leaveRecord()
  256. }
  257. }
  258. //请假记录列表
  259. let tableData = ref<any>([])
  260. //第几页
  261. const pageNum = ref<number>(1)
  262. //每页多少条
  263. const pageSize = ref<number>(10)
  264. //总条数
  265. const total = ref<number>(0)
  266. const leaveRecord = async () => {
  267. //leaveRecordApi
  268. let params = {
  269. pageNum: pageNum.value,
  270. pageSize: pageSize.value
  271. }
  272. let res: any = await leaveRecordApi(params)
  273. tableData.value = res.data.content
  274. total.value = res.data.totalElements
  275. }
  276. //格式化是否离郑
  277. const leaveTypeFormatter = (val: any) => {
  278. if (val.leaveType == '0') {
  279. return '不离郑'
  280. } else {
  281. return '离郑'
  282. }
  283. }
  284. //格式化父母是否知情
  285. const isKnowFormatter = (val: any) => {
  286. if (val.isKnow == '1') {
  287. return '知情'
  288. } else {
  289. return '不知情'
  290. }
  291. }
  292. //格式审核状态状态
  293. const auditStatusFormatter = (val: any) => {
  294. if (val.auditStatus == '0') {
  295. return '待审批'
  296. } else {
  297. return '已审批'
  298. }
  299. }
  300. //审核结果
  301. const auditResultFormatter = (val: any) => {
  302. if (val.auditResult == null) {
  303. return ''
  304. } else {
  305. if (val.auditResult == '0') {
  306. return '驳回'
  307. } else {
  308. return '通过'
  309. }
  310. }
  311. }
  312. //分页显示
  313. const handleCurrentChange = (val: number) => {
  314. pageNum.value = val
  315. leaveRecord()
  316. }
  317. //需要重新编辑操作
  318. const editFun = (val: any, flag: boolean) => {
  319. editFlag.value.open(val, flag)
  320. }
  321. const listFun = () => {
  322. //刷新列表
  323. leaveRecord()
  324. }
  325. defineExpose({ open })
  326. </script>
  327. <template>
  328. <div class="outt"> <el-dialog v-model="leave_visible" :show-close="true" width="80%" top="5vh"
  329. style="border-radius: 40px; ">
  330. <template #header="{ close, titleId, titleClass }">
  331. <!-- <img src="../assets/zs/top_leave.png" alt="" > -->
  332. <div class="leave_title"></div>
  333. <div
  334. style="display: inline-flex;background-color: #EDEDED ;padding: 4px;border-radius: 40px;margin-left: 20px;">
  335. <span :class="{ button_leave_active: type == '1', button_leave_default: type == '2' }"
  336. @click="typeFun('1')">我要请假</span>
  337. <span :class="{ button_leave_active: type == '2', button_leave_default: type == '1' }"
  338. @click="typeFun('2')">请假记录</span>
  339. </div>
  340. <!-- <el-radio-group v-model="type" size="large" @change="typeFun" style="margin-left:20px">
  341. <el-radio-button label="我要请假" value="1" />
  342. <el-radio-button label="请假记录" value="2" />
  343. </el-radio-group> -->
  344. <div v-show="type == '1'" class="leave">
  345. <el-form ref="ruleFormRef" style="display: flex;flex-wrap: wrap;" :model="ruleForm" :rules="rules"
  346. :validate-on-rule-change=false label-width="auto" class="demo-ruleForm" :size="formSize"
  347. status-icon>
  348. <el-form-item label="是否离郑" prop="leaveType">
  349. <el-radio-group v-model="ruleForm.leaveType" @change="leaveStatus">
  350. <el-radio value="0">不离郑</el-radio>
  351. <el-radio value="1">离郑</el-radio>
  352. </el-radio-group>
  353. </el-form-item>
  354. <el-form-item label="本人手机号码" prop="userPhone">
  355. <el-input v-model="ruleForm.userPhone" placeholder="请输入本人手机号码" />
  356. </el-form-item>
  357. <el-form-item label="班长姓名" prop="monitorName" v-if="ruleForm.leaveType == '1'">
  358. <el-input v-model="ruleForm.monitorName" placeholder="请输入班长姓名" />
  359. </el-form-item>
  360. <el-form-item label="宿舍" prop="dormitory">
  361. <el-input v-model="ruleForm.dormitory" placeholder="例如松15-XXX" />
  362. </el-form-item>
  363. <el-form-item label="请假原因" prop="reason">
  364. <el-input v-model="ruleForm.reason" :rows="2" type="textarea" placeholder="一定要写清楚,例如拔牙" />
  365. </el-form-item>
  366. <el-form-item label="出行目的地" prop="destination">
  367. <el-input v-model="ruleForm.destination" :rows="2" type="textarea"
  368. placeholder="一定要写清楚,例如郑州市中原区高新区郑州中心医院" />
  369. </el-form-item>
  370. <el-form-item label="父母是否知情" prop="isKnow">
  371. <el-radio-group v-model="ruleForm.isKnow">
  372. <el-radio value="1">知情</el-radio>
  373. <el-radio value="0">不知情</el-radio>
  374. </el-radio-group>
  375. </el-form-item>
  376. <el-form-item label="同行人电话" prop="companionsPhone" v-if="ruleForm.leaveType == '1'">
  377. <el-input v-model="ruleForm.companionsPhone" placeholder="请输入同行人电话" />
  378. </el-form-item>
  379. <el-form-item label="母亲电话" prop="motherPhone">
  380. <el-input v-model="ruleForm.motherPhone" placeholder="请输入母亲电话" />
  381. </el-form-item>
  382. <el-form-item label="父亲电话" prop="fatherPhone">
  383. <el-input v-model="ruleForm.fatherPhone" placeholder="请输入父亲电话" />
  384. </el-form-item>
  385. <el-form-item label="出行方式" prop="travelMode">
  386. <el-input v-model="ruleForm.travelMode" placeholder="请输入出行方式" />
  387. </el-form-item>
  388. <el-form-item label="请假时间" prop="startTime">
  389. <el-date-picker v-model="ruleForm.startTime" type="datetime" placeholder="请输入请假时间"
  390. style="width: 100%;" />
  391. </el-form-item>
  392. <el-form-item label="返校时间" prop="endTime">
  393. <el-date-picker v-model="ruleForm.endTime" type="datetime" placeholder="请输入返校时间"
  394. style="width: 100%;" />
  395. </el-form-item>
  396. </el-form>
  397. <div class="reset_sub">
  398. <el-button @click="resetData(ruleFormRef)"
  399. style="border-radius: 40px;padding:10px 40px">重置</el-button>
  400. <el-button type="success" @click="submitForm(ruleFormRef)" :disabled="buttonStatus"
  401. style="border-radius: 40px;padding:10px 40px">提交</el-button>
  402. </div>
  403. <div class="leave_tip"> 温馨提示:(天气寒冷,晚上行人少,为保证大家安全,返校时间尽量在21:00之前)
  404. </div>
  405. </div>
  406. <div v-show="type == '2'" style="padding:10px 20px">
  407. <el-table :data="tableData" style="width: 100%;height: 60vh;"
  408. :header-cell-style="{ background: '#F8F8F8', color: '#606266' }">
  409. <el-table-column fixed prop="leaveType" label="是否离郑" width="" :formatter="leaveTypeFormatter"
  410. align="center" />
  411. <el-table-column prop="userPhone" label="本人手机号码" width="" show-overflow-tooltip
  412. align="center" />
  413. <!-- <el-table-column prop="monitorName" label="班长姓名" width="" /> -->
  414. <!-- <el-table-column prop="dormitory" label="宿舍" width="" /> -->
  415. <el-table-column prop="reason" label="请假原因" width="" align="center" />
  416. <el-table-column prop="destination" label="出行目的地" width="" show-overflow-tooltip
  417. align="center" />
  418. <!-- <el-table-column prop="isKnow" label="父母是否知情" width="" :formatter="isKnowFormatter" /> -->
  419. <!-- <el-table-column prop="companionsPhone" label="同行人电话" width="" /> -->
  420. <!-- <el-table-column prop="motherPhone" label="母亲电话" width="" />
  421. <el-table-column prop="fatherPhone" label="父亲电话" width="" /> -->
  422. <el-table-column prop="travelMode" label="出行方式" width="" show-overflow-tooltip align="center" />
  423. <el-table-column prop="startTime" label="请假时间" width="" show-overflow-tooltip align="center" />
  424. <el-table-column prop="endTime" label="返校时间" width="" show-overflow-tooltip align="center" />
  425. <el-table-column fixed="right" prop="auditSuggest" label="审核建议" width="" align="center"
  426. show-overflow-tooltip />
  427. <el-table-column fixed="right" prop="auditStatus" label="审核状态" width="" align="center"
  428. :formatter="auditStatusFormatter" />
  429. <!-- :formatter="auditStatusFormatter" -->
  430. <el-table-column fixed="right" prop="auditResult" label="审核结果" width="" align="center">
  431. <template #default="scoped">
  432. <div style="display: flex;justify-content: center;align-items: center;"
  433. v-show="scoped.row.auditResult == '1'">
  434. <img style="width: 14px;" src="../assets/footer/pass.png" alt="">&nbsp;
  435. <div>通过</div>
  436. </div>
  437. <div style="display: flex;justify-content: center;align-items: center;"
  438. v-show="scoped.row.auditResult == '0'">
  439. <img style="width: 14px;" src="../assets/footer/noPass.png" alt="">&nbsp;
  440. <div>驳回</div>
  441. </div>
  442. </template>
  443. </el-table-column>
  444. <!-- <el-table-column fixed="right" prop="auditResult" label="审核结果" width="" align="center"
  445. :formatter="auditResultFormatter" /> -->
  446. <el-table-column fixed="right" label="操作" min-width="" align="center">
  447. <template #default="scoped">
  448. <el-button v-show="scoped.row.auditResult == null" link type="primary" size="small"
  449. @click="editFun(scoped.row, false)">重新编辑</el-button>
  450. <el-button link type="primary" size="small" style="margin-left: 0px;"
  451. @click="editFun(scoped.row, true)">查看</el-button>
  452. </template>
  453. </el-table-column>
  454. </el-table>
  455. <div style="display: flex;justify-content: center;margin-top:10px">
  456. <el-pagination background v-model:current-page="pageNum" :page-size="pageSize"
  457. layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" />
  458. </div>
  459. </div>
  460. </template>
  461. <CpdmLeaveEdit ref="editFlag" @search='listFun' />
  462. </el-dialog></div>
  463. </template>
  464. <style lang="scss" scoped>
  465. .button_leave_active {
  466. background-color: #ffffff;
  467. padding: 6px 12px;
  468. border-radius: 40px;
  469. font-size: 16px;
  470. color: #222222;
  471. }
  472. .button_leave_default {
  473. padding: 6px 12px;
  474. border-radius: 40px;
  475. font-size: 16px;
  476. color: #999999;
  477. }
  478. .outt {
  479. :deep(.el-dialog) {
  480. padding: 0px !important;
  481. }
  482. :deep(.el-dialog__header.show-close) {
  483. padding-right: 0px !important;
  484. }
  485. :deep(.el-dialog__headerbtn .el-dialog__close) {
  486. color: #ffffff !important;
  487. }
  488. }
  489. .leave {
  490. padding: 10px 20px;
  491. :deep(.el-form) {
  492. justify-content: space-between;
  493. }
  494. :deep(.el-form-item) {
  495. width: 48% !important;
  496. margin-top: 10px;
  497. }
  498. :deep(.el-input__wrapper) {
  499. align-items: center;
  500. background-color: #F7F7F7 !important;
  501. border-radius: 40px !important;
  502. // border: none;
  503. // outline: none !important;
  504. box-shadow: none;
  505. }
  506. :deep(.el-form-item__content) {
  507. align-items: flex-start !important;
  508. // align-items: center !important;
  509. }
  510. }
  511. .reset_sub {
  512. display: flex;
  513. justify-content: space-around;
  514. }
  515. .leave_tip {
  516. margin-top: 20px;
  517. color: #5c5c5c;
  518. text-align: center;
  519. font-size: 12px;
  520. }
  521. .leave_title {
  522. background: url(../assets/zs/top_leave.png) no-repeat;
  523. background-size: 100% 100%;
  524. // border-radius: 40px;
  525. border-top-left-radius: 40px;
  526. border-top-right-radius: 40px;
  527. height: 40px;
  528. text-align: center;
  529. color: #333333;
  530. font-weight: 700;
  531. font-size: 16px;
  532. margin-bottom: 20px;
  533. }
  534. </style>