Bläddra i källkod

feat: 新增报告分享页面;更新报告页面和工单更新逻辑

xiaohaizhao 1 vecka sedan
förälder
incheckning
141026cc71

+ 2 - 1
app.json

@@ -42,7 +42,8 @@
                 "workOrder/material/index",
                 "workOrder/team/index",
                 "workOrder/application/index",
-                "workOrder/nodes/report/index"
+                "workOrder/nodes/report/index",
+                "workOrder/nodes/report/share"
             ]
         }
     ],

BIN
bgj/workOrder/nodes/report/QQ20260603-08903.png


+ 0 - 74
bgj/workOrder/nodes/report/claude.md

@@ -1,74 +0,0 @@
-(1)顶部logo区域:logo来源【合作伙伴档案】中设置的当前工单所属经销商的logo。
-
-
-
-(2)标题区域:展示工单所属经销商名称+“施工进度汇报”
-
-例如:嘉兴云链信息施工进度汇报
-
-
-
-(3)表格区域:
-①日期:点击【施工日志汇报】功能的日期
-②天气:当前天气、气温。
-③项目名称:必填,取工单省市县、详细地址,可修改。
-④施工部位:非必填,人工填写。
-⑤品牌:取工单所属的经销商授权的类别品牌(多个则逗号隔开)
-⑥工作内容:必填,取工序内容,可修改。
-⑦人员情况:取工序中操作人员。
-⑧遇到的问题:非必填,人工填写。
-⑨需协调的内容:非必填,人工填写。
-下步计划:非必填,人工填写。
-
-
-
-(4)图片区域:
-
-①图片来源当前工序中上传的图片。
-
-②需按上传顺序汇总展示。
-
-
-
-(5)结束语:
-
-①文本来源工单所属经销商的“施工日志模板”字段值(经销商表)。
-
-
-
-2、操作:
-
-(1)施工日志汇报:工单模板中工作项设置”是否施工日志汇报“为”是“,并且工序状态为”已完成“时,工序详情显示【施工日志汇报】功能
-
-(1)保存:生成图片,保存至工单附件,可在附件tab查看。
-
-(2)保存并转发:生成图片,保存至工单附件,并可将图片转发给微信好用、微信群、朋友圈。
-
-
-/保存汇报内容接口
-{
-"id": 2026052814061302,
-"content": {
-"sc_workorderid":15,
-"sc_workorder_nodeid": 18,
-"report_content": {
-"title": "XXX施工进度汇报",
-"date": "2026-01-01",
-"weather": "晴 -1℃",
-"project_name": "项目名称",
-"construction_part": "施工部位",
-"brand_name": "品牌",
-"work_content": "工作内容",
-"reporter": "张三",
-"problem": "问题",
-"coordination_needed": "需要协调的内容",
-"next_plan": "下步计划"
-}
-},
-"accesstoken": "7bf8eb13d1af0a92203d86e0d9db2ea2"
-}
-
-
-你先按照以上需求做,未知的接口或者字段记录到这里,后面一点点补上 现在能做多少做多少;
-
-开发中我们默认要适配多语言

+ 80 - 13
bgj/workOrder/nodes/report/index.js

@@ -22,8 +22,9 @@ Page({
       nextPlan: '',
     },
     imageList: [],
-    closingText: '',
+    closingText: '感谢各位的辛勤付出,让我们携手共创美好未来!',
     saving: false,
+    showSharePopup: false,
   },
 
   onLoad(options) {
@@ -52,13 +53,19 @@ Page({
       'form.projectName': projectName,
     });
 
+    // 启用转发给朋友和朋友圈
+    wx.showShareMenu({
+      withShareTicket: true,
+      menus: ['shareAppMessage', 'shareTimeline'],
+    });
+
     this.fetchBrands();
     this.fetchNodeDetail(workorderId, nodeId);
   },
 
   // 调用节点详情接口获取工序数据
   fetchNodeDetail(workorderId, nodeId) {
-    _Http.basic({
+    _Http.base({
       id: 2026052615161102,
       content: {
         sc_workorderid: workorderId,
@@ -69,7 +76,6 @@ Page({
       const d = res.data;
       const nodeDetail = d;
       const workpresetjson = d.workpresetjson || {};
-      const workContent = workpresetjson.workname || '';
 
       // 人员情况:取操作人员名称,逗号分隔
       const trainers = d.trainers || [];
@@ -81,12 +87,32 @@ Page({
         .filter(v => (!v.usetype || v.usetype === 'default') && v.url)
         .map(v => ({ ...v, url: v.url.split('?')[0] }));
 
-      this.setData({
+      // 回填 report_content 中的数据
+      const reportContent = d.report_content || {};
+      const updateData = {
         nodeDetail,
-        'form.workContent': workContent,
-        'form.reporter': reporter,
         imageList,
-      });
+      };
+
+      // 如果有保存过的 report_content,回填表单
+      if (d.report_content) {
+        updateData['form.date'] = reportContent.date || this.data.form.date;
+        updateData['form.weather'] = reportContent.weather || '';
+        updateData['form.projectName'] = reportContent.project_name || this.data.form.projectName;
+        updateData['form.constructionPart'] = reportContent.construction_part || '';
+        updateData['form.brandName'] = reportContent.brand_name || this.data.form.brandName;
+        updateData['form.workContent'] = reportContent.work_content || workpresetjson.workname || '';
+        updateData['form.reporter'] = reportContent.reporter || reporter;
+        updateData['form.problem'] = reportContent.problem || '';
+        updateData['form.coordinationNeeded'] = reportContent.coordination_needed || '';
+        updateData['form.nextPlan'] = reportContent.next_plan || '';
+      } else {
+        // 没有保存过的数据,使用默认值
+        updateData['form.workContent'] = workpresetjson.workname || '';
+        updateData['form.reporter'] = reporter;
+      }
+
+      this.setData(updateData);
     }).catch(() => {});
   },
 
@@ -165,7 +191,6 @@ Page({
     try {
       await this._saveReportData();
       wx.showToast({ title: Language.getMapText('保存成功'), icon: 'success' });
-      setTimeout(() => wx.navigateBack(), 1500);
     } catch (e) {
       console.error('保存失败', e);
       wx.showToast({ title: Language.getMapText('保存失败'), icon: 'none' });
@@ -174,13 +199,46 @@ Page({
     }
   },
 
-  // 保存并转发
-  async saveAndForward() {
+  // 保存并转发:弹出分享选择
+  saveAndForward() {
     const msg = this.validate();
     if (msg) { wx.showToast({ title: msg, icon: 'none' }); return; }
     if (this.data.saving) return;
-    this.setData({ saving: true });
+    this.setData({ showSharePopup: true });
+  },
+
+  // 转发给朋友(open-type="share" 触发原生分享)
+  onShareFriends() {
+    this.setData({ showSharePopup: false });
+    this._doSave();
+  },
+
+  // 转发到朋友圈
+  handleShareTimeline() {
+    this.setData({ showSharePopup: false });
+    this._doSave();
+    wx.showShareMenu({
+      withShareTicket: true,
+      menus: ['shareTimeline'],
+    });
+    setTimeout(() => {
+      wx.previewImage({
+        current: '/bgj/workOrder/nodes/report/QQ20260603-08903.png', // 当前显示图片的http链接
+        urls: ['/bgj/workOrder/nodes/report/QQ20260603-08903.png'], // 当前显示图片的http链接
+        complete(res){
+          console.log(res)
+        }
+      })
+    }, 300);
+  },
+
+  closeSharePopup() {
+    this.setData({ showSharePopup: false });
+  },
 
+  async _doSave() {
+    if (this.data.saving) return;
+    this.setData({ saving: true });
     try {
       await this._saveReportData();
       wx.showToast({ title: Language.getMapText('保存成功'), icon: 'success' });
@@ -199,11 +257,20 @@ Page({
     wx.previewImage({ current: url, urls });
   },
 
-  // 微信原生转发
+  // 微信原生转发给朋友
   onShareAppMessage() {
+    const nodeId = this.data.nodeDetail.sc_workorder_nodeid || this.data.nodeDetail.sa_workorder_nodeid;
+    return {
+      title: this.data.dealerName + Language.getMapText('施工进度汇报'),
+      path: `/bgj/workOrder/nodes/report/index?nodeId=${nodeId}`,
+    };
+  },
+
+  // 转发到朋友圈
+  onShareTimeline() {
     return {
       title: this.data.dealerName + Language.getMapText('施工进度汇报'),
-      path: `/bgj/workOrder/nodes/report/index?nodeId=${this.data.nodeDetail.sc_workorder_nodeid || this.data.nodeDetail.sa_workorder_nodeid}`,
+      query: `nodeId=${this.data.nodeDetail.sc_workorder_nodeid || this.data.nodeDetail.sa_workorder_nodeid}`,
     };
   },
 });

+ 2 - 1
bgj/workOrder/nodes/report/index.json

@@ -3,6 +3,7 @@
     "usingComponents": {
         "van-button": "@vant/weapp/button/index",
         "van-field": "@vant/weapp/field/index",
-        "van-icon": "@vant/weapp/icon/index"
+        "van-icon": "@vant/weapp/icon/index",
+        "van-popup": "@vant/weapp/popup/index"
     }
 }

+ 322 - 68
bgj/workOrder/nodes/report/index.scss

@@ -1,13 +1,42 @@
 page {
-  background-color: #fff;
+  background-color: #f0f4ff;
 }
 
 .page {
   width: 100%;
   min-height: 100vh;
-  padding: 30rpx;
   box-sizing: border-box;
-  background: #fff;
+  background: linear-gradient(180deg, #e8f0fe 0%, #f0f4ff 30%, #f5f7fa 100%);
+}
+
+/* 头部背景 */
+.header-bg {
+  background: linear-gradient(135deg, #4a90d9 0%, #667eea 50%, #764ba2 100%);
+  padding: 50rpx 40rpx 80rpx;
+  position: relative;
+  overflow: hidden;
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: -50%;
+    right: -20%;
+    width: 400rpx;
+    height: 400rpx;
+    background: rgba(255, 255, 255, 0.1);
+    border-radius: 50%;
+  }
+
+  &::after {
+    content: '';
+    position: absolute;
+    bottom: -30%;
+    left: -10%;
+    width: 300rpx;
+    height: 300rpx;
+    background: rgba(255, 255, 255, 0.08);
+    border-radius: 50%;
+  }
 }
 
 /* logo 区域 */
@@ -15,6 +44,8 @@ page {
   display: flex;
   justify-content: center;
   padding: 20rpx 0;
+  position: relative;
+  z-index: 1;
 
   .logo-img {
     width: 200rpx;
@@ -25,92 +56,206 @@ page {
 /* 标题 */
 .title-area {
   text-align: center;
-  padding: 20rpx 0 30rpx;
+  padding: 20rpx 0 10rpx;
+  position: relative;
+  z-index: 1;
 
   .title-text {
-    font-size: 36rpx;
-    font-weight: bold;
-    color: #333;
+    font-size: 42rpx;
+    font-weight: 600;
+    color: #fff;
+    letter-spacing: 4rpx;
+    text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2);
+  }
+}
+
+/* 日期标签 */
+.date-badge {
+  display: flex;
+  justify-content: center;
+  margin-top: 20rpx;
+  position: relative;
+  z-index: 1;
+
+  .date-tag {
+    background: rgba(255, 255, 255, 0.2);
+    backdrop-filter: blur(10rpx);
+    padding: 10rpx 30rpx;
+    border-radius: 30rpx;
+    font-size: 26rpx;
+    color: rgba(255, 255, 255, 0.9);
+    letter-spacing: 2rpx;
+  }
+}
+
+/* 主内容区 */
+.main-content {
+  margin-top: -50rpx;
+  padding: 0 30rpx 180rpx;
+  position: relative;
+  z-index: 2;
+}
+
+/* 表格卡片 */
+.form-card {
+  background: #fff;
+  border-radius: 24rpx;
+  overflow: hidden;
+  box-shadow: 0 8rpx 40rpx rgba(74, 144, 217, 0.12);
+  margin-bottom: 30rpx;
+}
+
+.card-header {
+  display: flex;
+  align-items: center;
+  padding: 30rpx 36rpx;
+  background: linear-gradient(90deg, #f8faff 0%, #fff 100%);
+  border-bottom: 1rpx solid #eef3ff;
+
+  .card-icon {
+    width: 48rpx;
+    height: 48rpx;
+    background: linear-gradient(135deg, #4a90d9, #667eea);
+    border-radius: 12rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 20rpx;
+  }
+
+  .card-title {
+    font-size: 32rpx;
+    font-weight: 600;
+    color: #1a1a1a;
   }
 }
 
 /* 表格区域 */
 .form-area {
-  border: 2rpx solid #ebeef5;
-  border-radius: 12rpx;
-  overflow: hidden;
+  padding: 10rpx 0;
 
   .form-row {
     display: flex;
-    border-bottom: 2rpx solid #ebeef5;
-    min-height: 80rpx;
+    padding: 0 36rpx;
+    min-height: 100rpx;
+    transition: all 0.3s ease;
+    position: relative;
+
+    &:not(:last-child)::after {
+      content: '';
+      position: absolute;
+      bottom: 0;
+      left: 36rpx;
+      right: 36rpx;
+      height: 1rpx;
+      background: linear-gradient(90deg, transparent, #e8ecf4, transparent);
+    }
 
-    &:last-child {
-      border-bottom: none;
+    &:active {
+      background: #f8faff;
     }
   }
 
   .form-label {
-    width: 200rpx;
+    width: 180rpx;
     flex-shrink: 0;
-    padding: 20rpx 24rpx;
+    padding: 30rpx 0;
     font-size: 28rpx;
-    color: #606266;
-    background: #fafafa;
-    border-right: 2rpx solid #ebeef5;
+    font-weight: 500;
+    color: #666;
     display: flex;
     align-items: flex-start;
-    box-sizing: border-box;
+    line-height: 1.5;
   }
 
   .form-value {
     flex: 1;
-    padding: 20rpx 24rpx;
+    padding: 30rpx 0;
     font-size: 28rpx;
     color: #333;
     word-break: break-all;
+    white-space: normal;
+    overflow-wrap: break-word;
     display: flex;
-    align-items: center;
-  }
-
-  .form-input {
-    width: 100%;
-    font-size: 28rpx;
-    color: #333;
+    align-items: flex-start;
+    line-height: 1.6;
   }
 
   .form-textarea {
     width: 100%;
     font-size: 28rpx;
     color: #333;
-    min-height: 60rpx;
+    min-height: 48rpx;
+    line-height: 1.6;
+    border: none;
+    outline: none;
+    background: transparent;
+    padding: 0;
+
+    &::placeholder {
+      color: #c0c4cc;
+    }
   }
 }
 
 .required-star {
-  color: #e34d59;
-  margin-right: 4rpx;
+  color: #ff4757;
+  margin-right: 6rpx;
+  font-weight: bold;
 }
 
 /* 图片区域 */
-.section-title {
-  font-size: 30rpx;
-  font-weight: bold;
-  color: #333;
-  padding: 30rpx 0 16rpx;
+.image-section {
+  margin-bottom: 30rpx;
+}
+
+.section-header {
+  display: flex;
+  align-items: center;
+  padding: 30rpx 10rpx 24rpx;
+
+  .section-icon {
+    width: 40rpx;
+    height: 40rpx;
+    background: linear-gradient(135deg, #4a90d9, #667eea);
+    border-radius: 10rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 16rpx;
+  }
+
+  .section-title {
+    font-size: 32rpx;
+    font-weight: 600;
+    color: #1a1a1a;
+  }
+}
+
+.image-card {
+  background: #fff;
+  border-radius: 24rpx;
+  padding: 30rpx;
+  box-shadow: 0 8rpx 40rpx rgba(74, 144, 217, 0.12);
 }
 
 .image-area {
   display: flex;
   flex-wrap: wrap;
-  gap: 16rpx;
+  gap: 20rpx;
 
   .image-item {
-    width: 210rpx;
-    height: 210rpx;
-    border-radius: 8rpx;
+    width: calc(33.33% - 14rpx);
+    aspect-ratio: 1;
+    border-radius: 16rpx;
     overflow: hidden;
-    background: #f5f5f5;
+    background: linear-gradient(135deg, #f0f4ff, #e8f0fe);
+    box-shadow: 0 4rpx 16rpx rgba(74, 144, 217, 0.15);
+    transition: transform 0.2s ease;
+
+    &:active {
+      transform: scale(0.95);
+    }
   }
 
   .image-thumb {
@@ -121,52 +266,161 @@ page {
 
 /* 结束语 */
 .closing-area {
-  padding: 30rpx 0;
+  margin-bottom: 30rpx;
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  border-radius: 24rpx;
+  padding: 36rpx;
+  box-shadow: 0 8rpx 30rpx rgba(102, 126, 234, 0.3);
 
   .closing-text {
     font-size: 28rpx;
-    color: #666;
-    line-height: 1.6;
+    color: rgba(255, 255, 255, 0.95);
+    line-height: 1.8;
+    text-align: center;
   }
 }
 
 /* 底部按钮(悬浮) */
+.but-box-fixed {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 20rpx 30rpx 50rpx;
+  background: rgba(255, 255, 255, 0.98);
+  backdrop-filter: blur(30rpx);
+  box-shadow: 0 -4rpx 30rpx rgba(0, 0, 0, 0.08);
+  z-index: 100;
+  box-sizing: border-box;
+  display: flex;
+  gap: 24rpx;
+}
+
+.btn-half {
+  flex: 1;
+}
+
 .draft-btn {
-  height: 90rpx;
-  line-height: 90rpx;
-  background: #FA9115 !important;
-  border-radius: 8rpx;
+  height: 96rpx;
+  line-height: 96rpx;
+  background: linear-gradient(135deg, #ffd93d, #ff9f43) !important;
+  border-radius: 48rpx;
   font-size: 32rpx;
-  font-weight: bold;
+  font-weight: 600;
   color: #fff !important;
   border: none !important;
+  box-shadow: 0 8rpx 24rpx rgba(255, 159, 67, 0.4);
+  transition: all 0.2s ease;
+
+  &:active {
+    transform: scale(0.98);
+    box-shadow: 0 4rpx 16rpx rgba(255, 159, 67, 0.3);
+  }
 }
 
 .save-btn {
-  height: 90rpx;
-  line-height: 90rpx;
-  background: #3874F6 !important;
-  border-radius: 8rpx;
+  height: 96rpx;
+  line-height: 96rpx;
+  background: linear-gradient(135deg, #667eea, #4a90d9) !important;
+  border-radius: 48rpx;
   font-size: 32rpx;
-  font-weight: bold;
+  font-weight: 600;
   color: #fff !important;
   border: none !important;
+  box-shadow: 0 8rpx 24rpx rgba(74, 144, 217, 0.4);
+  transition: all 0.2s ease;
+
+  &:active {
+    transform: scale(0.98);
+    box-shadow: 0 4rpx 16rpx rgba(74, 144, 217, 0.3);
+  }
 }
 
-.but-box-fixed {
-  position: fixed;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  padding: 10rpx 30rpx 26rpx;
-  background: #fff;
-  box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
-  z-index: 100;
-  box-sizing: border-box;
-  display: flex;
-  gap: 20rpx;
+/* 分享弹窗 */
+.share-popup {
+  padding: 20rpx 0 40rpx;
 
-  .btn-half {
-    flex: 1;
+  .share-popup-title {
+    text-align: center;
+    font-size: 34rpx;
+    font-weight: 600;
+    color: #1a1a1a;
+    padding-bottom: 30rpx;
+    position: relative;
+
+    &::after {
+      content: '';
+      position: absolute;
+      bottom: 0;
+      left: 50%;
+      transform: translateX(-50%);
+      width: 60rpx;
+      height: 4rpx;
+      background: linear-gradient(90deg, #667eea, #4a90d9);
+      border-radius: 2rpx;
+    }
+  }
+
+  .share-option {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 110rpx;
+    font-size: 32rpx;
+    color: #333;
+    background: none;
+    border: none;
+    border-radius: 0;
+    line-height: 110rpx;
+    padding: 0;
+    transition: background 0.2s;
+
+    &::after {
+      border: none;
+    }
+
+    &:active {
+      background: #f0f4ff;
+    }
   }
+
+  .share-cancel {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 110rpx;
+    font-size: 32rpx;
+    color: #999;
+    border-top: 1rpx solid #f0f0f0;
+    margin-top: 16rpx;
+    transition: background 0.2s;
+
+    &:active {
+      background: #f5f7fa;
+    }
+  }
+}
+
+/* 动画 */
+@keyframes fadeInUp {
+  from {
+    opacity: 0;
+    transform: translateY(20rpx);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
+.form-card {
+  animation: fadeInUp 0.4s ease-out;
+}
+
+.image-section {
+  animation: fadeInUp 0.4s ease-out 0.1s both;
+}
+
+.closing-area {
+  animation: fadeInUp 0.4s ease-out 0.2s both;
 }

+ 137 - 80
bgj/workOrder/nodes/report/index.wxml

@@ -1,107 +1,149 @@
 <view class="page">
 
-  <!-- logo 区域(接口未知,先留空) -->
-  <view class="logo-area" wx:if="{{logoUrl}}">
-    <image class="logo-img" src="{{logoUrl}}" mode="aspectFit" />
-  </view>
-
-  <!-- 标题 -->
-  <view class="title-area">
-    <text class="title-text">{{dealerName}}{{language['施工进度汇报']||'施工进度汇报'}}</text>
-  </view>
-
-  <!-- 表格区域 -->
-  <view class="form-area">
-    <!-- 日期 -->
-    <view class="form-row">
-      <view class="form-label">{{language['日期']||'日期'}}</view>
-      <view class="form-value">{{form.date}}</view>
+  <!-- 头部渐变背景 -->
+  <view class="header-bg">
+    <!-- logo 区域 -->
+    <view class="logo-area" wx:if="{{logoUrl}}">
+      <image class="logo-img" src="{{logoUrl}}" mode="aspectFit" />
     </view>
 
-    <!-- 天气(接口未知,先留空) -->
-    <view class="form-row">
-      <view class="form-label">{{language['天气']||'天气'}}</view>
-      <view class="form-value">
-        <input class="form-input" value="{{form.weather}}" placeholder="{{language['请输入天气']||'请输入天气'}}" bindinput="onFieldInput" data-key="weather" />
-      </view>
+    <!-- 标题 -->
+    <view class="title-area">
+      <text class="title-text">{{dealerName}}{{language['施工进度汇报']||'施工进度汇报'}}</text>
     </view>
 
-    <!-- 项目名称(必填) -->
-    <view class="form-row">
-      <view class="form-label"><text class="required-star">*</text>{{language['项目名称']||'项目名称'}}</view>
-      <view class="form-value">
-        <input class="form-input" value="{{form.projectName}}" placeholder="{{language['请输入项目名称']||'请输入项目名称'}}" bindinput="onFieldInput" data-key="projectName" />
-      </view>
+    <!-- 日期标签 -->
+    <view class="date-badge">
+      <text class="date-tag">📅 {{form.date}}</text>
     </view>
+  </view>
 
-    <!-- 施工部位 -->
-    <view class="form-row">
-      <view class="form-label">{{language['施工部位']||'施工部位'}}</view>
-      <view class="form-value">
-        <input class="form-input" value="{{form.constructionPart}}" placeholder="{{language['请输入施工部位']||'请输入施工部位'}}" bindinput="onFieldInput" data-key="constructionPart" />
+  <!-- 主内容区 -->
+  <view class="main-content">
+    <!-- 基本信息卡片 -->
+    <view class="form-card">
+      <view class="card-header">
+        <view class="card-icon">
+          <text style="color: #fff; font-size: 24rpx;">📋</text>
+        </view>
+        <text class="card-title">{{language['基本信息']||'基本信息'}}</text>
       </view>
-    </view>
-
-    <!-- 品牌 -->
-    <view class="form-row">
-      <view class="form-label">{{language['品牌']||'品牌'}}</view>
-      <view class="form-value">{{form.brandName || '--'}}</view>
-    </view>
-
-    <!-- 工作内容(必填) -->
-    <view class="form-row">
-      <view class="form-label"><text class="required-star">*</text>{{language['工作内容']||'工作内容'}}</view>
-      <view class="form-value">
-        <input class="form-input" value="{{form.workContent}}" placeholder="{{language['请输入工作内容']||'请输入工作内容'}}" bindinput="onFieldInput" data-key="workContent" />
+      <view class="form-area">
+        <!-- 天气 -->
+        <view class="form-row">
+          <view class="form-label">{{language['天气']||'天气'}}</view>
+          <view class="form-value">
+            <textarea class="form-textarea" value="{{form.weather}}" placeholder="{{language['请输入天气']||'请输入天气'}}" auto-height bindinput="onFieldInput" data-key="weather" />
+          </view>
+        </view>
+
+        <!-- 项目名称(必填) -->
+        <view class="form-row">
+          <view class="form-label"><text class="required-star">*</text>{{language['项目名称']||'项目名称'}}</view>
+          <view class="form-value">
+            <textarea class="form-textarea" value="{{form.projectName}}" placeholder="{{language['请输入项目名称']||'请输入项目名称'}}" auto-height bindinput="onFieldInput" data-key="projectName" />
+          </view>
+        </view>
+
+        <!-- 施工部位 -->
+        <view class="form-row">
+          <view class="form-label">{{language['施工部位']||'施工部位'}}</view>
+          <view class="form-value">
+            <textarea class="form-textarea" value="{{form.constructionPart}}" placeholder="{{language['请输入施工部位']||'请输入施工部位'}}" auto-height bindinput="onFieldInput" data-key="constructionPart" />
+          </view>
+        </view>
+
+        <!-- 品牌 -->
+        <view class="form-row">
+          <view class="form-label">{{language['品牌']||'品牌'}}</view>
+          <view class="form-value">{{form.brandName || '--'}}</view>
+        </view>
       </view>
     </view>
 
-    <!-- 人员情况 -->
-    <view class="form-row">
-      <view class="form-label">{{language['人员情况']||'人员情况'}}</view>
-      <view class="form-value">{{form.reporter || '--'}}</view>
-    </view>
-
-    <!-- 遇到的问题 -->
-    <view class="form-row">
-      <view class="form-label">{{language['遇到的问题']||'遇到的问题'}}</view>
-      <view class="form-value">
-        <textarea class="form-textarea" value="{{form.problem}}" placeholder="{{language['请输入遇到的问题']||'请输入遇到的问题'}}" maxlength="500" auto-height bindinput="onFieldInput" data-key="problem" />
+    <!-- 工作内容卡片 -->
+    <view class="form-card">
+      <view class="card-header">
+        <view class="card-icon">
+          <text style="color: #fff; font-size: 24rpx;">🔧</text>
+        </view>
+        <text class="card-title">{{language['工作详情']||'工作详情'}}</text>
+      </view>
+      <view class="form-area">
+        <!-- 工作内容(必填) -->
+        <view class="form-row">
+          <view class="form-label"><text class="required-star">*</text>{{language['工作内容']||'工作内容'}}</view>
+          <view class="form-value">
+            <textarea class="form-textarea" value="{{form.workContent}}" placeholder="{{language['请输入工作内容']||'请输入工作内容'}}" auto-height bindinput="onFieldInput" data-key="workContent" />
+          </view>
+        </view>
+
+        <!-- 人员情况 -->
+        <view class="form-row">
+          <view class="form-label">{{language['人员情况']||'人员情况'}}</view>
+          <view class="form-value">{{form.reporter || '--'}}</view>
+        </view>
       </view>
     </view>
 
-    <!-- 需协调的内容 -->
-    <view class="form-row">
-      <view class="form-label">{{language['需协调的内容']||'需协调的内容'}}</view>
-      <view class="form-value">
-        <textarea class="form-textarea" value="{{form.coordinationNeeded}}" placeholder="{{language['请输入需协调的内容']||'请输入需协调的内容'}}" maxlength="500" auto-height bindinput="onFieldInput" data-key="coordinationNeeded" />
+    <!-- 问题与计划卡片 -->
+    <view class="form-card">
+      <view class="card-header">
+        <view class="card-icon">
+          <text style="color: #fff; font-size: 24rpx;">💡</text>
+        </view>
+        <text class="card-title">{{language['问题与计划']||'问题与计划'}}</text>
+      </view>
+      <view class="form-area">
+        <!-- 遇到的问题 -->
+        <view class="form-row">
+          <view class="form-label">{{language['遇到的问题']||'遇到的问题'}}</view>
+          <view class="form-value">
+            <textarea class="form-textarea" value="{{form.problem}}" placeholder="{{language['请输入遇到的问题']||'请输入遇到的问题'}}" maxlength="500" auto-height bindinput="onFieldInput" data-key="problem" />
+          </view>
+        </view>
+
+        <!-- 需协调的内容 -->
+        <view class="form-row">
+          <view class="form-label">{{language['需协调的内容']||'需协调的内容'}}</view>
+          <view class="form-value">
+            <textarea class="form-textarea" value="{{form.coordinationNeeded}}" placeholder="{{language['请输入需协调的内容']||'请输入需协调的内容'}}" maxlength="500" auto-height bindinput="onFieldInput" data-key="coordinationNeeded" />
+          </view>
+        </view>
+
+        <!-- 下步计划 -->
+        <view class="form-row">
+          <view class="form-label">{{language['下步计划']||'下步计划'}}</view>
+          <view class="form-value">
+            <textarea class="form-textarea" value="{{form.nextPlan}}" placeholder="{{language['请输入下步计划']||'请输入下步计划'}}" maxlength="500" auto-height bindinput="onFieldInput" data-key="nextPlan" />
+          </view>
+        </view>
       </view>
     </view>
 
-    <!-- 下步计划 -->
-    <view class="form-row">
-      <view class="form-label">{{language['下步计划']||'下步计划'}}</view>
-      <view class="form-value">
-        <textarea class="form-textarea" value="{{form.nextPlan}}" placeholder="{{language['请输入下步计划']||'请输入下步计划'}}" maxlength="500" auto-height bindinput="onFieldInput" data-key="nextPlan" />
+    <!-- 图片区域 -->
+    <view class="image-section" wx:if="{{imageList.length}}">
+      <view class="section-header">
+        <view class="section-icon">
+          <text style="color: #fff; font-size: 20rpx;">📷</text>
+        </view>
+        <text class="section-title">{{language['现场照片']||'现场照片'}}</text>
+      </view>
+      <view class="image-card">
+        <view class="image-area">
+          <view class="image-item" wx:for="{{imageList}}" wx:key="url" catch:tap="previewImage" data-url="{{item.url}}">
+            <image class="image-thumb" src="{{item.url}}" mode="aspectFill" />
+          </view>
+        </view>
       </view>
     </view>
-  </view>
 
-  <!-- 图片区域 -->
-  <view class="section-title" wx:if="{{imageList.length}}">
-    <text>{{language['现场照片']||'现场照片'}}</text>
-  </view>
-  <view class="image-area" wx:if="{{imageList.length}}">
-    <view class="image-item" wx:for="{{imageList}}" wx:key="url" catch:tap="previewImage" data-url="{{item.url}}">
-      <image class="image-thumb" src="{{item.url}}" mode="aspectFill" />
+    <!-- 结束语 -->
+    <view class="closing-area" wx:if="{{closingText}}">
+      <text class="closing-text">{{closingText}}</text>
     </view>
   </view>
 
-  <!-- 结束语(接口未知,先留空) -->
-  <view class="closing-area" wx:if="{{closingText}}">
-    <text class="closing-text">{{closingText}}</text>
-  </view>
-
   <view style="height: 160rpx;" />
 
   <!-- 底部按钮 -->
@@ -118,4 +160,19 @@
     </view>
   </view>
 
+  <!-- 自定义分享弹窗 -->
+  <van-popup show="{{showSharePopup}}" position="bottom" round bind:close="closeSharePopup">
+    <view class="share-popup">
+      <view class="share-popup-title">{{language['分享到']||'分享到'}}</view>
+      <button class="share-option" open-type="share" bindtap="onShareFriends">
+        <text>{{language['转发给朋友']||'转发给朋友'}}</text>
+      </button>
+      <view class="share-option" bindtap="handleShareTimeline">
+        <text>{{language['转发到朋友圈']||'转发到朋友圈'}}</text>
+      </view>
+      <view class="share-cancel" bindtap="closeSharePopup">
+        <text>{{language['取消']||'取消'}}</text>
+      </view>
+    </view>
+  </van-popup>
 </view>

+ 66 - 0
bgj/workOrder/nodes/report/share.js

@@ -0,0 +1,66 @@
+// bgj/workOrder/nodes/report/share.js
+Page({
+
+    /**
+     * 页面的初始数据
+     */
+    data: {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面加载
+     */
+    onLoad(options) {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面初次渲染完成
+     */
+    onReady() {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面显示
+     */
+    onShow() {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面隐藏
+     */
+    onHide() {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面卸载
+     */
+    onUnload() {
+
+    },
+
+    /**
+     * 页面相关事件处理函数--监听用户下拉动作
+     */
+    onPullDownRefresh() {
+
+    },
+
+    /**
+     * 页面上拉触底事件的处理函数
+     */
+    onReachBottom() {
+
+    },
+
+    /**
+     * 用户点击右上角分享
+     */
+    onShareAppMessage() {
+
+    }
+})

+ 3 - 0
bgj/workOrder/nodes/report/share.json

@@ -0,0 +1,3 @@
+{
+    "usingComponents": {}
+}

+ 1 - 0
bgj/workOrder/nodes/report/share.scss

@@ -0,0 +1 @@
+/* bgj/workOrder/nodes/report/share.wxss */

+ 2 - 0
bgj/workOrder/nodes/report/share.wxml

@@ -0,0 +1,2 @@
+<!--bgj/workOrder/nodes/report/share.wxml-->
+<text>bgj/workOrder/nodes/report/share.wxml</text>

+ 4 - 1
bgj/workOrder/nodes/update/update.js

@@ -566,9 +566,12 @@ Page({
         }
       }
 
-      // 保存工序,带上天气信息
+      // 保存工序,带上天气和日期信息
       const content = this.buildContent(1);
       content.weather = weather;
+      // 当前日期 YYYY-MM-DD
+      const now = new Date();
+      content.weatherdate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
 
       const res = await _Http.basic({
         id: 2026052814061302,