添加我的审核,我的申请提前结束

This commit is contained in:
2026-04-22 16:11:43 +08:00
parent 8b78e82a80
commit 50527f68e0
4 changed files with 81 additions and 18 deletions

View File

@@ -40,7 +40,6 @@ public class HrmTravelReqController extends BaseController {
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo<HrmTravelReqVo> list(HrmTravelReqBo bo, PageQuery pageQuery) { public TableDataInfo<HrmTravelReqVo> list(HrmTravelReqBo bo, PageQuery pageQuery) {
bo.setCreateBy(String.valueOf(LoginHelper.getUserId()));
bo.setCreateBy(LoginHelper.getUsername()); bo.setCreateBy(LoginHelper.getUsername());
return service.queryPageList(bo, pageQuery); return service.queryPageList(bo, pageQuery);
} }
@@ -84,7 +83,7 @@ public class HrmTravelReqController extends BaseController {
@GetMapping("/all") @GetMapping("/all")
public R<List<HrmTravelReqVo>> all(HrmTravelReqBo bo) { public R<List<HrmTravelReqVo>> all(HrmTravelReqBo bo) {
bo.setCreateBy(String.valueOf(LoginHelper.getUserId())); bo.setCreateBy(LoginHelper.getUsername());
return R.ok(service.queryList(bo)); return R.ok(service.queryList(bo));
} }
} }

View File

@@ -18,5 +18,7 @@ public class HrmMyApplyVo implements Serializable {
private String title; private String title;
private String status; private String status;
private Date createTime; private Date createTime;
private Date endTime;
private Date actualEndTime;
private String remark; private String remark;
} }

View File

@@ -66,15 +66,25 @@
</el-table-column> </el-table-column>
<el-table-column label="状态" min-width="110"> <el-table-column label="状态" min-width="110">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="statusType(scope.row.status)" size="small">{{ statusText(scope.row.status) }}</el-tag> <el-tag :type="statusType(scope.row)" size="small">{{ statusText(scope.row) }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="发起时间" prop="createTime" min-width="160"> <el-table-column label="发起时间" prop="createTime" min-width="160">
<template slot-scope="scope">{{ formatDate(scope.row.createTime) }}</template> <template slot-scope="scope">{{ formatDate(scope.row.createTime) }}</template>
</el-table-column> </el-table-column>
<el-table-column label="操作" min-width="120" fixed="right"> <el-table-column label="操作" min-width="180" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" size="mini" @click="goDetail(scope.row)">详情</el-button> <el-button type="text" size="mini" @click="goDetail(scope.row)">详情</el-button>
<el-button
v-if="showEarlyEndButton(scope.row)"
type="text"
size="mini"
style="color: #e6a23c"
:loading="earlyEndLoadingId === scope.row.bizId"
@click.stop="handleEarlyEnd(scope.row)"
>
提前结束
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -97,6 +107,7 @@
<script> <script>
import { listMyApply } from '@/api/hrm/myApply' import { listMyApply } from '@/api/hrm/myApply'
import { earlyEndTravel } from '@/api/hrm/travel'
import applyTypeMinix from '@/views/hrm/minix/applyTypeMinix.js' import applyTypeMinix from '@/views/hrm/minix/applyTypeMinix.js'
export default { export default {
@@ -105,6 +116,7 @@ export default {
data () { data () {
return { return {
loading: false, loading: false,
earlyEndLoadingId: null,
list: [], list: [],
total: 0, total: 0,
summary: { summary: {
@@ -128,11 +140,31 @@ export default {
getRowTitle (row) { getRowTitle (row) {
return row.title || row.remark || '-' return row.title || row.remark || '-'
}, },
statusText (status) { isTravelCompleted (row) {
if (!row || row.bizType !== 'travel') return false
const endTime = row.endTime ? new Date(row.endTime).getTime() : 0
const now = Date.now()
return Boolean(row.actualEndTime) || (endTime && endTime <= now)
},
showEarlyEndButton (row) {
if (!row || row.bizType !== 'travel') return false
if (row.actualEndTime) return false
const endTime = row.endTime ? new Date(row.endTime).getTime() : 0
return row.status === 'approved' && endTime > Date.now()
},
statusText (row) {
const status = row?.status
if (row?.bizType === 'travel' && status === 'approved') {
return this.isTravelCompleted(row) ? '已完成' : '进行中'
}
const map = { draft: '草稿', running: '审批中', pending: '审批中', approved: '已通过', rejected: '已驳回', revoked: '已撤销', finished: '已完成' } const map = { draft: '草稿', running: '审批中', pending: '审批中', approved: '已通过', rejected: '已驳回', revoked: '已撤销', finished: '已完成' }
return map[status] || status || '-' return map[status] || status || '-'
}, },
statusType (status) { statusType (row) {
const status = row?.status
if (row?.bizType === 'travel' && status === 'approved') {
return this.isTravelCompleted(row) ? 'success' : 'warning'
}
const map = { draft: 'info', running: 'warning', pending: 'warning', approved: 'success', rejected: 'danger', revoked: 'danger', finished: 'success' } const map = { draft: 'info', running: 'warning', pending: 'warning', approved: 'success', rejected: 'danger', revoked: 'danger', finished: 'success' }
return map[status] || 'info' return map[status] || 'info'
}, },
@@ -163,8 +195,8 @@ export default {
this.list = res.rows || [] this.list = res.rows || []
this.total = res.total || 0 this.total = res.total || 0
this.summary.total = res.total || 0 this.summary.total = res.total || 0
this.summary.running = (res.rows || []).filter(i => ['running', 'pending'].includes(i.status)).length this.summary.running = (res.rows || []).filter(i => ['running', 'pending'].includes(i.status) || (i.bizType === 'travel' && i.status === 'approved' && !this.isTravelCompleted(i))).length
this.summary.approved = (res.rows || []).filter(i => i.status === 'approved').length this.summary.approved = (res.rows || []).filter(i => i.status === 'approved' && !(i.bizType === 'travel' && !this.isTravelCompleted(i))).length
} catch (err) { } catch (err) {
console.error('加载我的申请失败:', err) console.error('加载我的申请失败:', err)
this.$message.error('加载我的申请失败') this.$message.error('加载我的申请失败')
@@ -183,6 +215,24 @@ export default {
this.query.pageNum = val this.query.pageNum = val
this.loadList() this.loadList()
}, },
async handleEarlyEnd (row) {
this.$confirm('确认提前结束本次出差吗?结束后的实际时间将记录为当前时间。', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
this.earlyEndLoadingId = row.bizId
try {
await earlyEndTravel(row.bizId)
this.$message.success('提前结束成功')
await this.loadList()
} catch (error) {
this.$message.error(error.message || '提前结束失败')
} finally {
this.earlyEndLoadingId = null
}
}).catch(() => {})
},
goDetail (row) { goDetail (row) {
if (!row) return if (!row) return
const routeMap = { const routeMap = {

View File

@@ -15,7 +15,6 @@
</el-button> </el-button>
<span class="hint-text">提前结束将把当前时间记录为实际结束时间</span> <span class="hint-text">提前结束将把当前时间记录为实际结束时间</span>
</div> </div>
<!-- ===== 新增显示已提前结束的信息 ===== -->
<div v-if="detail.actualEndTime" class="early-end-info"> <div v-if="detail.actualEndTime" class="early-end-info">
<el-alert <el-alert
type="info" type="info"
@@ -26,6 +25,16 @@
</template> </template>
</el-alert> </el-alert>
</div> </div>
<div v-else-if="isTravelCompleted(detail)" class="early-end-info">
<el-alert
type="success"
:closable="false"
show-icon>
<template slot="default">
该出差已完成
</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">
@@ -95,14 +104,19 @@ 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())}`
}, },
// 新增:处理提前结束 isTravelCompleted (detail) {
if (!detail) return false
const endTime = detail.endTime ? new Date(detail.endTime).getTime() : 0
const now = Date.now()
return Boolean(detail.actualEndTime) || (endTime && endTime <= now)
},
showEarlyEndButton(detail) { showEarlyEndButton(detail) {
if (!detail) return false if (!detail) return false
// 已经提前结束的不显示
if (detail.actualEndTime) return false if (detail.actualEndTime) return false
// 只有已通过或进行中状态才显示
const status = detail.status const status = detail.status
return status === 'approved' || status === 'in_progress' const endTime = detail.endTime ? new Date(detail.endTime).getTime() : 0
const now = Date.now()
return status === 'approved' && endTime > now
}, },
handleEarlyEnd() { handleEarlyEnd() {
@@ -116,10 +130,8 @@ export default {
const bizId = this.currentBizId const bizId = this.currentBizId
await earlyEndTravel(bizId) await earlyEndTravel(bizId)
this.$message.success('提前结束成功') this.$message.success('提前结束成功')
// 刷新页面 this.$emit('refresh')
setTimeout(() => { this.$forceUpdate()
location.reload()
}, 1000)
} catch (error) { } catch (error) {
this.$message.error(error.message || '提前结束失败') this.$message.error(error.message || '提前结束失败')
} finally { } finally {