2025-12-30 13:47:53 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="hrm-page">
|
|
|
|
|
|
<!-- 发起申请模块 -->
|
|
|
|
|
|
<section class="apply-section">
|
|
|
|
|
|
<div class="section-header">
|
|
|
|
|
|
<h3 class="section-title">发起申请</h3>
|
|
|
|
|
|
<p class="section-desc">选择申请类型,快速发起新的申请流程</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="apply-cards">
|
|
|
|
|
|
<el-card
|
|
|
|
|
|
v-for="item in applyTypes"
|
|
|
|
|
|
:key="item.key"
|
|
|
|
|
|
class="apply-card"
|
|
|
|
|
|
shadow="hover"
|
|
|
|
|
|
@click.native="goCreate(item.key)"
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
|
<div class="card-title">{{ item.title }}</div>
|
|
|
|
|
|
<div class="card-desc">{{ item.desc }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="card-action">
|
|
|
|
|
|
<el-button type="primary" size="small" icon="el-icon-plus">发起</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 申请历史模块 -->
|
|
|
|
|
|
<section class="history-section">
|
|
|
|
|
|
<div class="section-header">
|
|
|
|
|
|
<h3 class="section-title">我的申请</h3>
|
|
|
|
|
|
<div class="section-actions">
|
|
|
|
|
|
<el-select
|
|
|
|
|
|
v-model="historyQuery.type"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
placeholder="申请类型"
|
|
|
|
|
|
clearable
|
|
|
|
|
|
style="width: 120px; margin-right: 8px"
|
|
|
|
|
|
@change="loadHistory"
|
|
|
|
|
|
>
|
|
|
|
|
|
<el-option label="全部" value="" />
|
|
|
|
|
|
<el-option label="请假" value="leave" />
|
|
|
|
|
|
<el-option label="出差" value="travel" />
|
|
|
|
|
|
<el-option label="用印" value="seal" />
|
|
|
|
|
|
<el-option label="报销" value="reimburse" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
<el-select
|
|
|
|
|
|
v-model="historyQuery.status"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
placeholder="状态"
|
|
|
|
|
|
clearable
|
|
|
|
|
|
style="width: 120px; margin-right: 8px"
|
|
|
|
|
|
@change="loadHistory"
|
|
|
|
|
|
>
|
|
|
|
|
|
<el-option label="全部" value="" />
|
|
|
|
|
|
<el-option label="草稿" value="draft" />
|
2026-01-05 14:38:22 +08:00
|
|
|
|
<el-option label="审批中" value="running" />
|
2025-12-30 13:47:53 +08:00
|
|
|
|
<el-option label="已通过" value="approved" />
|
|
|
|
|
|
<el-option label="已驳回" value="rejected" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
<el-button size="small" icon="el-icon-refresh" @click="loadHistory">刷新</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<el-card class="history-card" shadow="never">
|
|
|
|
|
|
<el-table
|
|
|
|
|
|
:data="historyList"
|
|
|
|
|
|
v-loading="historyLoading"
|
|
|
|
|
|
stripe
|
|
|
|
|
|
@row-dblclick="handleRowClick"
|
|
|
|
|
|
>
|
|
|
|
|
|
<el-table-column label="申请类型" min-width="100">
|
|
|
|
|
|
<template slot-scope="scope">
|
2025-12-30 17:49:45 +08:00
|
|
|
|
<el-tag :type="getTypeTagType(scope.row.bizType)">{{ getTypeText(scope.row.bizType) }}</el-tag>
|
2025-12-30 13:47:53 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2026-01-03 14:32:47 +08:00
|
|
|
|
<!-- <el-table-column label="申请人" min-width="120">
|
2025-12-30 13:47:53 +08:00
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
|
{{ formatEmpDisplay(scope.row.startUserId) }}
|
|
|
|
|
|
</template>
|
2026-01-03 14:32:47 +08:00
|
|
|
|
</el-table-column> -->
|
2025-12-30 13:47:53 +08:00
|
|
|
|
<el-table-column label="类型/目的" min-width="140">
|
|
|
|
|
|
<template slot-scope="scope">
|
2026-01-05 14:38:22 +08:00
|
|
|
|
<el-input v-model="scope.row.remark" placeholder="请输入类型/目的便于审批或查看" @change="handleRemarkChange(scope.row)"></el-input>
|
|
|
|
|
|
<!-- {{ getTypeDetail(scope.row) }} -->
|
2025-12-30 13:47:53 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
2026-01-03 14:32:47 +08:00
|
|
|
|
<!-- <el-table-column label="开始时间" prop="startTime" min-width="160">
|
2025-12-30 13:47:53 +08:00
|
|
|
|
<template slot-scope="scope">{{ formatDate(scope.row.startTime) }}</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="结束时间" prop="endTime" min-width="160">
|
|
|
|
|
|
<template slot-scope="scope">{{ formatDate(scope.row.endTime) }}</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="时长" min-width="100">
|
|
|
|
|
|
<template slot-scope="scope">{{ formatDuration(scope.row) }}</template>
|
2026-01-03 14:32:47 +08:00
|
|
|
|
</el-table-column> -->
|
2025-12-30 13:47:53 +08:00
|
|
|
|
<el-table-column label="状态" prop="status" min-width="110">
|
|
|
|
|
|
<template slot-scope="scope">
|
2025-12-30 17:49:45 +08:00
|
|
|
|
<el-tag :type="statusType(scope.row.status)">{{ statusText(scope.row.status) }}</el-tag>
|
2025-12-30 13:47:53 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="申请时间" prop="createTime" min-width="160">
|
|
|
|
|
|
<template slot-scope="scope">{{ formatDate(scope.row.createTime) }}</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="操作" min-width="120" fixed="right">
|
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
|
<el-button size="mini" type="text" @click="goDetail(scope.row)">详情</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
<div class="pagination-wrapper">
|
|
|
|
|
|
<el-pagination
|
|
|
|
|
|
:current-page="historyQuery.pageNum"
|
|
|
|
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
|
|
|
|
:page-size="historyQuery.pageSize"
|
|
|
|
|
|
:total="historyTotal"
|
|
|
|
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
|
|
|
|
@size-change="handleSizeChange"
|
|
|
|
|
|
@current-change="handlePageChange"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
2026-01-05 14:38:22 +08:00
|
|
|
|
import { listMyFlowInstance, updateFlowInstance } from '@/api/hrm/flow'
|
2025-12-30 13:47:53 +08:00
|
|
|
|
import { getEmployeeByUserId } from '@/api/hrm/employee'
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: 'HrmApply',
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
currentEmp: null,
|
|
|
|
|
|
applyTypes: [
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'leave',
|
|
|
|
|
|
title: '请假申请',
|
|
|
|
|
|
desc: '申请各类假期,包括年假、病假、事假等',
|
|
|
|
|
|
icon: 'el-icon-calendar',
|
|
|
|
|
|
color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'travel',
|
|
|
|
|
|
title: '出差申请',
|
|
|
|
|
|
desc: '申请出差,包括目的地、时间、费用等信息',
|
|
|
|
|
|
icon: 'el-icon-location',
|
|
|
|
|
|
color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'seal',
|
|
|
|
|
|
title: '用印申请',
|
|
|
|
|
|
desc: '申请使用印章,上传文件并指定盖章位置',
|
|
|
|
|
|
icon: 'el-icon-stamp',
|
|
|
|
|
|
color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'reimburse',
|
|
|
|
|
|
title: '报销申请',
|
|
|
|
|
|
desc: '申请费用报销,包括单据、理由、金额等信息',
|
|
|
|
|
|
icon: 'el-icon-money',
|
|
|
|
|
|
color: 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)'
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
historyList: [],
|
|
|
|
|
|
historyLoading: false,
|
|
|
|
|
|
historyTotal: 0,
|
|
|
|
|
|
historyQuery: {
|
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
|
type: '',
|
|
|
|
|
|
status: ''
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
created() {
|
|
|
|
|
|
this.loadCurrentEmployee()
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
formatEmpLabel(emp) {
|
|
|
|
|
|
if (!emp) return '未指定'
|
|
|
|
|
|
const name = emp.empName || emp.nickName || emp.userName || ''
|
|
|
|
|
|
const no = emp.empNo ? ` · ${emp.empNo}` : ''
|
|
|
|
|
|
const dept = emp.deptName ? ` · ${emp.deptName}` : ''
|
|
|
|
|
|
return `${name || '员工'}${no}${dept}`.trim()
|
|
|
|
|
|
},
|
2026-01-05 14:38:22 +08:00
|
|
|
|
handleRemarkChange(row) {
|
|
|
|
|
|
updateFlowInstance(row).then(response => {
|
|
|
|
|
|
if (response.code === 200) {
|
|
|
|
|
|
this.$message({
|
|
|
|
|
|
message: '更新成功',
|
|
|
|
|
|
type: 'success'
|
|
|
|
|
|
})
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message({
|
|
|
|
|
|
message: `更新失败: ${response.msg || '未知错误'}`,
|
|
|
|
|
|
type: 'error'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
2025-12-30 13:47:53 +08:00
|
|
|
|
formatEmpDisplay(userId) {
|
|
|
|
|
|
// The API returns startUserId, which is a user ID, not an empId.
|
|
|
|
|
|
// We can display the current user's name if the ID matches.
|
|
|
|
|
|
if (this.currentEmp && String(this.currentEmp.userId) === String(userId)) {
|
|
|
|
|
|
return this.formatEmpLabel(this.currentEmp)
|
|
|
|
|
|
}
|
|
|
|
|
|
return userId ? `用户ID:${userId}` : '未指定'
|
|
|
|
|
|
},
|
|
|
|
|
|
formatDuration(row) {
|
|
|
|
|
|
if (row.hours) return `${row.hours}h`
|
|
|
|
|
|
if (row.startTime && row.endTime) {
|
|
|
|
|
|
const ms = new Date(row.endTime).getTime() - new Date(row.startTime).getTime()
|
|
|
|
|
|
if (ms > 0) return `${(ms / 3600000).toFixed(1)}h`
|
|
|
|
|
|
}
|
|
|
|
|
|
return '-'
|
|
|
|
|
|
},
|
|
|
|
|
|
statusText(status) {
|
2025-12-30 17:49:45 +08:00
|
|
|
|
const map = { running: '审批中', draft: '草稿', approved: '已通过', rejected: '已驳回', finished: '已完成' }
|
2025-12-30 13:47:53 +08:00
|
|
|
|
return map[status] || status || '-'
|
|
|
|
|
|
},
|
|
|
|
|
|
statusType(status) {
|
|
|
|
|
|
if (!status) return 'info'
|
2025-12-30 17:49:45 +08:00
|
|
|
|
const map = { running: 'warning', draft: 'info', approved: 'success', rejected: 'danger', finished: 'success' }
|
2025-12-30 13:47:53 +08:00
|
|
|
|
return map[status] || 'info'
|
|
|
|
|
|
},
|
|
|
|
|
|
formatDate(val) {
|
|
|
|
|
|
if (!val) return ''
|
|
|
|
|
|
const d = new Date(val)
|
|
|
|
|
|
const p = n => (n < 10 ? `0${n}` : n)
|
|
|
|
|
|
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`
|
|
|
|
|
|
},
|
|
|
|
|
|
getTypeText(type) {
|
|
|
|
|
|
const map = { leave: '请假', travel: '出差', seal: '用印', reimburse: '报销' }
|
|
|
|
|
|
return map[type] || type || '-'
|
|
|
|
|
|
},
|
|
|
|
|
|
getTypeTagType(type) {
|
|
|
|
|
|
const map = { leave: 'primary', travel: 'success', seal: 'warning', reimburse: 'danger' }
|
|
|
|
|
|
return map[type] || 'info'
|
|
|
|
|
|
},
|
|
|
|
|
|
getTypeDetail(row) {
|
|
|
|
|
|
// This detail might need to be fetched or be part of the process variables
|
|
|
|
|
|
// For now, we display the process name as a fallback.
|
|
|
|
|
|
return row.procDefName || '-'
|
|
|
|
|
|
},
|
|
|
|
|
|
goCreate(key) {
|
|
|
|
|
|
const pathMap = {
|
|
|
|
|
|
leave: '/hrm/HrmLeaveRequest',
|
|
|
|
|
|
travel: '/hrm/HrmTravelRequest',
|
|
|
|
|
|
seal: '/hrm/HrmSealRequest',
|
|
|
|
|
|
reimburse: '/hrm/HrmReimburseRequest'
|
|
|
|
|
|
}
|
|
|
|
|
|
const path = pathMap[key]
|
|
|
|
|
|
if (path) {
|
|
|
|
|
|
this.$router.push(path)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message.warning('该申请类型暂未实现')
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
goDetail(row) {
|
2025-12-30 17:49:45 +08:00
|
|
|
|
if (!row || !row.bizId || !row.bizType) {
|
2025-12-30 13:47:53 +08:00
|
|
|
|
this.$message.warning('缺少businessKey,无法打开详情')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-12-30 17:49:45 +08:00
|
|
|
|
const { bizId, bizType: type } = row
|
2025-12-30 13:47:53 +08:00
|
|
|
|
if (!bizId) {
|
|
|
|
|
|
this.$message.warning('businessKey格式不正确,无法解析业务ID')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const pathMap = {
|
|
|
|
|
|
leave: '/hrm/HrmLeaveDetail',
|
|
|
|
|
|
travel: '/hrm/HrmTravelDetail',
|
|
|
|
|
|
seal: '/hrm/HrmSealDetail',
|
|
|
|
|
|
reimburse: '/hrm/HrmReimburseDetail'
|
|
|
|
|
|
}
|
|
|
|
|
|
const routePath = pathMap[type]
|
|
|
|
|
|
|
|
|
|
|
|
if (routePath) {
|
|
|
|
|
|
this.$router.push({
|
|
|
|
|
|
path: routePath,
|
|
|
|
|
|
query: { bizId: bizId }
|
|
|
|
|
|
})
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message.warning('无法确定申请类型对应的详情页面')
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
handleRowClick(row) {
|
|
|
|
|
|
this.goDetail(row)
|
|
|
|
|
|
},
|
|
|
|
|
|
async loadCurrentEmployee() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const userId = this.$store?.state?.user?.id
|
|
|
|
|
|
if (!userId) {
|
|
|
|
|
|
this.$message.warning('无法获取当前用户信息,请重新登录')
|
|
|
|
|
|
this.loadHistory() // Still try to load history if user is not found
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const res = await getEmployeeByUserId(userId)
|
|
|
|
|
|
if (res.code === 200 && res.data) {
|
|
|
|
|
|
this.currentEmp = res.data
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message.warning('未找到当前用户对应的员工信息')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('加载员工信息失败', err)
|
|
|
|
|
|
this.$message.error('加载员工信息失败')
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
this.loadHistory()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
async loadHistory() {
|
|
|
|
|
|
this.historyLoading = true
|
|
|
|
|
|
try {
|
|
|
|
|
|
const params = {
|
|
|
|
|
|
pageNum: this.historyQuery.pageNum,
|
|
|
|
|
|
pageSize: this.historyQuery.pageSize,
|
|
|
|
|
|
bizType: this.historyQuery.type || undefined, // 业务类型:leave/travel/seal/reimburse
|
2026-01-05 14:38:22 +08:00
|
|
|
|
status: this.historyQuery.status || undefined // 状态:draft/running/approved/rejected
|
2025-12-30 13:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
const res = await listMyFlowInstance(params)
|
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
|
this.historyList = res.rows || []
|
|
|
|
|
|
this.historyTotal = res.total || 0
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.historyList = []
|
|
|
|
|
|
this.historyTotal = 0
|
|
|
|
|
|
this.$message.error(res.msg || '加载申请历史失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('加载申请历史失败:', err)
|
|
|
|
|
|
this.$message.error('加载申请历史失败')
|
|
|
|
|
|
this.historyList = []
|
|
|
|
|
|
this.historyTotal = 0
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
this.historyLoading = false
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
handleSizeChange(val) {
|
|
|
|
|
|
this.historyQuery.pageSize = val
|
|
|
|
|
|
this.historyQuery.pageNum = 1
|
|
|
|
|
|
this.loadHistory()
|
|
|
|
|
|
},
|
|
|
|
|
|
handlePageChange(val) {
|
|
|
|
|
|
this.historyQuery.pageNum = val
|
|
|
|
|
|
this.loadHistory()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.hrm-page {
|
|
|
|
|
|
padding: 20px 24px 32px;
|
|
|
|
|
|
background: #f8f9fb;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
.section-title {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
.section-desc {
|
|
|
|
|
|
margin: 4px 0 0;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
}
|
|
|
|
|
|
.section-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.apply-section {
|
|
|
|
|
|
margin-bottom: 32px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.apply-cards {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(4, 1fr);
|
|
|
|
|
|
gap: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.apply-card {
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
border: 1px solid #e6e8ed;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
transform: translateY(-4px);
|
|
|
|
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
|
|
|
|
border-color: #409eff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.card-content {
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
.card-title {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.card-desc {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.card-action {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-section {
|
|
|
|
|
|
.history-card {
|
|
|
|
|
|
border: 1px solid #d7d9df;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-wrapper {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 1600px) {
|
|
|
|
|
|
.apply-cards {
|
|
|
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.apply-cards {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|