Browse Source

fix: resolve merge conflicts and sync build artifacts

Sisyphus 2 months ago
parent
commit
48b059bfdb

+ 0 - 69
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminActivityController.java

@@ -12,7 +12,6 @@ import java.util.Map;
  * 后台活动管理接口
  * - 活动列表(包含草稿)
  * - 审核活动(发布/删除)
- * - 活动工作流(提交审核/审核/撤回/重新编辑)
  */
 @RestController
 @RequestMapping("/api/admin/activity")
@@ -39,74 +38,6 @@ public class AdminActivityController {
         return activityAdminService.review(params);
     }
 
-    /**
-     * 提交审核(draft → pending)
-     */
-    @PostMapping("/submit-review")
-    public Result<String> submitReview(@RequestBody Map<String, Object> params) {
-        Long id = params.get("id") != null ? Long.valueOf(params.get("id").toString()) : null;
-        if (id == null) return Result.error("id不能为空");
-        try {
-            activityAdminService.submitForReview(id);
-            return Result.success("已提交审核");
-        } catch (RuntimeException e) {
-            return Result.error(e.getMessage());
-        }
-    }
-
-    /**
-     * 审核活动(pending → approved/rejected)
-     */
-    @PostMapping("/audit")
-    public Result<String> audit(@RequestBody Map<String, Object> params,
-                                 @RequestAttribute("userId") Long adminId) {
-        Long id = params.get("id") != null ? Long.valueOf(params.get("id").toString()) : null;
-        String action = (String) params.get("action");
-        String auditReason = (String) params.get("auditReason");
-        if (id == null) return Result.error("id不能为空");
-        if (action == null) return Result.error("action不能为空(approved/rejected)");
-        if ("rejected".equals(action) && (auditReason == null || auditReason.trim().isEmpty())) {
-            return Result.error("驳回时必须填写原因");
-        }
-        try {
-            activityAdminService.auditActivity(id, action, auditReason, adminId);
-            String msg = "approved".equals(action) ? "审核通过" : "已驳回";
-            return Result.success(msg);
-        } catch (RuntimeException e) {
-            return Result.error(e.getMessage());
-        }
-    }
-
-    /**
-     * 撤回活动(published → withdrawn)
-     */
-    @PostMapping("/withdraw")
-    public Result<String> withdraw(@RequestBody Map<String, Object> params) {
-        Long id = params.get("id") != null ? Long.valueOf(params.get("id").toString()) : null;
-        if (id == null) return Result.error("id不能为空");
-        try {
-            activityAdminService.withdraw(id);
-            return Result.success("已撤回");
-        } catch (RuntimeException e) {
-            return Result.error(e.getMessage());
-        }
-    }
-
-    /**
-     * 驳回后重新编辑(rejected → draft)
-     */
-    @PostMapping("/re-draft")
-    public Result<String> reDraft(@RequestBody Map<String, Object> params) {
-        Long id = params.get("id") != null ? Long.valueOf(params.get("id").toString()) : null;
-        if (id == null) return Result.error("id不能为空");
-        try {
-            activityAdminService.reDraft(id);
-            return Result.success("已保存到草稿箱");
-        } catch (RuntimeException e) {
-            return Result.error(e.getMessage());
-        }
-    }
-
     /**
      * 获取活动详情
      */

+ 24 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/Supplier.java

@@ -0,0 +1,24 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@TableName("supplier")
+public class Supplier implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String name;
+    private String contactName;
+    private String contactPhone;
+    private Long supplySystemId;
+    private BigDecimal commissionRate;
+    private String status;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 21 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/SupplyRelationship.java

@@ -0,0 +1,21 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("supply_relationship")
+public class SupplyRelationship implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long supplierId;
+    private Long productId;
+    private String relationType;
+    private String status;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 27 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/SupplySettlement.java

@@ -0,0 +1,27 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@TableName("supply_settlement")
+public class SupplySettlement implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long supplierId;
+    private Long supplySystemId;
+    private Long orderId;
+    private BigDecimal totalAmount;
+    private BigDecimal platformProfit;
+    private BigDecimal supplierIncome;
+    private BigDecimal commissionAmount;
+    private String status;
+    private Date settlementDate;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 25 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/SupplySettlementItem.java

@@ -0,0 +1,25 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@TableName("supply_settlement_item")
+public class SupplySettlementItem implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long settlementId;
+    private Long productId;
+    private String productName;
+    private Integer quantity;
+    private BigDecimal unitPrice;
+    private BigDecimal subtotal;
+    private BigDecimal commissionRate;
+    private BigDecimal commissionAmount;
+    private Date createdAt;
+}

+ 24 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/SupplySystem.java

@@ -0,0 +1,24 @@
+package com.etotem.cfc.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@TableName("supply_system")
+public class SupplySystem implements Serializable {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String name;
+    private Long adminId;
+    private Integer settlementPeriodDays;
+    private BigDecimal platformProfitRate;
+    private String description;
+    private String status;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/mapper/SupplierMapper.java

@@ -0,0 +1,9 @@
+package com.etotem.cfc.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.etotem.cfc.entity.Supplier;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SupplierMapper extends BaseMapper<Supplier> {
+}

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/mapper/SupplySystemMapper.java

@@ -0,0 +1,9 @@
+package com.etotem.cfc.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.etotem.cfc.entity.SupplySystem;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SupplySystemMapper extends BaseMapper<SupplySystem> {
+}

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-c438751253e85819675d036a5c86d03661854833
+34eaf000892bd22a570d9efcbe2d8a6d13503ff3

+ 1 - 1
cfc-web/package.json

@@ -1,6 +1,6 @@
 {
   "name": "cfc-web",
-  "version": "1.0.5",
+  "version": "1.0.6",
   "private": true,
   "scripts": {
     "dev": "vue-cli-service serve",

+ 83 - 0
cfc-web/public/CHANGELOG.md

@@ -0,0 +1,83 @@
+# 文档变更记录
+
+## 2026-06-14 — 文档归档整理
+
+### 变更说明
+
+为消除开发干扰,将历史需求和设计文档迁移至 `docs/backup/`,主目录仅保留最新版本的文档。
+
+### 保留的文档
+
+| 目录 | 文件 | 说明 |
+|------|------|------|
+| `需求分析/` | `底签页面详细设计.md` | 5个 TabBar 页面详细设计 v2.0(含首页/身泰/心智/行远/富沛) |
+| | `TabBar重构需求.md` | 5-Tab 重构原始需求 |
+| | `健康能量设计.md` | 五维能量系统设计 |
+| | `会员与分销体系设计.md` | 会员等级与分销体系 |
+| `系统设计/` | `小程序页面重设计划.md` | 小程序页面改造规划 |
+| `设计/` | `角色权限-UC矩阵-v2.md` | 角色权限矩阵 |
+| `superpowers/specs/` | `2026-06-13-five-dimension-pages-redesign.md` | **三页统一改造设计**(含堆叠图、游客模式、权限模型) |
+| | `2026-06-04-pre-login-discovery-design.md` | 登录前浏览设计 |
+| | `2026-06-02-care-family-club-design.md` | 平台升级设计规格(哲学/架构) |
+| | `2026-06-05-five-dimension-energy-design.md` | 五维能量系统设计 |
+| | `2026-06-08-article-publishing-system-design.md` | 文章发布系统设计 |
+| | `2026-06-08-five-dimension-wuxing-philosophy.md` | 五行哲学对照 |
+| `superpowers/plans/` | `2026-06-13-five-dimension-pages-redesign.md` | **三页改造实施计划**(10 Task) |
+| | `2026-06-13-guest-mode-implementation.md` | **游客模式实施计划**(10 Task) |
+| | `2026-06-12-danshop-integration-design.md` | DanShop 电商集成设计(P0) |
+| | `2026-06-11-5-tab-pages.md` | 5 TabBar 页面实施计划 |
+
+## 2026-06-14 — 行远页新增「重要关系维护」功能
+
+### 变更说明
+
+行远(行动/木)页新增关系维护模块,用于管理用户的重要人际关系(家人/朋友/伴侣/同事等),支持从手机通讯录导入联系人。
+
+### 新增文件
+
+| 文件 | 类型 | 说明 |
+|------|:----:|------|
+| `docs/superpowers/specs/2026-06-14-action-page-relationship-design.md` | 设计 | 关系维护功能设计 |
+| `docs/superpowers/plans/2026-06-14-action-page-relationship.md` | 计划 | 关系维护实施计划 |
+| `cfc-backend/.../entity/Contact.java` | entity | 通讯录关系实体 |
+| `cfc-backend/.../service/ContactService.java` | service | 关系 CRUD + 导入逻辑 |
+| `cfc-backend/.../controller/ContactController.java` | controller | 关系 API 接口 |
+| `cfc-frontend/components/ContactCard.vue` | component | 关系卡片组件 |
+| `cfc-frontend/components/ContactImport.vue` | component | 通讯录导入浮层 |
+| `cfc-frontend/pages/action/contact-detail.vue` | page | 关系详情/编辑页 |
+
+### 核心设计决策
+
+| 决策 | 选择 |
+|------|------|
+| 关系归属维度 | **行远(行动)** — 五行属木,对应"关系践行、社群连接" |
+| 联系人导入 | 微信 `wx.chooseContact` + 后端查重 + 补充信息浮层 |
+| 亲密度 | 0-100 数值,根据 contactCount / lastContactAt 自动计算 + 用户可 ±20 微调 |
+| 关系区块位置 | 行远页「今日待办」与「热门活动」之间 |
+| 生日提醒 | 近期生日在卡片上标注"还有 N 天",后续可扩展推送 |
+| 互动记录 | 后端记录每次查看/编辑联系人(可选手动标记"联系了") |
+
+---
+
+### 核心设计决策(最新)
+
+| 决策 | 选择 |
+|------|------|
+| TabBar 5页 | 首页 / 身泰 / 心智 / 行远 / 富沛(始终可见) |
+| 首页角色分流 | 游客→发现页 / parent-index / child-index / teacher-index→收归 parent-index |
+| 心智双维度展示 | **堆叠图**:一根柱叠加心能量+智能量 |
+| 私密活动可见性 | `visibility` + `visibleScope`(family/role/user) + `visibleTo` 三字段 |
+| 游客价格 | 隐藏数值,显示"登录查看" |
+| 游客空数据 | 显示「登录后查看更多」占位 |
+| 后端过滤 | 根据 JWT + userId/role/familyId 统一过滤 |
+| 行远页新增 | 重要关系维护 + 通讯录导入 |
+
+### 已归档(移至 `docs/backup/`)
+
+| 原位置 | 文件 |
+|--------|------|
+| 需求分析/ | v1.2-心智增强-版本计划/阶段总结, 底签页面内容设计(旧版), 需求分析文档, 领域对比分析×4 |
+| 系统设计/ | 心知家庭-系统设计报告(.docx/.md) |
+| superpowers/specs/ | 2026-03/05/06月历史specs 共13个 |
+| superpowers/plans/ | 2026-03/05/06月历史plans 共23个 |
+| docs/根目录 | requirements-analysis.md, API-INTEGRATION.md, badge/dan/guide/report/task-requirements, 参考资料, product-plan, plans |

+ 37 - 135
cfc-web/src/views/admin/Activities.vue

@@ -4,9 +4,19 @@
       <div slot="header">
         <span>活动管理</span>
         <div style="float:right">
-          <div class="status-tabs" style="display:inline-block;margin-right:12px;">
-            <el-button v-for="tab in statusTabs" :key="tab.value" :type="filter.status === tab.value ? 'primary' : 'default'" size="mini" @click="filter.status = tab.value; filter.page = 1; loadActivities()">{{ tab.label }}</el-button>
-          </div>
+          <el-select
+            v-model="filter.status"
+            placeholder="状态筛选"
+            size="mini"
+            style="margin-right:12px;width:130px"
+            clearable
+            @change="loadActivities"
+          >
+            <el-option label="全部" value="" />
+            <el-option label="草稿" value="draft" />
+            <el-option label="已发布" value="published" />
+            <el-option label="已结束" value="ended" />
+          </el-select>
           <el-button type="primary" size="mini" @click="$router.push('/activity-edit')">创建活动</el-button>
         </div>
       </div>
@@ -36,51 +46,31 @@
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column label="状态" width="120">
+        <el-table-column label="状态" width="100">
           <template slot-scope="{ row }">
-            <el-tag :type="statusType(row.status)" size="mini" :title="row.status === 'rejected' ? (row.auditReason || '已驳回') : ''">
+            <el-tag :type="statusType(row.status)" size="mini">
               {{ statusLabel(row.status) }}
             </el-tag>
           </template>
         </el-table-column>
         <el-table-column prop="startTime" label="开始时间" width="170" />
         <el-table-column prop="endTime" label="结束时间" width="170" />
-        <el-table-column label="操作" width="320">
+        <el-table-column label="操作" width="280">
           <template slot-scope="{ row }">
-            <!-- 草稿箱 -->
-            <template v-if="row.status === 'draft' && !row.auditStatus">
-              <el-button size="mini" @click="$router.push('/activity-edit?id=' + row.id)">编辑</el-button>
-              <el-button size="mini" type="success" @click="handleSubmitReview(row)">提交审核</el-button>
-              <el-button size="mini" type="danger" plain @click="handlePublishDirect(row)">直接发布</el-button>
-            </template>
-            <!-- 待审核 -->
-            <template v-else-if="row.status === 'pending'">
-              <el-button size="mini" @click="$router.push('/activity-edit?id=' + row.id + '&readonly=1')">查看</el-button>
-              <el-button size="mini" type="success" @click="handleAuditApprove(row)">通过</el-button>
-              <el-button size="mini" type="danger" @click="showAuditRejectDialog(row)">驳回</el-button>
-            </template>
-            <!-- 已驳回 -->
-            <template v-else-if="row.status === 'rejected'">
-              <el-button size="mini" @click="$router.push('/activity-edit?id=' + row.id + '&readonly=1')">查看</el-button>
-              <el-button size="mini" type="primary" @click="handleReDraft(row)">重新编辑</el-button>
-            </template>
-            <!-- 发布中 -->
-            <template v-else-if="row.status === 'published'">
-              <el-button size="mini" @click="$router.push('/activity-edit?id=' + row.id + '&readonly=1')">查看</el-button>
-              <el-button size="mini" type="warning" @click="handleWithdraw(row)">撤回</el-button>
-            </template>
-            <!-- 已撤回 -->
-            <template v-else-if="row.status === 'withdrawn'">
-              <el-button size="mini" @click="$router.push('/activity-edit?id=' + row.id + '&readonly=1')">查看</el-button>
-              <el-button size="mini" type="success" @click="handlePublishDirect(row)">重新发布</el-button>
-            </template>
-            <!-- 其他(兼容旧状态) -->
-            <template v-else>
-              <el-button size="mini" @click="$router.push('/activity-edit?id=' + row.id + '&readonly=1')">查看</el-button>
-              <el-button v-if="row.status === 'draft'" size="mini" @click="$router.push('/activity-edit?id=' + row.id)">编辑</el-button>
-              <el-button v-if="row.status === 'draft'" size="mini" type="success" @click="handlePublishDirect(row)">发布</el-button>
-              <el-button v-if="row.status === 'published'" size="mini" type="warning" @click="handleEnd(row)">结束</el-button>
-            </template>
+            <el-button size="mini" @click="$router.push('/activity-edit?id=' + row.id + '&readonly=1')" v-if="row.status !== 'draft'">查看</el-button>
+            <el-button size="mini" @click="$router.push('/activity-edit?id=' + row.id)" v-else>编辑</el-button>
+            <el-button
+              size="mini"
+              type="success"
+              @click="handlePublish(row)"
+              v-if="row.status === 'draft'"
+            >发布</el-button>
+            <el-button
+              size="mini"
+              type="warning"
+              @click="handleEnd(row)"
+              v-if="row.status === 'published'"
+            >结束</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -97,16 +87,7 @@
       />
     </el-card>
 
-    <!-- 审核驳回弹窗 -->
-    <el-dialog title="驳回原因" :visible.sync="auditRejectDialogVisible" width="400px">
-      <el-input type="textarea" :rows="4" v-model="auditRejectReason" placeholder="请输入驳回原因..."></el-input>
-      <span slot="footer">
-        <el-button @click="auditRejectDialogVisible = false">取消</el-button>
-        <el-button type="primary" @click="confirmAuditReject">确认驳回</el-button>
-      </span>
-    </el-dialog>
-
-    <!-- 报名列表对话框 -->
+    <!-- 报名列表对话框(保留) -->
     <el-dialog
       :title="'报名列表 - ' + (currentActivity ? currentActivity.title : '')"
       :visible.sync="regDialogVisible"
@@ -143,14 +124,12 @@
 </template>
 
 <script>
-import { getActivityList, publishActivity, endActivity, getRegistrationList, approveRegistration, rejectRegistration, submitActivityReview, auditActivity, withdrawActivity, reDraftActivity } from '@/api/activity'
+import { getActivityList, publishActivity, endActivity, getRegistrationList, approveRegistration, rejectRegistration } from '@/api/activity'
 
 const STATUS_MAP = {
-  draft: { label: '草稿箱', type: 'info' },
-  pending: { label: '待审核', type: 'warning' },
-  rejected: { label: '已驳回', type: 'danger' },
-  published: { label: '发布中', type: 'success' },
-  withdrawn: { label: '已撤回', type: 'info' }
+  draft: { label: '草稿', type: 'info' },
+  published: { label: '已发布', type: 'success' },
+  ended: { label: '已结束', type: 'danger' }
 }
 const ACTIVITY_TYPE_MAP = {
   offline: '线下活动',
@@ -172,14 +151,6 @@ export default {
       loading: false,
       activities: [],
       total: 0,
-      statusTabs: [
-        { value: '', label: '全部' },
-        { value: 'draft', label: '草稿箱' },
-        { value: 'pending', label: '待审核' },
-        { value: 'rejected', label: '已驳回' },
-        { value: 'published', label: '发布中' },
-        { value: 'withdrawn', label: '已撤回' }
-      ],
       filter: {
         status: '',
         page: 1,
@@ -189,11 +160,7 @@ export default {
       regDialogVisible: false,
       regLoading: false,
       currentActivity: null,
-      registrations: [],
-      // 审核驳回
-      auditRejectDialogVisible: false,
-      auditRejectReason: '',
-      currentAuditRow: null
+      registrations: []
     }
   },
   created() {
@@ -244,76 +211,11 @@ export default {
       try {
         await publishActivity(row.id)
         this.$message.success('发布成功')
-
         this.loadActivities()
       } catch (e) {
         this.$message.error('发布失败')
       }
     },
-    async handleSubmitReview(row) {
-      try {
-        await submitActivityReview({ id: row.id })
-        this.$message.success('已提交审核')
-        this.loadActivities()
-      } catch (e) {
-        this.$message.error(e.message || '提交审核失败')
-      }
-    },
-    async handlePublishDirect(row) {
-      try {
-        await publishActivity(row.id)
-        this.$message.success('发布成功')
-        this.loadActivities()
-      } catch (e) {
-        this.$message.error('发布失败')
-      }
-    },
-    async handleAuditApprove(row) {
-      try {
-        await auditActivity({ id: row.id, action: 'approved' })
-        this.$message.success('审核通过')
-        this.loadActivities()
-      } catch (e) {
-        this.$message.error(e.message || '审核失败')
-      }
-    },
-    showAuditRejectDialog(row) {
-      this.currentAuditRow = row
-      this.auditRejectReason = ''
-      this.auditRejectDialogVisible = true
-    },
-    async confirmAuditReject() {
-      if (!this.auditRejectReason.trim()) {
-        this.$message.warning('请填写驳回原因')
-        return
-      }
-      this.auditRejectDialogVisible = false
-      try {
-        await auditActivity({ id: this.currentAuditRow.id, action: 'rejected', auditReason: this.auditRejectReason })
-        this.$message.success('已驳回')
-        this.loadActivities()
-      } catch (e) {
-        this.$message.error(e.message || '驳回失败')
-      }
-    },
-    async handleWithdraw(row) {
-      try {
-        await withdrawActivity({ id: row.id })
-        this.$message.success('已撤回')
-        this.loadActivities()
-      } catch (e) {
-        this.$message.error(e.message || '撤回失败')
-      }
-    },
-    async handleReDraft(row) {
-      try {
-        await reDraftActivity({ id: row.id })
-        this.$message.success('已保存到草稿箱')
-        this.loadActivities()
-      } catch (e) {
-        this.$message.error(e.message || '操作失败')
-      }
-    },
     async handleEnd(row) {
       try {
         await endActivity(row.id)
@@ -378,4 +280,4 @@ export default {
 
 <style scoped>
 .activities { padding: 20px; }
-</style>
+</style>