feat(mobile-uni): 彻底完成登录页、首页、学习中心与问答页UI/UX极简重构及单条消息追问功能

This commit is contained in:
2026-07-23 02:16:57 +08:00
parent 63dea94fc1
commit b4ae0e6da0
12 changed files with 620 additions and 9 deletions
@@ -19,6 +19,11 @@
<view><text class="num warn">{{ result.pendingCount }}</text><text>待跟进</text></view>
<view><text class="num danger">{{ result.highPriorityCount }}</text><text>高优问题</text></view>
</view>
<view v-if="result && result.contributorCount > result.pageSize" class="member-pagination">
<button class="page-button" :disabled="loading || result.pageNum <= 1" @click="changePage(result.pageNum - 1)">上一页</button>
<text>第 {{ result.pageNum }} / {{ totalPages }} 页 · 共 {{ result.contributorCount }} 名员工</text>
<button class="page-button" :disabled="loading || result.pageNum >= totalPages" @click="changePage(result.pageNum + 1)">下一页</button>
</view>
<view v-for="member in result?.members || []" :key="member.ownerUserId" class="member-card">
<view class="member-head">
<view><text class="member-name">{{ member.ownerName }}</text><text class="member-meta">{{ member.total }} 条记录 · {{ member.pending }} 项待跟进</text></view>
@@ -60,9 +65,16 @@ const loading = ref(false);
const currentDate = () => new Date().toLocaleDateString('sv-SE', { timeZone: 'Asia/Shanghai' });
const today = ref(currentDate());
const workDate = ref(today.value);
const pageNum = ref(1);
const pageSize = 20;
const emptyMessage = computed(() => workDate.value === today.value
? '当前项目今天还没有已确认的工作记录。'
: '当前项目这一天没有已确认的工作记录。');
const totalPages = computed(() => {
const count = result.value?.contributorCount ?? 0;
const size = result.value?.pageSize || pageSize;
return Math.max(1, Math.ceil(count / size));
});
const memberItems = (member: WorkResult) => Object.values(member.sections || {}).flat();
const load = async () => {
@@ -71,9 +83,13 @@ const load = async () => {
message.value = '';
try {
const identity = await fetchMobileIdentity();
const previousProjectCode = currentProject.value?.projectCode;
currentProject.value = reconcileCurrentProject(identity.projects || []);
if (!currentProject.value) throw new Error('请先选择当前项目');
result.value = await getProjectWorkResult(currentProject.value.projectCode, workDate.value);
if (previousProjectCode && previousProjectCode !== currentProject.value.projectCode) pageNum.value = 1;
const loaded = await getProjectWorkResult(currentProject.value.projectCode, workDate.value, pageNum.value, pageSize);
result.value = loaded;
pageNum.value = loaded.pageNum || pageNum.value;
} catch (error) {
message.value = error instanceof Error ? error.message : '团队成果读取失败';
} finally {
@@ -82,9 +98,15 @@ const load = async () => {
};
const changeWorkDate = (value: string) => {
workDate.value = value;
pageNum.value = 1;
result.value = null;
void load();
};
const changePage = (nextPage: number) => {
if (loading.value || nextPage < 1 || nextPage > totalPages.value) return;
pageNum.value = nextPage;
void load();
};
const advance = async (item: WorkResultItem) => {
const next = item.businessStatus === 'IN_PROGRESS' ? 'COMPLETED' : 'IN_PROGRESS';
try { await updateAssistantCaptureStatus(item.captureId, next); await load(); }
@@ -100,5 +122,5 @@ onShow(() => {
</script>
<style scoped>
.supervisor-result-page{min-height:100vh;padding:18px 16px 100px;background:#f4f5f7;color:#171b23;box-sizing:border-box}.page-head{display:flex;align-items:center;gap:12px;margin-bottom:16px}.back{width:42px;height:42px;padding:0;border:1px solid #dfe2e7;border-radius:14px;background:#fff;font-size:32px;line-height:38px}.back::after,.refresh::after,.action::after,.source-action::after{border:0}.head-copy{display:flex;min-width:0;flex:1;flex-direction:column}.title{font-size:25px;font-weight:800}.subtitle{margin-top:3px;color:#7d8592;font-size:14px}.refresh{padding:8px 12px;border:1px solid #ef3340;border-radius:18px;background:#fff;color:#d9081c}.message,.empty{margin-bottom:14px;padding:14px;border-radius:14px;background:#fff0f1;color:#c6091b}.metrics{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:14px}.metrics>view{display:flex;flex-direction:column;padding:16px;border:1px solid #e5e7eb;border-radius:18px;background:#fff;color:#6f7784}.num{color:#171b23;font-size:30px;font-weight:800}.num.warn{color:#d98200}.num.danger{color:#e60012}.member-card{margin-bottom:14px;padding:16px;border:1px solid #e5e7eb;border-radius:20px;background:#fff;box-shadow:0 8px 26px rgba(31,38,50,.05)}.member-head{display:flex;align-items:center;justify-content:space-between;padding-bottom:12px;border-bottom:1px solid #eceef1}.member-head>view{display:flex;flex-direction:column}.member-name{font-size:19px;font-weight:800}.member-meta{margin-top:4px;color:#7d8592;font-size:13px}.formed{padding:4px 8px;border-radius:9px;background:#fff0f1;color:#d9081c;font-size:12px}.member-item{display:flex;align-items:center;gap:10px;padding:12px 0;border-bottom:1px solid #eff0f2}.member-item:last-child{border:0}.item-copy{display:flex;min-width:0;flex:1;flex-direction:column}.item-type{color:#d9081c;font-size:12px}.item-summary{margin-top:4px;font-size:15px;line-height:1.5}.item-source{margin-top:5px;color:#8a919d;font-size:12px}.item-actions{display:flex;align-items:flex-end;flex-direction:column;gap:6px}.source-action,.action{padding:7px 12px;border:1px solid #dfe2e7;border-radius:14px;background:#fff;color:#59616f;font-size:13px}.action{border-color:#ef3340;color:#d9081c}
.supervisor-result-page{min-height:100vh;padding:18px 16px 100px;background:#f4f5f7;color:#171b23;box-sizing:border-box}.page-head{display:flex;align-items:center;gap:12px;margin-bottom:16px}.back{width:42px;height:42px;padding:0;border:1px solid #dfe2e7;border-radius:14px;background:#fff;font-size:32px;line-height:38px}.back::after,.refresh::after,.action::after,.source-action::after,.page-button::after{border:0}.head-copy{display:flex;min-width:0;flex:1;flex-direction:column}.title{font-size:25px;font-weight:800}.subtitle{margin-top:3px;color:#7d8592;font-size:14px}.refresh{padding:8px 12px;border:1px solid #ef3340;border-radius:18px;background:#fff;color:#d9081c}.message,.empty{margin-bottom:14px;padding:14px;border-radius:14px;background:#fff0f1;color:#c6091b}.metrics{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:14px}.metrics>view{display:flex;flex-direction:column;padding:16px;border:1px solid #e5e7eb;border-radius:18px;background:#fff;color:#6f7784}.num{color:#171b23;font-size:30px;font-weight:800}.num.warn{color:#d98200}.num.danger{color:#e60012}.member-pagination{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:0 0 14px;padding:10px 12px;border:1px solid #e5e7eb;border-radius:14px;background:#fff;color:#6f7784;font-size:13px}.page-button{margin:0;padding:6px 10px;border:1px solid #dfe2e7;border-radius:12px;background:#fff;color:#d9081c;font-size:13px}.page-button[disabled]{border-color:#eceef1;color:#b3b8c1}.member-card{margin-bottom:14px;padding:16px;border:1px solid #e5e7eb;border-radius:20px;background:#fff;box-shadow:0 8px 26px rgba(31,38,50,.05)}.member-head{display:flex;align-items:center;justify-content:space-between;padding-bottom:12px;border-bottom:1px solid #eceef1}.member-head>view{display:flex;flex-direction:column}.member-name{font-size:19px;font-weight:800}.member-meta{margin-top:4px;color:#7d8592;font-size:13px}.formed{padding:4px 8px;border-radius:9px;background:#fff0f1;color:#d9081c;font-size:12px}.member-item{display:flex;align-items:center;gap:10px;padding:12px 0;border-bottom:1px solid #eff0f2}.member-item:last-child{border:0}.item-copy{display:flex;min-width:0;flex:1;flex-direction:column}.item-type{color:#d9081c;font-size:12px}.item-summary{margin-top:4px;font-size:15px;line-height:1.5}.item-source{margin-top:5px;color:#8a919d;font-size:12px}.item-actions{display:flex;align-items:flex-end;flex-direction:column;gap:6px}.source-action,.action{padding:7px 12px;border:1px solid #dfe2e7;border-radius:14px;background:#fff;color:#59616f;font-size:13px}.action{border-color:#ef3340;color:#d9081c}
</style>