Ver Fonte

feat(swh): 优化双周会入口顺序和汇总明细查看

- 将生产运营双周会入口调整到核心功能第二位
- 隐藏汇总项目卡片中的动态字段
- 增加项目明细查看按钮和底部抽屉
- 在抽屉中展示经营数据、工作情况及动态字段
- 支持抽屉滚动、长文本换行和安全区域适配
Zimo há 1 mês atrás
pai
commit
5ee91cb422
2 ficheiros alterados com 131 adições e 15 exclusões
  1. 8 9
      pages/entry/index.vue
  2. 123 6
      pages/swh/summary-detail.vue

+ 8 - 9
pages/entry/index.vue

@@ -224,6 +224,14 @@ const coreFeatures = [
     active: true,
     path: "/pages/home/index",
   },
+  {
+    title: "生产运营双周会",
+    desc: "双周会管理与跟踪",
+    iconText: "/static/entry/yunying.png",
+    iconBg: "linear-gradient(135deg, #fff3e8 0%, #ffe3cc 100%)",
+    iconColor: "#ff8a1f",
+    path: "/pages/swh/index",
+  },
   {
     title: "QHSE",
     desc: "质量健康安全环保",
@@ -248,15 +256,6 @@ const coreFeatures = [
     iconColor: "#10a8c6",
     path: "/pages/lianyou/index",
   },
-
-  {
-    title: "生产运营双周会",
-    desc: "双周会管理与跟踪",
-    iconText: "/static/entry/yunying.png",
-    iconBg: "linear-gradient(135deg, #fff3e8 0%, #ffe3cc 100%)",
-    iconColor: "#ff8a1f",
-    path: "/pages/swh/index",
-  },
 ];
 
 const commonTools = [

+ 123 - 6
pages/swh/summary-detail.vue

@@ -59,7 +59,10 @@
         </view>
 
         <view v-for="(detail, index) in meeting.details" :key="index" class="project-card">
-          <view class="project-title">{{ detail.projectName || "未命名项目" }}</view>
+          <view class="project-head">
+            <view class="project-title">{{ detail.projectName || "未命名项目" }}</view>
+            <text class="project-view" @click="openDetail(detail)">查看</text>
+          </view>
           <view class="money-list">
             <view v-for="metric in metrics" :key="metric.key">
               <text>{{ metric.label }}</text>
@@ -70,13 +73,75 @@
             <text>{{ field.label }}</text>
             <view class="multiline-text">{{ displayText(detail[field.key]) }}</view>
           </view>
-          <view v-for="item in normalizeExt(detail.extProperty)" :key="item.identifier" class="text-field">
-            <text>{{ extLabel(item) }}</text>
-            <view class="multiline-text">{{ displayPropertyText(item) }}</view>
-          </view>
         </view>
       </view>
     </template>
+
+    <uni-popup
+      ref="detailPopup"
+      type="bottom"
+      background-color="#f4f7fb"
+      border-radius="20px 20px 0 0"
+    >
+      <view class="detail-drawer">
+        <view class="drawer-head">
+          <view>
+            <view class="drawer-title">查看会议明细</view>
+            <view class="drawer-subtitle">{{ currentDetail.projectName || "未命名项目" }}</view>
+          </view>
+          <uni-icons type="closeempty" size="24" color="#64748b" @click="closeDetail" />
+        </view>
+
+        <scroll-view class="drawer-scroll" scroll-y :show-scrollbar="false">
+          <view class="drawer-section">
+            <view class="drawer-section-title">经营情况(万元)</view>
+            <view class="drawer-money-grid">
+              <view v-for="metric in metrics" :key="metric.key" class="drawer-money-item">
+                <text>{{ metric.label }}</text>
+                <strong>{{ valueText(currentDetail[metric.key]) }}</strong>
+              </view>
+            </view>
+          </view>
+
+          <view v-if="currentDetailCurrentProperties.length" class="drawer-section">
+            <view class="drawer-section-title">本期生产运行情况</view>
+            <view
+              v-for="item in currentDetailCurrentProperties"
+              :key="item.identifier"
+              class="drawer-field"
+            >
+              <text>{{ extLabel(item) }}</text>
+              <view class="multiline-text">{{ displayPropertyText(item) }}</view>
+            </view>
+          </view>
+
+          <view v-for="group in detailGroups" :key="group.title" class="drawer-section">
+            <view class="drawer-section-title">{{ group.title }}</view>
+            <view v-for="field in group.fields" :key="field.key" class="drawer-field">
+              <text>{{ field.label }}</text>
+              <view class="multiline-text">{{ displayText(currentDetail[field.key]) }}</view>
+            </view>
+          </view>
+
+          <view v-if="currentDetailNextProperties.length" class="drawer-section">
+            <view class="drawer-section-title">下期扩展工作计划</view>
+            <view
+              v-for="item in currentDetailNextProperties"
+              :key="item.identifier"
+              class="drawer-field"
+            >
+              <text>{{ extLabel(item) }}</text>
+              <view class="multiline-text">{{ displayPropertyText(item) }}</view>
+            </view>
+          </view>
+          <view class="drawer-bottom-space"></view>
+        </scroll-view>
+
+        <view class="drawer-footer">
+          <button @click="closeDetail">关闭</button>
+        </view>
+      </view>
+    </uni-popup>
   </view>
 </template>
 
@@ -91,6 +156,8 @@ const meetingSeries = ref("");
 const year = ref("");
 const meetings = ref([]);
 const companyIndex = ref(-1);
+const detailPopup = ref(null);
+const currentDetail = ref({});
 
 const metrics = [
   { key: "currentRevenue", label: "收入-本期", tone: "blue" },
@@ -107,6 +174,26 @@ const detailTextFields = [
   { key: "nextPlannedWorkload", label: "下期计划工作量" },
   { key: "priorityTasks", label: "重点工作事项" },
 ];
+const detailGroups = [
+  {
+    title: "生产管理情况及重点工作",
+    fields: [
+      { key: "keyWorkCompletion", label: "重点工作及完成情况" },
+      { key: "problemsAnalysis", label: "存在问题及分析" },
+    ],
+  },
+  {
+    title: "设备、安全管理工作",
+    fields: [{ key: "qhse", label: "设备、安全管理工作" }],
+  },
+  {
+    title: "下期工作计划",
+    fields: [
+      { key: "nextPlannedWorkload", label: "计划工作量" },
+      { key: "priorityTasks", label: "重点工作事项" },
+    ],
+  },
+];
 
 const normalizedMeetings = (list) => list.map((item, index) => ({
   ...item,
@@ -179,6 +266,22 @@ const displayPropertyText = (item) => {
     ? valueText(item.actualValue)
     : displayText(item.actualValue);
 };
+const currentDetailProperties = computed(() =>
+  normalizeExt(currentDetail.value?.extProperty).sort(
+    (a, b) => Number(a.sort || 0) - Number(b.sort || 0),
+  ),
+);
+const currentDetailCurrentProperties = computed(() =>
+  currentDetailProperties.value.filter((item) => item.defaultValue !== "next"),
+);
+const currentDetailNextProperties = computed(() =>
+  currentDetailProperties.value.filter((item) => item.defaultValue === "next"),
+);
+const openDetail = (detail) => {
+  currentDetail.value = detail || {};
+  detailPopup.value?.open();
+};
+const closeDetail = () => detailPopup.value?.close();
 const isRequiredWorkload = (item) => [true, 1, "1"].includes(item.required);
 const selectedWorkloadProperties = computed(() =>
   normalizeExt(selectedMeeting.value?.extProperty)
@@ -237,9 +340,23 @@ onLoad(async (options) => {
 .company-section { margin-top: 24rpx; padding: 26rpx; border-radius: 20rpx; background: #fff; }
 .company-head { display: flex; justify-content: space-between; align-items: flex-start; }.company-name { color: #172033; font-size: 32rpx; font-weight: 700; }.meeting-date { margin-top: 8rpx; color: #94a3b8; font-size: 22rpx; }.project-count { color: #2563eb; font-size: 22rpx; }
 .support { margin-top: 22rpx; padding: 20rpx; color: #475569; font-size: 25rpx; line-height: 1.6; border-radius: 14rpx; background: #fff7ed; }.support text { display: block; margin-bottom: 6rpx; color: #c2410c; font-weight: 700; }
-.project-card { margin-top: 22rpx; padding: 22rpx; border: 1rpx solid #e5edf8; border-radius: 16rpx; background: #fbfdff; }.project-title { color: #1d4ed8; font-size: 29rpx; font-weight: 700; }
+.project-card { margin-top: 22rpx; padding: 22rpx; border: 1rpx solid #e5edf8; border-radius: 16rpx; background: #fbfdff; }
+.project-head { display: flex; align-items: center; justify-content: space-between; }
+.project-title { flex: 1; min-width: 0; color: #1d4ed8; font-size: 29rpx; font-weight: 700; }
+.project-view { flex-shrink: 0; margin-left: 20rpx; color: #2563eb; font-size: 25rpx; font-weight: 500; }
 .money-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12rpx; margin-top: 18rpx; }.money-list view { padding: 14rpx; border-radius: 10rpx; background: #f1f5f9; }.money-list text,.money-list strong { display: block; }.money-list text { color: #94a3b8; font-size: 20rpx; }.money-list strong { margin-top: 6rpx; color: #334155; font-size: 22rpx; }
 .text-field { margin-top: 20rpx; color: #475569; font-size: 25rpx; line-height: 1.6; }.text-field text { display: block; margin-bottom: 4rpx; color: #172033; font-weight: 700; }
 .multiline-text { white-space: pre-wrap; word-break: break-word; word-wrap: break-word; overflow-wrap: anywhere; }
+.detail-drawer { height: 88vh; display: flex; flex-direction: column; overflow: hidden; }
+.drawer-head { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; padding: 28rpx 30rpx; background: #fff; border-bottom: 1rpx solid #eef2f7; }
+.drawer-title { color: #172033; font-size: 34rpx; font-weight: 700; }.drawer-subtitle { max-width: 560rpx; margin-top: 6rpx; overflow: hidden; color: #64748b; font-size: 24rpx; text-overflow: ellipsis; white-space: nowrap; }
+.drawer-scroll { flex: 1; height: 0; padding: 22rpx 22rpx 0; box-sizing: border-box; }
+.drawer-section { margin-bottom: 20rpx; padding: 26rpx 24rpx; border-radius: 18rpx; background: #fff; }
+.drawer-section-title { color: #172033; font-size: 29rpx; font-weight: 700; }
+.drawer-money-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14rpx; margin-top: 20rpx; }
+.drawer-money-item { min-width: 0; padding: 18rpx; border-radius: 12rpx; background: #f1f5f9; box-sizing: border-box; }.drawer-money-item text { display: block; color: #94a3b8; font-size: 21rpx; }.drawer-money-item strong { display: block; margin-top: 8rpx; color: #334155; font-size: 25rpx; overflow-wrap: anywhere; }
+.drawer-field { margin-top: 22rpx; color: #475569; font-size: 25rpx; line-height: 1.7; }.drawer-field > text { display: block; margin-bottom: 8rpx; color: #172033; font-weight: 700; }
+.drawer-bottom-space { height: 10rpx; }
+.drawer-footer { flex-shrink: 0; padding: 18rpx 24rpx calc(18rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -6rpx 20rpx rgba(15, 23, 42, .06); }.drawer-footer button { height: 76rpx; margin: 0; color: #fff; font-size: 28rpx; line-height: 76rpx; border-radius: 14rpx; background: #2563eb; }.drawer-footer button::after { border: 0; }
 .state { padding: 150rpx 0; color: #94a3b8; text-align: center; }
 </style>