Compare commits
2 Commits
ebb57f4f26
...
8b627c000f
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b627c000f | |||
| 56f7a6abb9 |
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.hrm.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.AjaxResult;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
@@ -28,6 +29,7 @@ import java.util.List;
|
||||
public class HrmTravelReqController extends BaseController {
|
||||
|
||||
private final IHrmTravelReqService service;
|
||||
private final IHrmTravelReqService hrmTravelReqService;
|
||||
|
||||
@GetMapping("/list")
|
||||
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) {
|
||||
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")
|
||||
public R<List<HrmTravelReqVo>> all(HrmTravelReqBo bo) {
|
||||
|
||||
@@ -32,6 +32,7 @@ public class HrmTravelReq extends BaseEntity {
|
||||
private String bankName;
|
||||
private String bankAccount;
|
||||
private String remark;
|
||||
private Date actualEndTime;
|
||||
@TableLogic
|
||||
private Integer delFlag;
|
||||
}
|
||||
|
||||
@@ -22,5 +22,7 @@ public interface IHrmTravelReqService {
|
||||
|
||||
Boolean updateByBo(HrmTravelReqBo bo);
|
||||
|
||||
int earlyEnd(Long bizId);
|
||||
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@@ -128,4 +129,36 @@ public class HrmTravelReqServiceImpl implements IHrmTravelReqService {
|
||||
private String defaultStatus(String 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
|
||||
})
|
||||
}
|
||||
export function earlyEndTravel(bizId) {
|
||||
return request({
|
||||
url: `/hrm/travel/earlyEnd/${bizId}`,
|
||||
method: 'put'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,6 +2,30 @@
|
||||
<BizDetailContainer :bizId="currentBizId" bizType="travel" :preview="preview">
|
||||
<template slot-scope="{ detail }">
|
||||
<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>
|
||||
<el-card class="inner-card" shadow="never">
|
||||
@@ -41,6 +65,7 @@
|
||||
<script>
|
||||
import FilePreview from "@/components/FilePreview/index.vue";
|
||||
import BizDetailContainer from '@/views/hrm/components/BizDetailContainer/index.vue';
|
||||
import { earlyEndTravel } from '@/api/hrm/travel'
|
||||
|
||||
export default {
|
||||
name: 'TravelDetail',
|
||||
@@ -53,7 +78,11 @@ export default {
|
||||
BizDetailContainer,
|
||||
FilePreview
|
||||
},
|
||||
name: 'HrmTravelDetail',
|
||||
data() {
|
||||
return {
|
||||
earlyEndLoading: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentBizId () {
|
||||
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)
|
||||
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>
|
||||
|
||||
@@ -375,4 +438,17 @@ export default {
|
||||
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>
|
||||
|
||||
Reference in New Issue
Block a user