From f44c9bff49bbefbbed206f9dc0c05997ea60e2ee Mon Sep 17 00:00:00 2001 From: hermes Date: Mon, 15 Jun 2026 23:06:46 +0800 Subject: [PATCH] feat: UI rewrite R6 - final round (10 pages) - fxgl: groupsClock/teamList/instructionList/receive/materialList/inventory (6) - xjgl: constructionList/detail (2) - map: tckzPop/ybPop redesign (2) All 63 pages now use consistent design system --- src/views/fxgl/groupsClockList.vue | 219 ++++++++++--- src/views/fxgl/instructionList.vue | 270 ++++++++++++---- src/views/fxgl/instructionReceive.vue | 421 ++++++++++++++++++++----- src/views/fxgl/managementInventory.vue | 407 +++++++++++++++++++----- src/views/fxgl/materialList.vue | 339 ++++++++++++++++---- src/views/fxgl/teamList.vue | 211 ++++++++++--- src/views/map/tckzPop.vue | 138 +++++--- src/views/map/ybPop.vue | 207 +++++++----- src/views/xjgl/constructionDetail.vue | 396 ++++++++++++++++++----- src/views/xjgl/constructionList.vue | 246 ++++++++++----- 10 files changed, 2206 insertions(+), 648 deletions(-) diff --git a/src/views/fxgl/groupsClockList.vue b/src/views/fxgl/groupsClockList.vue index 3e89f3a..3b8c587 100644 --- a/src/views/fxgl/groupsClockList.vue +++ b/src/views/fxgl/groupsClockList.vue @@ -1,87 +1,150 @@ @@ -98,20 +161,78 @@ function goTeamList() { } } -.card-list { - padding: 0 8px; +.pull-refresh-wrap { + min-height: calc(100vh - 90px); +} - :deep(.van-card) { - margin: 8px; - border-radius: 10px; - background: var(--color-bg-card); +// ── 骨架屏 ── +.skeleton-wrap { + padding: 8px 16px; +} +.skeleton-card { + padding: 16px; + margin-bottom: 8px; + background: var(--color-bg-card); + border-radius: 10px; +} + +// ── 卡片列表 ── +.card-list { + padding: 8px 12px; +} + +.clock-card { + background: var(--color-bg-card); + border-radius: 10px; + padding: 16px; + margin-bottom: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); + + .card-hd { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + } + + .card-name { + font-size: 16px; + font-weight: 600; + color: var(--color-text-primary); + } + + .card-bd { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: 10px; + } + + .card-info { + display: flex; + align-items: center; + gap: 6px; + font-size: 13px; + color: var(--color-text-secondary); + } + + .card-ft { + padding-top: 8px; + border-top: 1px solid var(--color-border-light); + } + + .card-team { + font-size: 12px; + color: var(--color-text-placeholder); + background: var(--color-primary-bg); + color: var(--color-primary); + padding: 2px 8px; + border-radius: 4px; } } -.card-meta { - display: flex; - gap: 12px; - font-size: 12px; - color: var(--color-text-secondary); +// ── 空状态 ── +:deep(.van-empty) { + padding: 60px 0; } diff --git a/src/views/fxgl/instructionList.vue b/src/views/fxgl/instructionList.vue index 86ca2ec..6bbbb9b 100644 --- a/src/views/fxgl/instructionList.vue +++ b/src/views/fxgl/instructionList.vue @@ -1,52 +1,74 @@ @@ -118,22 +195,87 @@ function goReceive(id: number) { } } -.card-list { - padding: 0 8px; - - :deep(.van-card) { - margin: 8px; - border-radius: 10px; - background: var(--color-bg-card); - } - - :deep(.van-tag) { - margin-right: 4px; - } +.pull-refresh-wrap { + min-height: calc(100vh - 140px); } -.card-meta { - font-size: 12px; - color: var(--color-text-secondary); +// ── 骨架屏 ── +.skeleton-wrap { + padding: 8px 16px; +} +.skeleton-card { + padding: 16px; + margin-bottom: 8px; + background: var(--color-bg-card); + border-radius: 10px; +} + +// ── 指令卡片 ── +.card-list { + padding: 8px 12px; +} + +.inst-card { + background: var(--color-bg-card); + border-radius: 10px; + padding: 16px; + margin-bottom: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); + cursor: pointer; + + &:active { + opacity: 0.85; + } + + .card-hd { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 10px; + gap: 8px; + } + + .card-title-wrap { + display: flex; + align-items: flex-start; + gap: 8px; + flex: 1; + min-width: 0; + } + + .level-badge { + display: inline-block; + padding: 2px 6px; + border-radius: 4px; + font-size: 11px; + font-weight: 600; + white-space: nowrap; + flex-shrink: 0; + } + + .card-title { + font-size: 15px; + font-weight: 600; + color: var(--color-text-primary); + line-height: 1.4; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + } + + .card-bd { + display: flex; + flex-wrap: wrap; + gap: 12px; + } + + .card-info { + display: flex; + align-items: center; + gap: 4px; + font-size: 13px; + color: var(--color-text-secondary); + } } diff --git a/src/views/fxgl/instructionReceive.vue b/src/views/fxgl/instructionReceive.vue index 74bf391..f4e2d3e 100644 --- a/src/views/fxgl/instructionReceive.vue +++ b/src/views/fxgl/instructionReceive.vue @@ -1,53 +1,115 @@ @@ -117,7 +260,7 @@ function onDecline() { .page-container { min-height: 100vh; background: var(--color-bg-page); - padding-bottom: 24px; + padding-bottom: 150px; :deep(.van-nav-bar) { background: var(--color-primary); @@ -127,16 +270,144 @@ function onDecline() { } } -.content-block { +.loading-center { + display: flex; + justify-content: center; + padding-top: 160px; +} + +// ── 级别头部 ── +.level-header { + display: flex; + align-items: center; + gap: 10px; padding: 12px 16px; + + .level-tag { + display: inline-block; + padding: 4px 12px; + border-radius: 4px; + font-size: 13px; + font-weight: 600; + color: #fff; + } + + .level-label { + font-size: 14px; + color: var(--color-text-secondary); + } +} + +// ── 卡片通用 ── +.info-card, +.content-card { + margin: 0 12px 10px; + padding: 16px; + background: var(--color-bg-card); + border-radius: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); +} + +.card-title-row { + font-size: 17px; + font-weight: 600; + color: var(--color-text-primary); + line-height: 1.5; + margin-bottom: 14px; + padding-bottom: 12px; + border-bottom: 1px solid var(--color-border-light); +} + +// ── 信息网格 ── +.info-grid { + display: flex; + flex-direction: column; + gap: 12px; +} + +.info-item { + display: flex; + align-items: center; + + .info-label { + width: 70px; + font-size: 13px; + color: var(--color-text-secondary); + flex-shrink: 0; + } + + .info-value { + font-size: 14px; + color: var(--color-text-primary); + + &.deadline { + color: var(--color-danger); + font-weight: 500; + } + + a { + color: var(--color-primary); + } + } +} + +// ── 段落标签 ── +.section-label { + font-size: 14px; + font-weight: 600; + color: var(--color-text-primary); + margin-bottom: 10px; +} + +// ── 内容文本 ── +.content-text { font-size: 14px; line-height: 1.8; color: var(--color-text-regular); - background: var(--color-bg-card); white-space: pre-wrap; + word-break: break-all; } +// ── 附件列表 ── +.attach-list { + display: flex; + flex-direction: column; + gap: 8px; +} + +.attach-item { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background: var(--color-bg-page); + border-radius: 6px; + font-size: 13px; + color: var(--color-text-primary); +} + +// ── 操作按钮区 ── .action-bar { - padding: 24px 16px; + position: fixed; + bottom: 0; + left: 0; + right: 0; + padding: 12px 16px; + padding-bottom: calc(12px + env(safe-area-inset-bottom)); + background: var(--color-bg-card); + box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.06); + display: flex; + flex-direction: column; + gap: 10px; +} + +.btn-decline { + --van-button-default-color: var(--color-danger) !important; + --van-button-default-border-color: var(--color-danger) !important; +} + +// ── 退回弹窗 ── +.decline-body { + padding: 12px 16px 0; } diff --git a/src/views/fxgl/managementInventory.vue b/src/views/fxgl/managementInventory.vue index 47d308c..095a0c2 100644 --- a/src/views/fxgl/managementInventory.vue +++ b/src/views/fxgl/managementInventory.vue @@ -1,50 +1,103 @@ @@ -121,6 +239,7 @@ function onSubmit() { .page-container { min-height: 100vh; background: var(--color-bg-page); + padding-bottom: 40px; :deep(.van-nav-bar) { background: var(--color-primary); @@ -130,12 +249,148 @@ function onSubmit() { } } +.loading-center { + display: flex; + justify-content: center; + padding-top: 160px; +} + +// ── 物资信息卡片 ── +.info-card { + margin: 0 12px 10px; + padding: 16px; + background: var(--color-bg-card); + border-radius: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); +} + +.card-title-row { + font-size: 17px; + font-weight: 600; + color: var(--color-text-primary); + margin-bottom: 12px; + padding-bottom: 10px; + border-bottom: 1px solid var(--color-border-light); +} + +.info-grid { + display: flex; + flex-direction: column; + gap: 10px; +} + +.info-item { + display: flex; + align-items: center; + + .info-label { + width: 70px; + font-size: 13px; + color: var(--color-text-secondary); + flex-shrink: 0; + } + + .info-value { + font-size: 14px; + color: var(--color-text-primary); + + &.stock-val { + font-size: 18px; + font-weight: 700; + color: var(--color-primary); + } + } +} + +// ── 表单 ── +.form-wrap { + padding: 0 12px; +} + +.form-card { + margin-bottom: 10px; + padding: 12px 0 0; + background: var(--color-bg-card); + border-radius: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); + overflow: hidden; + + :deep(.van-cell) { + padding: 12px 16px; + } + + :deep(.van-cell::after) { + left: 16px; + right: 16px; + } +} + +.form-label { + font-size: 14px; + font-weight: 600; + color: var(--color-text-primary); + padding: 0 16px 4px; +} + +// ── 操作类型 Radio ── +.radio-group { + display: flex; + gap: 32px; + padding: 8px 16px 12px; + + :deep(.van-radio) { + margin-right: 0; + } +} + +.radio-label { + font-size: 15px; + font-weight: 500; + color: var(--color-text-secondary); + transition: color 0.2s; + + &.active { + color: var(--color-text-primary); + font-weight: 600; + } +} + .unit-text { color: var(--color-text-secondary); font-size: 14px; } +// ── 预览提示 ── +.preview-hint { + display: flex; + align-items: center; + gap: 6px; + padding: 8px 16px; + margin-bottom: 12px; + font-size: 13px; + border-radius: 8px; + + &.in { + background: var(--color-success-bg); + color: var(--color-success-dark); + } + + &.out { + background: var(--color-danger-bg); + color: var(--color-danger-dark); + } + + strong { + font-weight: 600; + } + + &:empty { + display: none; + } +} + +// ── 提交按钮 ── .submit-wrap { - padding: 24px 16px; + padding: 8px 4px 40px; } diff --git a/src/views/fxgl/materialList.vue b/src/views/fxgl/materialList.vue index 4456ff2..d3b481b 100644 --- a/src/views/fxgl/materialList.vue +++ b/src/views/fxgl/materialList.vue @@ -1,56 +1,80 @@ @@ -120,32 +220,141 @@ function goInventory(id: number) { } } -.card-list { - padding: 0 8px; - - :deep(.van-card) { - margin: 8px; - border-radius: 10px; - background: var(--color-bg-card); - } - - :deep(.van-tag) { - margin-right: 4px; - } +.pull-refresh-wrap { + min-height: calc(100vh - 140px); } -.card-meta { - display: flex; - gap: 12px; - font-size: 12px; - color: var(--color-text-secondary); +// ── 骨架屏 ── +.skeleton-wrap { + padding: 8px 16px; +} +.skeleton-card { + padding: 16px; + margin-bottom: 8px; + background: var(--color-bg-card); + border-radius: 10px; +} - .stock-count { - font-weight: 500; +// ── 物资卡片 ── +.card-list { + padding: 8px 12px; +} + +.mat-card { + background: var(--color-bg-card); + border-radius: 10px; + padding: 16px; + margin-bottom: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04); + cursor: pointer; + + &:active { + opacity: 0.85; + } + + .card-hd { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 14px; + gap: 8px; + } + + .card-title-wrap { + display: flex; + align-items: center; + gap: 8px; + flex: 1; + min-width: 0; + } + + .type-badge { + display: inline-block; + padding: 2px 8px; + border-radius: 4px; + font-size: 11px; + font-weight: 600; + color: #fff; + white-space: nowrap; + flex-shrink: 0; + } + + .card-name { + font-size: 15px; + font-weight: 600; color: var(--color-text-primary); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .card-bd { + margin-bottom: 10px; + } + + // ── 库存信息 ── + .stock-info { + margin-bottom: 8px; + } + + .stock-row { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 4px; + } + + .stock-label { + font-size: 13px; + color: var(--color-text-secondary); + } + + .stock-value { + font-size: 18px; + font-weight: 700; + color: var(--color-text-primary); + + &.stock-low { + color: var(--color-danger); + } + + small { + font-size: 12px; + font-weight: 400; + color: var(--color-text-secondary); + } } .stock-min { + font-size: 12px; + color: var(--color-text-placeholder); + } + + // ── 进度条 ── + .stock-progress { + height: 6px; + background: var(--color-border-light); + border-radius: 3px; + overflow: hidden; + } + + .progress-fill { + height: 100%; + border-radius: 3px; + transition: width 0.6s ease; + } + + // ── 底部 ── + .card-ft { + padding-top: 8px; + border-top: 1px solid var(--color-border-light); + } + + .card-location { + display: flex; + align-items: center; + gap: 4px; + font-size: 12px; color: var(--color-text-placeholder); } } diff --git a/src/views/fxgl/teamList.vue b/src/views/fxgl/teamList.vue index e96fc71..b693845 100644 --- a/src/views/fxgl/teamList.vue +++ b/src/views/fxgl/teamList.vue @@ -1,41 +1,84 @@ diff --git a/src/views/xjgl/constructionDetail.vue b/src/views/xjgl/constructionDetail.vue index 52f937d..d353a08 100644 --- a/src/views/xjgl/constructionDetail.vue +++ b/src/views/xjgl/constructionDetail.vue @@ -5,27 +5,55 @@ * 展示工程项目的详细信息,包括基本信息、 * 施工进度、现场照片等。 */ -import { ref } from 'vue' +import { ref, computed } from 'vue' import { useRouter, useRoute } from 'vue-router' const router = useRouter() const route = useRoute() +const detailId = computed(() => route.params.id as string | undefined) -/** 模拟项目详情 */ -const project = { - id: route.params.id, +interface ProjectDetail { + id: string + name: string + no: string + company: string + progress: number + status: 'building' | 'paused' | 'completed' + manager: string + phone: string + startDate: string + endDate: string + budget: string + address: string + description: string +} + +const project = ref({ + id: detailId.value || '1', name: '城北雨水管网改造工程', no: 'XM-2025-001', company: '中建三局', - manager: '赵工', - phone: '13800001010', progress: 75, status: 'building', + manager: '赵工', + phone: '13800001010', startDate: '2025-03-01', - endDate: '2025-09-30', + endDate: '2025-12-31', budget: '1250万元', address: '城北工业园区大道路段', - description: '该项目对城北工业园区范围内雨水管网进行全面改造升级,包括主管网更换、检查井增设、雨水口改造等内容。改造完成后将显著提升区域排水能力。', + description: '该项目对城北工业园区范围内雨水管网进行全面改造升级,包括主管网更换、检查井增设、雨水口改造等内容。改造完成后将显著提升区域排水能力,惠及周边30万居民。', +}) + +const statusCfg: Record = { + building: { label: '在建', color: '#1E74FF', bg: '#E3F2FD' }, + paused: { label: '暂停', color: '#FF976A', bg: '#FFF3ED' }, + completed: { label: '竣工', color: '#07C160', bg: '#E8F8EF' }, +} + +function progressColor(pct: number): string { + if (pct >= 80) return '#07C160' + if (pct >= 40) return '#1E74FF' + return '#FF976A' } /** 模拟现场照片 */ @@ -36,21 +64,21 @@ const photos = ref([ { url: 'https://img.yzcdn.cn/vant/apple-3.jpg' }, ]) -function progressColor(pct: number): string { - if (pct >= 80) return '#07c160' - if (pct >= 40) return '#1989fa' - return '#ff976a' -} +/** 模拟里程碑 */ +const milestones = ref([ + { text: '项目立项', time: '2025-02-15', done: true }, + { text: '施工设计', time: '2025-03-15', done: true }, + { text: '管网铺设', time: '2025-06-30', done: true }, + { text: '泵站建设', time: '2025-09-30', done: false }, + { text: '竣工验收', time: '2025-12-31', done: false }, +]) -const statusMap: Record = { - building: '在建', - paused: '暂停', - completed: '竣工', -} +const activeStep = computed(() => milestones.value.filter(m => m.done).length - 1) diff --git a/src/views/xjgl/constructionList.vue b/src/views/xjgl/constructionList.vue index 262ce16..cb17e90 100644 --- a/src/views/xjgl/constructionList.vue +++ b/src/views/xjgl/constructionList.vue @@ -9,41 +9,43 @@ import { ref, computed } from 'vue' import { useRouter } from 'vue-router' const router = useRouter() - const searchText = ref('') const activeTab = ref(0) -/** 状态映射 */ -const statusMap: Record = { - building: '在建', - paused: '暂停', - completed: '竣工', +interface ConstructionProject { + id: number + name: string + no: string + company: string + progress: number + status: 'building' | 'paused' | 'completed' + manager: string + startDate: string } -const statusColorMap: Record = { - building: 'primary', - paused: 'warning', - completed: 'success', -} - -/** 进度颜色 */ -function progressColor(pct: number): string { - if (pct >= 80) return '#07c160' - if (pct >= 40) return '#1989fa' - return '#ff976a' -} - -/** 模拟项目数据 */ -const mockProjects = [ +const projects: ConstructionProject[] = [ { id: 1, name: '城北雨水管网改造工程', no: 'XM-2025-001', company: '中建三局', progress: 75, status: 'building', manager: '赵工', startDate: '2025-03-01' }, { id: 2, name: '东风路排水泵站新建项目', no: 'XM-2025-002', company: '水务工程公司', progress: 30, status: 'building', manager: '钱工', startDate: '2025-04-15' }, { id: 3, name: '中山河河道整治工程', no: 'XM-2025-003', company: '市政建设集团', progress: 90, status: 'building', manager: '孙工', startDate: '2025-01-10' }, { id: 4, name: '开发区污水管网铺设', no: 'XM-2025-004', company: '中交一公局', progress: 0, status: 'paused', manager: '李工', startDate: '2025-05-01' }, { id: 5, name: '老城区雨污分流改造', no: 'XM-2025-005', company: '中铁十二局', progress: 100, status: 'completed', manager: '周工', startDate: '2024-09-01' }, + { id: 6, name: '南湖片区海绵城市试点', no: 'XM-2025-006', company: '葛洲坝集团', progress: 55, status: 'building', manager: '吴工', startDate: '2025-06-01' }, ] +const statusCfg: Record = { + building: { label: '在建', color: '#1E74FF', bg: '#E3F2FD' }, + paused: { label: '暂停', color: '#FF976A', bg: '#FFF3ED' }, + completed: { label: '竣工', color: '#07C160', bg: '#E8F8EF' }, +} + +function progressColor(pct: number): string { + if (pct >= 80) return '#07C160' + if (pct >= 40) return '#1E74FF' + return '#FF976A' +} + const filteredList = computed(() => { - let list = mockProjects + let list = projects if (searchText.value) { const kw = searchText.value.toLowerCase() list = list.filter(p => @@ -64,85 +66,187 @@ function goDetail(id: number) {