OfficeSystem/pages/verify/list/index.vue
2025-11-13 17:18:37 +08:00

243 lines
5.2 KiB
Vue

<template>
<view class="verify-page">
<view class="tabs-wrapper">
<uv-tabs :list="tabs" :current="currentTab" @click="onTabClick"></uv-tabs>
</view>
<scroll-view class="list-scroll" scroll-y @scrolltolower="loadMore">
<view class="card" v-for="item in displayList" :key="item.id" @click="goDetail(item)">
<view class="card-header">
<view class="left">
<text class="badge">申请延期</text>
<text class="sub">所属项目 · {{ item.projectName || '—' }}</text>
</view>
<view class="right">
<uv-tags :text="statusText(item.status)" :type="statusType(item.status)" size="mini"></uv-tags>
</view>
</view>
<view class="card-body">
<text class="remark" v-if="item.createRemark">{{ item.createRemark }}</text>
<view class="row">
<text class="label">截止时间:</text>
<text class="value">{{ item.expireTime || '—' }}</text>
</view>
<view class="row">
<text class="label">申请人:</text>
<text class="value">{{ item.createName || '—' }}</text>
</view>
</view>
<view class="card-footer">
<uv-button
v-if="item.status === '3'"
type="primary"
size="small"
text="去处理"
@click.stop="goHandle(item)"
/>
<uv-button
v-else
type="info"
size="small"
:text="statusText(item.status)"
:plain="true"
:disabled="true"
/>
</view>
</view>
<view class="empty" v-if="!loading && displayList.length === 0">
<text>暂无数据</text>
</view>
<view class="loading" v-if="loading">
<text>加载中...</text>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue';
import { getVerifyList } from '@/api';
const tabs = [
{ name: '待我处理', value: 'pending' },
{ name: '我已处理', value: 'done' }
];
const currentTab = ref(0);
const pageNum = ref(1);
const pageSize = ref(20);
const total = ref(0);
const rawList = ref([]);
const loading = ref(false);
const bstType = ref('UPDATE_TASK');
function statusText(s) {
if (s === '1') return '已通过';
if (s === '2') return '已驳回';
return '待处理';
}
function statusType(s) {
if (s === '1') return 'success';
if (s === '2') return 'error';
return 'warning';
}
const displayList = computed(() => {
if (currentTab.value === 0) {
return rawList.value.filter(i => String(i.status) === '3');
}
return rawList.value.filter(i => String(i.status) !== '3');
});
const safeParseExpire = (dataField) => {
if (!dataField) return '';
try {
if (typeof dataField === 'string') {
return JSON.parse(dataField)?.expireTime || '';
}
return dataField.expireTime || '';
} catch (e) {
return '';
}
};
const fetchList = async () => {
if (loading.value) return;
loading.value = true;
try {
const res = await getVerifyList({
pageNum: pageNum.value,
pageSize: pageSize.value,
orderByColumn: 'createTime',
isAsc: 'descending',
bstType: bstType.value
});
const rows = res?.rows || [];
total.value = res?.total || 0;
const mapped = rows.map(r => ({
...r,
expireTime: safeParseExpire(r.data)
}));
if (pageNum.value === 1) {
rawList.value = mapped;
} else {
rawList.value = rawList.value.concat(mapped);
}
} finally {
loading.value = false;
}
};
const loadMore = () => {
if (rawList.value.length >= total.value) return;
pageNum.value += 1;
fetchList();
};
const onTabClick = (tab) => {
currentTab.value = tab.index;
};
const goHandle = (item) => {
// 预留处理入口
uni.showToast({ title: '去处理', icon: 'none' });
};
const goDetail = (item) => {
// 可跳转到任务详情或审批详情
};
onMounted(() => {
// 读取路由参数
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const options = currentPage?.options || {};
if (options.bstType) {
bstType.value = options.bstType;
}
fetchList();
});
</script>
<style lang="scss" scoped>
.verify-page {
width: 100%;
background: #f5f5f5;
display: flex;
flex-direction: column;
}
.tabs-wrapper {
background: #fff;
}
.list-scroll {
flex: 1;
}
.card {
background: #fff;
margin: 12px 12px 0 12px;
border-radius: 12px;
padding: 12px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
}
.left {
display: flex;
align-items: center;
gap: 8px;
}
.badge {
font-size: 14px;
font-weight: 600;
color: #333;
}
.sub {
font-size: 12px;
color: #999;
}
.card-body {
display: flex;
flex-direction: column;
gap: 6px;
margin-top: 4px;
}
.remark {
font-size: 13px;
color: #333;
line-height: 1.6;
}
.row {
display: flex;
font-size: 12px;
color: #666;
}
.label {
width: 70px;
flex-shrink: 0;
}
.value {
color: #333;
}
.card-footer {
margin-top: 10px;
display: flex;
justify-content: flex-start;
}
.empty, .loading {
text-align: center;
color: #999;
font-size: 12px;
padding: 16px 0;
}
</style>