feat:完成出差申请提前结束功能
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.hrm.controller;
|
package com.ruoyi.hrm.controller;
|
||||||
|
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.AjaxResult;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.PageQuery;
|
import com.ruoyi.common.core.domain.PageQuery;
|
||||||
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.domain.R;
|
||||||
@@ -28,6 +29,7 @@ import java.util.List;
|
|||||||
public class HrmTravelReqController extends BaseController {
|
public class HrmTravelReqController extends BaseController {
|
||||||
|
|
||||||
private final IHrmTravelReqService service;
|
private final IHrmTravelReqService service;
|
||||||
|
private final IHrmTravelReqService hrmTravelReqService;
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo<HrmTravelReqVo> list(HrmTravelReqBo bo, PageQuery pageQuery) {
|
public TableDataInfo<HrmTravelReqVo> list(HrmTravelReqBo bo, PageQuery pageQuery) {
|
||||||
@@ -56,6 +58,10 @@ public class HrmTravelReqController extends BaseController {
|
|||||||
public R<Void> remove(@PathVariable @NotEmpty Long[] bizIds) {
|
public R<Void> remove(@PathVariable @NotEmpty Long[] bizIds) {
|
||||||
return toAjax(service.deleteWithValidByIds(Arrays.asList(bizIds), true));
|
return toAjax(service.deleteWithValidByIds(Arrays.asList(bizIds), true));
|
||||||
}
|
}
|
||||||
|
@PutMapping("/earlyEnd/{bizId}")
|
||||||
|
public R<Void> earlyEnd(@PathVariable Long bizId) {
|
||||||
|
return toAjax(hrmTravelReqService.earlyEnd(bizId));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/all")
|
@GetMapping("/all")
|
||||||
public R<List<HrmTravelReqVo>> all(HrmTravelReqBo bo) {
|
public R<List<HrmTravelReqVo>> all(HrmTravelReqBo bo) {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class HrmTravelReq extends BaseEntity {
|
|||||||
private String bankName;
|
private String bankName;
|
||||||
private String bankAccount;
|
private String bankAccount;
|
||||||
private String remark;
|
private String remark;
|
||||||
|
private Date actualEndTime;
|
||||||
@TableLogic
|
@TableLogic
|
||||||
private Integer delFlag;
|
private Integer delFlag;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,5 +22,7 @@ public interface IHrmTravelReqService {
|
|||||||
|
|
||||||
Boolean updateByBo(HrmTravelReqBo bo);
|
Boolean updateByBo(HrmTravelReqBo bo);
|
||||||
|
|
||||||
|
int earlyEnd(Long bizId);
|
||||||
|
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Service
|
@Service
|
||||||
@@ -128,4 +129,36 @@ public class HrmTravelReqServiceImpl implements IHrmTravelReqService {
|
|||||||
private String defaultStatus(String status) {
|
private String defaultStatus(String status) {
|
||||||
return status == null ? "draft" : status;
|
return status == null ? "draft" : status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public int earlyEnd(Long bizId) {
|
||||||
|
HrmTravelReq travelReq = baseMapper.selectById(bizId);
|
||||||
|
if (travelReq == null) {
|
||||||
|
throw new RuntimeException("出差申请不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
String status = travelReq.getStatus();
|
||||||
|
if (!"approved".equals(status) && !"in_progress".equals(status)) {
|
||||||
|
throw new RuntimeException("当前状态不能提前结束,只有已通过或进行中的出差才能提前结束");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 检查是否已经提前结束过
|
||||||
|
if (travelReq.getActualEndTime() != null) {
|
||||||
|
throw new RuntimeException("该出差已经提前结束过了");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 更新实际结束时间为当前时间
|
||||||
|
travelReq.setActualEndTime(new Date());
|
||||||
|
// 5. 可选:更新状态为已完成
|
||||||
|
travelReq.setStatus("completed");
|
||||||
|
|
||||||
|
// 6. 执行更新
|
||||||
|
int result = baseMapper.updateById(travelReq);
|
||||||
|
if (result <= 0) {
|
||||||
|
throw new RuntimeException("提前结束失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,3 +46,9 @@ export function allTravelReq(query) {
|
|||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function earlyEndTravel(bizId) {
|
||||||
|
return request({
|
||||||
|
url: `/hrm/travel/earlyEnd/${bizId}`,
|
||||||
|
method: 'put'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,30 @@
|
|||||||
<BizDetailContainer :bizId="currentBizId" bizType="travel" :preview="preview">
|
<BizDetailContainer :bizId="currentBizId" bizType="travel" :preview="preview">
|
||||||
<template slot-scope="{ detail }">
|
<template slot-scope="{ detail }">
|
||||||
<div>
|
<div>
|
||||||
|
<!-- ===== 新增:提前结束按钮区域 ===== -->
|
||||||
|
<div class="action-buttons" v-if="showEarlyEndButton(detail)">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
size="small"
|
||||||
|
icon="el-icon-finished"
|
||||||
|
:loading="earlyEndLoading"
|
||||||
|
@click="handleEarlyEnd"
|
||||||
|
>
|
||||||
|
提前结束
|
||||||
|
</el-button>
|
||||||
|
<span class="hint-text">提前结束将把当前时间记录为实际结束时间</span>
|
||||||
|
</div>
|
||||||
|
<!-- ===== 新增:显示已提前结束的信息 ===== -->
|
||||||
|
<div v-if="detail.actualEndTime" class="early-end-info">
|
||||||
|
<el-alert
|
||||||
|
type="info"
|
||||||
|
:closable="false"
|
||||||
|
show-icon>
|
||||||
|
<template slot="default">
|
||||||
|
该出差已于 {{ formatDate(detail.actualEndTime) }} 提前结束
|
||||||
|
</template>
|
||||||
|
</el-alert>
|
||||||
|
</div>
|
||||||
<!-- 出差时间与行程 -->
|
<!-- 出差时间与行程 -->
|
||||||
<div class="block-title">出差时间与行程</div>
|
<div class="block-title">出差时间与行程</div>
|
||||||
<el-card class="inner-card" shadow="never">
|
<el-card class="inner-card" shadow="never">
|
||||||
@@ -41,6 +65,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import FilePreview from "@/components/FilePreview/index.vue";
|
import FilePreview from "@/components/FilePreview/index.vue";
|
||||||
import BizDetailContainer from '@/views/hrm/components/BizDetailContainer/index.vue';
|
import BizDetailContainer from '@/views/hrm/components/BizDetailContainer/index.vue';
|
||||||
|
import { earlyEndTravel } from '@/api/hrm/travel'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TravelDetail',
|
name: 'TravelDetail',
|
||||||
@@ -53,7 +78,11 @@ export default {
|
|||||||
BizDetailContainer,
|
BizDetailContainer,
|
||||||
FilePreview
|
FilePreview
|
||||||
},
|
},
|
||||||
name: 'HrmTravelDetail',
|
data() {
|
||||||
|
return {
|
||||||
|
earlyEndLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentBizId () {
|
currentBizId () {
|
||||||
return this.bizId || this.$route?.params?.bizId || this.$route?.query?.bizId || this.$route?.params?.id
|
return this.bizId || this.$route?.params?.bizId || this.$route?.query?.bizId || this.$route?.params?.id
|
||||||
@@ -66,7 +95,41 @@ export default {
|
|||||||
const p = n => (n < 10 ? `0${n}` : n)
|
const p = n => (n < 10 ? `0${n}` : n)
|
||||||
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`
|
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`
|
||||||
},
|
},
|
||||||
|
// 新增:处理提前结束
|
||||||
|
showEarlyEndButton(detail) {
|
||||||
|
if (!detail) return false
|
||||||
|
// 已经提前结束的不显示
|
||||||
|
if (detail.actualEndTime) return false
|
||||||
|
// 只有已通过或进行中状态才显示
|
||||||
|
const status = detail.status
|
||||||
|
return status === 'approved' || status === 'in_progress'
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEarlyEnd() {
|
||||||
|
this.$confirm('确认提前结束本次出差吗?结束后的实际时间将记录为当前时间。', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
this.earlyEndLoading = true
|
||||||
|
try {
|
||||||
|
const bizId = this.currentBizId
|
||||||
|
await earlyEndTravel(bizId)
|
||||||
|
this.$message.success('提前结束成功')
|
||||||
|
// 刷新页面
|
||||||
|
setTimeout(() => {
|
||||||
|
location.reload()
|
||||||
|
}, 1000)
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error(error.message || '提前结束失败')
|
||||||
|
} finally {
|
||||||
|
this.earlyEndLoading = false
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -375,4 +438,17 @@ export default {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.action-buttons {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: #fdf6ec;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.early-end-info {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user