From 91491239c5d4611b5b1404a7abeb2bb23d0edad5 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期三, 30 九月 2026 14:26:59 +0800
Subject: [PATCH] feat(wxcp): 活动封面改用附件中间表,报名姓名手机号改为选填

---
 docs/sql/wxcp_module.sql                                                                                                 |   20 +++
 yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityPublicController.java |   70 ++++++++++++-
 yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityServiceImpl.java               |  120 ++++++++++++++++++-----
 yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/storage/StorageRecordTypeEnum.java                |    1 
 docs/sql/config_export_all_20260929.sql                                                                                  |    1 
 yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/dal/dataobject/activity/WxCpActivityDO.java                 |    4 
 yudao-server/src/main/resources/application-test.yaml                                                                    |    2 
 yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityService.java                   |    8 +
 docs/wxcp_activity_integration.md                                                                                        |   25 ++++
 yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityController.java       |   17 ++
 yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivityRespVO.java        |    6 
 yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivitySaveReqVO.java     |    7 
 yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpSignupPublicReqVO.java     |    9 -
 13 files changed, 229 insertions(+), 61 deletions(-)

diff --git a/docs/sql/config_export_all_20260929.sql b/docs/sql/config_export_all_20260929.sql
index d9ea1fa..7f1cc1e 100644
--- a/docs/sql/config_export_all_20260929.sql
+++ b/docs/sql/config_export_all_20260929.sql
@@ -11469,7 +11469,6 @@
   `id`                 bigint       NOT NULL AUTO_INCREMENT                COMMENT '缂栧彿',
   `title`              varchar(128) NOT NULL                               COMMENT '娲诲姩鏍囬',
   `content`            text                                                COMMENT '娲诲姩璇︽儏',
-  `cover_url`          varchar(512)          DEFAULT ''                   COMMENT '灏侀潰鍥惧湴鍧�',
   `location`           varchar(255)          DEFAULT ''                   COMMENT '娲诲姩鍦扮偣',
   `start_time`         datetime              DEFAULT NULL                 COMMENT '娲诲姩寮�濮嬫椂闂�',
   `end_time`           datetime              DEFAULT NULL                 COMMENT '娲诲姩缁撴潫鏃堕棿',
diff --git a/docs/sql/wxcp_module.sql b/docs/sql/wxcp_module.sql
index a95f076..8f2a542 100644
--- a/docs/sql/wxcp_module.sql
+++ b/docs/sql/wxcp_module.sql
@@ -3,8 +3,9 @@
 -- 鐩爣搴擄細mom-jssm锛�36.213.150.237:10000锛�
 -- 璇存槑锛氶」鐩笉浣跨敤澶氱鎴凤紝鍥犳涓嶅惈 tenant_id 瀛楁
 --
--- 鎶ュ悕鎻愪氦鐨勫浘鐗�/闄勪欢涓嶈惤鏈ā鍧楃殑琛細
--- 缁熶竴璧� system_storage_attachment 涓棿琛紝record_type = 'wxcp_activity_signup'
+-- 娲诲姩灏侀潰銆佹姤鍚嶆彁浜ょ殑鍥剧墖/闄勪欢閮戒笉钀芥湰妯″潡鐨勮〃锛�
+-- 缁熶竴璧� system_storage_attachment 涓棿琛紝
+-- 娲诲姩灏侀潰 record_type = 'wxcp_activity'锛屾姤鍚嶉檮浠� record_type = 'wxcp_activity_signup'
 -- ============================================================
 
 -- ----------------------------
@@ -14,7 +15,6 @@
   `id`                 bigint       NOT NULL AUTO_INCREMENT                COMMENT '缂栧彿',
   `title`              varchar(128) NOT NULL                               COMMENT '娲诲姩鏍囬',
   `content`            text                                                COMMENT '娲诲姩璇︽儏',
-  `cover_url`          varchar(512)          DEFAULT ''                   COMMENT '灏侀潰鍥惧湴鍧�',
   `location`           varchar(255)          DEFAULT ''                   COMMENT '娲诲姩鍦扮偣',
   `start_time`         datetime              DEFAULT NULL                 COMMENT '娲诲姩寮�濮嬫椂闂�',
   `end_time`           datetime              DEFAULT NULL                 COMMENT '娲诲姩缁撴潫鏃堕棿',
@@ -86,3 +86,17 @@
   PRIMARY KEY (`id`),
   KEY `idx_status` (`status`)
 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '浼佷笟寰俊閫氱煡';
+
+-- ============================================================
+-- 鍗囩骇鑴氭湰锛氬皝闈㈠浘浠庛�屼笟鍔¤〃瀛樺湴鍧�銆嶆敼涓恒�岄檮浠朵腑闂磋〃銆�
+-- 宸插缓杩囧簱鐨勭幆澧冩墽琛屼竴娆″嵆鍙紱鏂板簱鎵ц涓婇潰鐨� CREATE TABLE 宸叉槸鏈�鏂扮粨鏋勶紝鏃犻渶鎵ц
+-- MySQL 鐨� ADD/DROP COLUMN 涓嶆敮鎸� IF NOT EXISTS锛岃繖閲屽厛鍒ゆ柇鍐嶆墽琛�
+-- ============================================================
+SET @exists = (SELECT COUNT(*) FROM information_schema.columns
+               WHERE table_schema = DATABASE() AND table_name = 'wxcp_activity' AND column_name = 'cover_url');
+SET @sql = IF(@exists > 0,
+              'ALTER TABLE `wxcp_activity` DROP COLUMN `cover_url`',
+              'SELECT 1');
+PREPARE stmt FROM @sql;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
diff --git a/docs/wxcp_activity_integration.md b/docs/wxcp_activity_integration.md
index ca5c0fd..b6fb4c4 100644
--- a/docs/wxcp_activity_integration.md
+++ b/docs/wxcp_activity_integration.md
@@ -52,7 +52,7 @@
 | id | Long | 淇敼鏃跺繀濉� | 缂栧彿 |
 | title | String | 鏄� | 娲诲姩鏍囬锛屸墹128 瀛楃 |
 | content | String | 鍚� | 娲诲姩璇︽儏 |
-| coverUrl | String | 鍚� | 灏侀潰鍥惧湴鍧� |
+| blobIds | Long[] | 鍚� | **灏侀潰鍥炬枃浠剁紪鍙�**锛屾渶澶� 1 涓紱涓嶄紶 = 涓嶆敼鍔ㄥ皝闈紝浼� `[]` = 娓呯┖灏侀潰 |
 | location | String | 鍚� | 娲诲姩鍦扮偣锛屸墹255 瀛楃 |
 | startTime | DateTime | 鍚� | 娲诲姩寮�濮嬫椂闂� |
 | endTime | DateTime | 鍚� | 娲诲姩缁撴潫鏃堕棿 |
@@ -72,6 +72,7 @@
 | signupCount | Integer | 宸叉姤鍚嶄汉鏁� |
 | pushStatus | Integer | 0鏈帹閫� 1宸叉帹閫� |
 | pushTime | DateTime | 鏈�杩戞帹閫佹椂闂� |
+| attachmentList | Object[] | **灏侀潰鍥鹃檮浠跺垪琛�**锛堟渶澶� 1 鏉★級锛屽瓧娈靛悓鎶ュ悕闄勪欢锛歚id`銆乣name`銆乣url`銆乣previewURL`銆乣downloadURL`銆傚垪琛ㄧ缉鐣ュ浘銆佽〃鍗曞洖鏄鹃兘浠庤繖閲屽彇 |
 
 ### 鎺ㄩ�佷笌浜岀淮鐮�
 
@@ -116,6 +117,18 @@
 |------|------|------|
 | GET | `/wxcp/activity/signup-page?id={娲诲姩缂栧彿}` | 鎶ュ悕钀藉湴椤� HTML锛岀敱鍚庣娓叉煋 |
 | POST | `/wxcp/activity/signup` | 鎻愪氦鎶ュ悕锛堟敮鎸� `content` 鏂囧瓧 + `blobIds` 闄勪欢锛� |
+
+**鎻愪氦鎶ュ悕璇锋眰鍙傛暟锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|------|------|------|------|
+| activityId | Long | 鏄� | 娲诲姩缂栧彿 |
+| name | String | 鍚� | 濮撳悕锛屸墹64 瀛楃 |
+| mobile | String | 鍚� | 鎵嬫満鍙凤紱**濉簡鎵嶆牎楠�** 11 浣嶆牸寮忥紝鐣欑┖閫氳繃 |
+| wxUserId | String | 鍚� | 浼佷笟寰俊鎴愬憳璐﹀彿 |
+| deptName | String | 鍚� | 閮ㄩ棬鍚嶇О |
+| content | String | 鍚� | 鍙備笌璇存槑 |
+| blobIds | Long[] | 鍚� | 闄勪欢鏂囦欢缂栧彿 |
 
 ### 鎶ュ悕缁熻涓庨檮浠�
 
@@ -180,7 +193,7 @@
 1. 鏂板缓娲诲姩 鈫� 淇濆瓨涓�**鑽夌**锛屾鏃舵壂鐮佹姤鍚嶄細鎻愮ず銆屾姤鍚嶅凡缁撴潫銆�
 2. 鐐广�屽彂甯冦�嶁啋 鐘舵�佸彉銆屽凡鍙戝竷銆嶏紝姝ゆ椂浜岀淮鐮佸拰鎶ュ悕椤垫墠鍙敤
 3. 鐐广�屾帹閫併�嶁啋 鎴愬憳浼佷笟寰俊鏀跺埌鍗$墖娑堟伅锛屾爣棰樹负娲诲姩鏍囬锛屾鏂囧惈**娲诲姩鏃堕棿 / 鍦扮偣 / 鎶ュ悕鎴 / 鍚嶉**锛屾寜閽�岀珛鍗虫姤鍚嶃�嶇洿杈炬姤鍚嶉〉
-4. 鎴愬憳鐐规寜閽垨鎵爜 鈫� 鎵撳紑鎶ュ悕椤� 鈫� 濉鍚嶅拰鎵嬫満鍙� 鈫� 鎻愪氦
+4. 鎴愬憳鐐规寜閽垨鎵爜 鈫� 鎵撳紑鎶ュ悕椤� 鈫掞紙鍙�夛級濉鍚嶅拰鎵嬫満鍙� + 浼犻檮浠� 鈫� 鎻愪氦
 5. 鎶ュ悕鎴愬姛 鈫� 娲诲姩 `signupCount` 鑷姩 +1
 6. 鍚庡彴鍦ㄦ椿鍔ㄨ鎯呯殑鎶ュ悕璁板綍鍒楄〃閲屽彲鐪嬪埌璇ユ垚鍛橈紝鍙墽琛屻�屽彇娑堟姤鍚嶃�嶃�岀鍒般��
 
@@ -219,9 +232,12 @@
 | 鎺ㄩ�佹垚鍔熷悗 | 娲诲姩 `pushStatus` 缃� 1銆乣pushTime` 璁板綍鏃堕棿锛涢噸澶嶆帹閫佷細瑕嗙洊杩欎袱涓瓧娈� |
 | 鎶ュ悕鏃堕棿绐楀彛 | 鏈埌 `signupStartTime` 鎴栧凡杩� `signupEndTime` 鍧囦笉鑳芥姤鍚� |
 | 鎶ュ悕鍚嶉 | `signupLimit=0` 琛ㄧず涓嶉檺锛涘凡婊℃椂鎻愮ず銆屾姤鍚嶄汉鏁板凡婊°�� |
-| 閲嶅鎶ュ悕 | 鏈変紒涓氬井淇¤韩浠芥寜鎴愬憳璐﹀彿鍒ら噸锛涙櫘閫氭祻瑙堝櫒鎸�**鎵嬫満鍙�**鍒ら噸 |
+| 鎶ュ悕濮撳悕/鎵嬫満鍙� | **鍧囦负閫夊~**銆傛墜鏈哄彿濉簡鎵嶆牎楠屾牸寮忥紝鐣欑┖鍏佽鎻愪氦 |
+| 閲嶅鎶ュ悕 | 鏈変紒涓氬井淇¤韩浠芥寜鎴愬憳璐﹀彿鍒ら噸锛涙病鏈夎处鍙蜂絾鏈夋墜鏈哄彿鍒欐寜鎵嬫満鍙峰垽閲嶏紱**涓よ�呴兘娌℃湁鏃朵笉鍋氬垽閲�**锛堟棤娉曞垽瀹氳韩浠斤紝姣忔鎻愪氦閮芥柊寤轰竴鏉★級 |
 | 鍙栨秷鍚庨噸鏂版姤鍚� | 澶嶇敤鍘熻褰曪紝涓嶄細浜х敓绗簩鏉″巻鍙� |
 | 鍙栨秷鎶ュ悕 | 娲诲姩 `signupCount` 鑷姩 -1 |
+| 灏侀潰鍥� | 涓嶅瓨涓氬姟琛ㄥ瓧娈碉紝瀛� `system_storage_attachment`锛坄record_type = wxcp_activity`锛夈�傚垹闄ゆ椿鍔ㄦ椂涓�骞舵竻鎺夐檮浠跺叧绯� |
+| 灏侀潰鍥惧睍绀� | 鎶ュ悕椤甸《閮ㄤ互 `object-fit: cover` 灞曠ず锛涚鐞嗗悗鍙板垪琛ㄥ湪鏍囬宸︿晶鏄剧ず缂╃暐鍥� |
 
 ## 娉ㄦ剰浜嬮」
 
@@ -236,6 +252,9 @@
 - **鎺ㄩ�佺洰鏍囩敤鐨勬槸 `userId`锛堟垚鍛樿处鍙凤紝濡� `LiuYi`锛夛紝涓嶆槸濮撳悕銆佷篃涓嶆槸鎵嬫満鍙枫��** 浠庨�氳褰曟帴鍙e彇 `userId` 濉繘 `pushTarget`銆�
 - **闄勪欢涓婁紶璧� system 妯″潡鐨勫叕鍏变笂浼犳帴鍙�**锛氭姤鍚嶉〉鍏堣皟 `POST /admin-api/system/storage-blob/public-upload`锛堣〃鍗曞瓧娈靛悕 `files`锛夋嬁鍒� `blobId`锛屽啀鎶� `blobIds` 闅忔姤鍚嶆彁浜わ紝鐢�**鏈嶅姟绔�**瀹屾垚涓庢姤鍚嶈褰曠殑缁戝畾銆傜鐞嗗悗鍙版煡闄勪欢鐢� `/wxcp/activity/signup/attachments`銆�
 - **鎶ュ悕鐨� `recordType` 鍥哄畾涓� `wxcp_activity_signup`**锛屽凡娉ㄥ唽杩� system 妯″潡鐨� `StorageRecordTypeEnum` 鐧藉悕鍗曘�備互鍚庢柊澧炲埆鐨勯檮浠跺叧鑱旂被鍨嬶紝蹇呴』鍚屾娉ㄥ唽锛屽惁鍒欑粦瀹氫細鎶ャ�屾棤鏁堢殑璁板綍绫诲瀷銆嶃��
+- **娲诲姩灏侀潰鐨� `recordType` 涓� `wxcp_activity`**锛屽悓鏍峰凡娉ㄥ唽杩涚櫧鍚嶅崟銆傚皝闈�**涓嶅啀鏈� `coverUrl` 瀛楁**锛宍POST/PUT /wxcp/activity/create|update` 鎻愪氦 `blobIds`锛宍GET` 璇� `attachmentList`銆�
+- **灏侀潰鍥惧湪鎶ュ悕椤垫樉绀烘椂浼氬幓鎺夊崗璁拰鍩熷悕**銆傞檮浠跺湴鍧�閲岀殑鍩熷悕鍙栬嚜 `yudao.storage.domain`锛堜竴鑸槸鍐呯綉鍦板潃锛夛紝鑰屾墜鏈烘壂鐮佹槸浠庡叕缃戝煙鍚嶆墦寮�椤甸潰鐨勶紝鐩磋繛鍐呯綉鍦板潃鍔犺浇涓嶅嚭鍥剧墖锛屾墍浠ュ悗绔彧淇濈暀 `/admin-api/...` 璺緞浜ょ粰鍚屾簮浠g悊銆�**濡傛灉閮ㄧ讲鏃剁鐞嗗悗鍙颁笌鎶ュ悕椤典笉鍚屾簮锛岃繖涓鐞嗛渶瑕侀噸鏂拌瘎浼般��**
+- 琛ㄥ崟閲岀殑灏侀潰鐢� `ImageUpload` 缁勪欢锛坄maxNumber: 1`锛夋椂锛岀粍浠惰繑鍥炵殑鏄�**鍗曞�艰�屼笉鏄暟缁�**锛屾彁浜ゅ墠蹇呴』鍖呮垚鏁扮粍锛坄blobIds` 鍚庣绛惧悕鏄� `List<Long>`锛夈��
 - 閫氳褰曟帴鍙�**瀹炴椂璋冧紒涓氬井淇�**锛屾湁棰戠巼闄愬埗锛屽墠绔姟蹇呯紦瀛橈紝涓嶈闅忚緭鍏ュ疄鏃惰姹傘��
 - 閫氱煡姝f枃瓒呰繃 600 瀛椾細**鑷姩鎴柇**锛堜紒涓氬井淇℃枃鏈秷鎭湁闀垮害涓婇檺锛夛紝鎴柇鎻愮ず浼氬啓鍦ㄦ秷鎭湯灏俱��
 
diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/storage/StorageRecordTypeEnum.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/storage/StorageRecordTypeEnum.java
index b230c41..cf90237 100644
--- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/storage/StorageRecordTypeEnum.java
+++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/enums/storage/StorageRecordTypeEnum.java
@@ -85,6 +85,7 @@
     ARCHIVE_DOCUMENT("archive_document", "妗f"),
 
     // ===== 浼佷笟寰俊娲诲姩 =====
+    WXCP_ACTIVITY("wxcp_activity", "浼佷笟寰俊娲诲姩灏侀潰"),
     WXCP_ACTIVITY_SIGNUP("wxcp_activity_signup", "浼佷笟寰俊娲诲姩鎶ュ悕");
 
     private final String type;
diff --git a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityController.java b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityController.java
index 8e3cefe..76e21ae 100644
--- a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityController.java
+++ b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityController.java
@@ -83,7 +83,9 @@
     @PreAuthorize("@ss.hasPermission('wxcp:activity:query')")
     public CommonResult<PageResult<WxCpActivityRespVO>> getActivityPage(@Valid WxCpActivityPageReqVO pageReqVO) {
         PageResult<WxCpActivityDO> pageResult = activityService.getActivityPage(pageReqVO);
-        return success(BeanUtils.toBean(pageResult, WxCpActivityRespVO.class, this::fillActivityNames));
+        PageResult<WxCpActivityRespVO> result = BeanUtils.toBean(pageResult, WxCpActivityRespVO.class);
+        result.getList().forEach(this::fillActivityExtra);
+        return success(result);
     }
 
     @PutMapping("/publish")
@@ -206,15 +208,24 @@
             return null;
         }
         WxCpActivityRespVO vo = BeanUtils.toBean(activity, WxCpActivityRespVO.class);
-        fillActivityNames(vo);
+        fillActivityExtra(vo);
         return vo;
     }
 
-    private void fillActivityNames(WxCpActivityRespVO vo) {
+    /**
+     * 琛ラ綈鐘舵�佸悕銆佹帹閫佽寖鍥村悕涓庡皝闈㈤檮浠�
+     *
+     * 灏侀潰涓嶈惤涓氬姟琛ㄥ瓧娈碉紝缁熶竴浠� system_storage_attachment 涓棿琛ㄨ锛�
+     * 鍓嶇鍙� attachmentList[0].previewURL 灞曠ず銆�
+     */
+    private void fillActivityExtra(WxCpActivityRespVO vo) {
         WxCpActivityStatusEnum status = WxCpActivityStatusEnum.valueOf(vo.getStatus());
         vo.setStatusName(status != null ? status.getName() : null);
         WxCpPushScopeEnum scope = WxCpPushScopeEnum.valueOf(vo.getPushScope());
         vo.setPushScopeName(scope != null ? scope.getName() : null);
+        if (vo.getId() != null) {
+            vo.setAttachmentList(activityService.getActivityAttachments(vo.getId()));
+        }
     }
 
 }
diff --git a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityPublicController.java b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityPublicController.java
index be902a8..6acbdcb 100644
--- a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityPublicController.java
+++ b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/WxCpActivityPublicController.java
@@ -1,7 +1,9 @@
 package cn.iocoder.yudao.module.wxcp.controller.admin.activity;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.system.controller.admin.storage.vo.SystemStorageBlobRespVO;
 import cn.iocoder.yudao.module.wxcp.controller.admin.activity.vo.WxCpSignupPublicReqVO;
 import cn.iocoder.yudao.module.wxcp.dal.dataobject.activity.WxCpActivityDO;
 import cn.iocoder.yudao.module.wxcp.enums.activity.WxCpActivityStatusEnum;
@@ -17,8 +19,10 @@
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.net.URI;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
@@ -91,6 +95,7 @@
                 .append("body{margin:0;padding:16px;font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei',sans-serif;")
                 .append("background:#f5f6f8;color:#1f2329;font-size:15px;line-height:1.6}")
                 .append(".card{background:#fff;border-radius:12px;padding:18px;margin-bottom:12px;box-shadow:0 1px 4px rgba(0,0,0,.06)}")
+                .append(".cover{display:block;width:100%;max-height:260px;object-fit:cover;border-radius:8px;margin-bottom:14px;background:#f2f3f5}")
                 .append("h1{font-size:19px;margin:0 0 14px;font-weight:600;word-break:break-all}")
                 .append(".meta{color:#646a73;font-size:14px}")
                 .append(".meta div{margin-bottom:6px;display:flex}")
@@ -113,7 +118,13 @@
                 .append("</style></head><body>");
 
         // 娲诲姩淇℃伅
-        sb.append("<div class=\"card\"><h1>").append(esc(activity.getTitle())).append("</h1>")
+        sb.append("<div class=\"card\">");
+        // 灏侀潰鍥撅細鏉ヨ嚜闄勪欢涓棿琛紙record_type = wxcp_activity锛夛紝涓氬姟琛ㄤ笉瀛樻枃浠跺湴鍧�
+        String coverUrl = resolveCoverUrl(activity.getId());
+        if (StrUtil.isNotBlank(coverUrl)) {
+            sb.append("<img class=\"cover\" src=\"").append(esc(coverUrl)).append("\" alt=\"娲诲姩灏侀潰\">");
+        }
+        sb.append("<h1>").append(esc(activity.getTitle())).append("</h1>")
                 .append("<div class=\"meta\">");
         String timeText = formatTimeRange(activity.getStartTime(), activity.getEndTime());
         if (StrUtil.isNotBlank(timeText)) {
@@ -139,12 +150,12 @@
         }
         sb.append("</div>");
 
-        // 鎶ュ悕琛ㄥ崟
+        // 鎶ュ悕琛ㄥ崟锛氬鍚嶃�佹墜鏈哄彿鍧囦负閫夊~锛屽彧濉簡鎵嬫満鍙锋墠鏍¢獙鏍煎紡
         sb.append("<div class=\"card\">")
-                .append("<label>濮撳悕 <span style=\"color:#f53f3f\">*</span></label>")
-                .append("<input id=\"name\" type=\"text\" placeholder=\"璇疯緭鍏ュ鍚峔" maxlength=\"64\" autocomplete=\"name\">")
-                .append("<label>鎵嬫満鍙� <span style=\"color:#f53f3f\">*</span></label>")
-                .append("<input id=\"mobile\" type=\"tel\" inputmode=\"numeric\" placeholder=\"璇疯緭鍏� 11 浣嶆墜鏈哄彿\" maxlength=\"11\" autocomplete=\"tel\">")
+                .append("<label>濮撳悕</label>")
+                .append("<input id=\"name\" type=\"text\" placeholder=\"璇疯緭鍏ュ鍚嶏紙閫夊~锛塡" maxlength=\"64\" autocomplete=\"name\">")
+                .append("<label>鎵嬫満鍙�</label>")
+                .append("<input id=\"mobile\" type=\"tel\" inputmode=\"numeric\" placeholder=\"璇疯緭鍏� 11 浣嶆墜鏈哄彿锛堥�夊~锛塡" maxlength=\"11\" autocomplete=\"tel\">")
                 .append("<label>鍙備笌璇存槑</label>")
                 .append("<textarea id=\"content\" placeholder=\"鍙~鍐欏娉ㄣ�侀渶姹傛垨鍏朵粬璇存槑锛堥�夊~锛塡" maxlength=\"1000\"></textarea>")
                 .append("<label>鍥剧墖 / 闄勪欢</label>")
@@ -172,8 +183,7 @@
                 .append("var n=document.getElementById('name').value.trim();")
                 .append("var m=document.getElementById('mobile').value.trim();")
                 .append("var c=document.getElementById('content').value.trim();")
-                .append("if(!n){tip('璇峰~鍐欏鍚�');return}")
-                .append("if(!/^1[3-9]\\d{9}$/.test(m)){tip('鎵嬫満鍙锋牸寮忎笉姝g‘');return}")
+                .append("if(m&&!/^1[3-9]\\d{9}$/.test(m)){tip('鎵嬫満鍙锋牸寮忎笉姝g‘锛岃濉� 11 浣嶆墜鏈哄彿鎴栫暀绌�');return}")
                 .append("btn.disabled=true;")
                 .append("var fs=fileInput.files;")
                 .append("var upload=Promise.resolve([]);")
@@ -202,6 +212,50 @@
         return sb.toString();
     }
 
+    /**
+     * 鍙栨椿鍔ㄥ皝闈㈠湴鍧�锛堝彇闄勪欢鍒楄〃閲岀殑绗竴寮狅級
+     */
+    private String resolveCoverUrl(Long activityId) {
+        List<SystemStorageBlobRespVO> attachments = activityService.getActivityAttachments(activityId);
+        if (CollUtil.isEmpty(attachments)) {
+            return null;
+        }
+        SystemStorageBlobRespVO cover = attachments.get(0);
+        String raw = StrUtil.blankToDefault(cover.getPreviewURL(), cover.getUrl());
+        if (StrUtil.isBlank(raw)) {
+            return null;
+        }
+        return toSameOriginUrl(raw);
+    }
+
+    /**
+     * 鎶婇檮浠跺湴鍧�杞垚鍚屾簮鐩稿鍦板潃
+     *
+     * 闄勪欢閲屽瓨鐨勬槸甯︾鍚嶇殑缁濆鍦板潃锛屽煙鍚嶅彇鑷� yudao.storage.domain锛堥�氬父鏄唴缃戝湴鍧�锛夈��
+     * 鑰屾墜鏈烘壂鐮佹槸閫氳繃鍏綉鍩熷悕鎵撳紑鏈〉闈㈢殑锛岀洿杩炲唴缃戝湴鍧�浼氬姞杞戒笉鍑哄浘鐗囥��
+     * 杩欓噷鍓ユ帀鍗忚涓庡煙鍚嶅彧鐣� /admin-api/... 璺緞锛屼氦缁欏悓婧愪唬鐞嗚浆鍙戯紝
+     * 鍐呯綉銆佸叕缃戣闂兘鑳芥甯告樉绀猴紱鍥犱负鍙彇璺緞涓嶅彇鍩熷悕锛屼篃涓嶅瓨鍦ㄨ烦杞埌澶栭儴绔欑偣鐨勯闄┿��
+     */
+    private String toSameOriginUrl(String url) {
+        String trimmed = url.trim();
+        if (!StrUtil.startWithAnyIgnoreCase(trimmed, "http://", "https://")) {
+            return trimmed;
+        }
+        try {
+            URI uri = URI.create(trimmed);
+            String path = uri.getRawPath();
+            if (StrUtil.isBlank(path)) {
+                return trimmed;
+            }
+            String query = uri.getRawQuery();
+            return StrUtil.isBlank(query) ? path : path + "?" + query;
+        } catch (IllegalArgumentException e) {
+            // 鍦板潃涓嶅悎瑙勫氨鍘熸牱閫忓嚭锛屼笉鑳藉洜涓轰竴寮犲皝闈㈠浘璁╂暣椤垫墦涓嶅紑
+            log.warn("娲诲姩灏侀潰鍦板潃瑙f瀽澶辫触锛屾寜鍘熸牱杈撳嚭锛歿}", trimmed);
+            return trimmed;
+        }
+    }
+
     private String renderMessagePage(String title, String desc) {
         return "<!DOCTYPE html><html lang=\"zh-CN\"><head><meta charset=\"UTF-8\">"
                 + "<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"
diff --git a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivityRespVO.java b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivityRespVO.java
index fa93d79..13266ec 100644
--- a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivityRespVO.java
+++ b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivityRespVO.java
@@ -1,9 +1,11 @@
 package cn.iocoder.yudao.module.wxcp.controller.admin.activity.vo;
 
+import cn.iocoder.yudao.module.system.controller.admin.storage.vo.SystemStorageBlobRespVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 @Schema(description = "绠$悊鍚庡彴 - 浼佷笟寰俊娲诲姩 Response VO")
 @Data
@@ -18,8 +20,8 @@
     @Schema(description = "娲诲姩璇︽儏")
     private String content;
 
-    @Schema(description = "灏侀潰鍥惧湴鍧�")
-    private String coverUrl;
+    @Schema(description = "灏侀潰鍥鹃檮浠跺垪琛紙鏈�澶� 1 寮狅級")
+    private List<SystemStorageBlobRespVO> attachmentList;
 
     @Schema(description = "娲诲姩鍦扮偣", example = "鍏徃澶т細璁")
     private String location;
diff --git a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivitySaveReqVO.java b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivitySaveReqVO.java
index aa445ab..6680c22 100644
--- a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivitySaveReqVO.java
+++ b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpActivitySaveReqVO.java
@@ -9,6 +9,7 @@
 import lombok.Data;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 @Schema(description = "绠$悊鍚庡彴 - 浼佷笟寰俊娲诲姩 鍒涘缓/淇敼 Request VO")
 @Data
@@ -25,9 +26,9 @@
     @Schema(description = "娲诲姩璇︽儏")
     private String content;
 
-    @Schema(description = "灏侀潰鍥惧湴鍧�")
-    @Size(max = 512, message = "灏侀潰鍥惧湴鍧�闀垮害涓嶈兘瓒呰繃 512 涓瓧绗�")
-    private String coverUrl;
+    @Schema(description = "灏侀潰鍥炬枃浠剁紪鍙峰垪琛紙鏈�澶� 1 寮狅級", example = "[1]")
+    @Size(max = 1, message = "灏侀潰鍥炬渶澶氫笂浼� 1 寮�")
+    private List<Long> blobIds;
 
     @Schema(description = "娲诲姩鍦扮偣", example = "鍏徃澶т細璁")
     @Size(max = 255, message = "娲诲姩鍦扮偣闀垮害涓嶈兘瓒呰繃 255 涓瓧绗�")
diff --git a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpSignupPublicReqVO.java b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpSignupPublicReqVO.java
index acf2c96..5d8929e 100644
--- a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpSignupPublicReqVO.java
+++ b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/controller/admin/activity/vo/WxCpSignupPublicReqVO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.wxcp.controller.admin.activity.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Pattern;
 import jakarta.validation.constraints.Size;
@@ -17,14 +16,12 @@
     @NotNull(message = "娲诲姩缂栧彿涓嶈兘涓虹┖")
     private Long activityId;
 
-    @Schema(description = "濮撳悕", requiredMode = Schema.RequiredMode.REQUIRED, example = "鍒樻剰")
-    @NotEmpty(message = "濮撳悕涓嶈兘涓虹┖")
+    @Schema(description = "濮撳悕锛堥�夊~锛�", example = "鍒樻剰")
     @Size(max = 64, message = "濮撳悕闀垮害涓嶈兘瓒呰繃 64 涓瓧绗�")
     private String name;
 
-    @Schema(description = "鎵嬫満鍙�", requiredMode = Schema.RequiredMode.REQUIRED, example = "13800138000")
-    @NotEmpty(message = "鎵嬫満鍙蜂笉鑳戒负绌�")
-    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "鎵嬫満鍙锋牸寮忎笉姝g‘")
+    @Schema(description = "鎵嬫満鍙凤紙閫夊~锛屽~浜嗘墠鏍¢獙鏍煎紡锛�", example = "13800138000")
+    @Pattern(regexp = "^$|^1[3-9]\\d{9}$", message = "鎵嬫満鍙锋牸寮忎笉姝g‘锛岃濉啓 11 浣嶆墜鏈哄彿鎴栫暀绌�")
     private String mobile;
 
     @Schema(description = "浼佷笟寰俊鎴愬憳璐﹀彿锛涗粠浼佷笟寰俊鍐呮墦寮�鏃剁敱鍓嶇鑷姩甯︿笂锛屾櫘閫氭祻瑙堝櫒鎶ュ悕鍙笉浼�")
diff --git a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/dal/dataobject/activity/WxCpActivityDO.java b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/dal/dataobject/activity/WxCpActivityDO.java
index c04924a..47be2be 100644
--- a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/dal/dataobject/activity/WxCpActivityDO.java
+++ b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/dal/dataobject/activity/WxCpActivityDO.java
@@ -39,10 +39,6 @@
      */
     private String content;
     /**
-     * 灏侀潰鍥惧湴鍧�
-     */
-    private String coverUrl;
-    /**
      * 娲诲姩鍦扮偣
      */
     private String location;
diff --git a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityService.java b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityService.java
index 3166c1a..b8cad24 100644
--- a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityService.java
+++ b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityService.java
@@ -59,6 +59,14 @@
     PageResult<WxCpActivityDO> getActivityPage(@Valid WxCpActivityPageReqVO pageReqVO);
 
     /**
+     * 鑾峰緱娲诲姩灏侀潰闄勪欢鍒楄〃锛堟渶澶� 1 寮狅級
+     *
+     * @param activityId 娲诲姩缂栧彿
+     * @return 闄勪欢锛堝惈璁块棶鍦板潃锛�
+     */
+    List<SystemStorageBlobRespVO> getActivityAttachments(Long activityId);
+
+    /**
      * 鍙戝竷娲诲姩锛堣崏绋� -&gt; 宸插彂甯冿級
      *
      * @param id 娲诲姩缂栧彿
diff --git a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityServiceImpl.java b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityServiceImpl.java
index 70508df..ffc4d26 100644
--- a/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityServiceImpl.java
+++ b/yudao-module-wxcp/src/main/java/cn/iocoder/yudao/module/wxcp/service/activity/WxCpActivityServiceImpl.java
@@ -30,6 +30,7 @@
 
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -56,6 +57,16 @@
      */
     public static final String SIGNUP_RECORD_TYPE = "wxcp_activity_signup";
 
+    /**
+     * 娲诲姩灏侀潰鐨勫叧鑱旇褰曠被鍨嬶紝瀵瑰簲 system_storage_attachment.record_type
+     */
+    public static final String ACTIVITY_RECORD_TYPE = "wxcp_activity";
+
+    /**
+     * 闄勪欢鐢ㄩ�旓紝涓庡叾瀹冩ā鍧椾繚鎸佷竴鑷�
+     */
+    private static final String ATTACHMENT_APPLICATION = "file";
+
     @Resource
     private WxCpActivityMapper wxcpActivityMapper;
     @Resource
@@ -72,6 +83,7 @@
     // ==================== 娲诲姩绠$悊 ====================
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Long createActivity(WxCpActivitySaveReqVO createReqVO) {
         WxCpActivityDO activity = BeanUtils.toBean(createReqVO, WxCpActivityDO.class);
         // 鏂板缓鐨勪竴寰嬫槸鑽夌锛岄伩鍏嶆湭閰嶇疆瀹屽氨琚壂鐮佹姤鍚�
@@ -83,10 +95,15 @@
             activity.setPushScope(WxCpPushScopeEnum.ALL.getScope());
         }
         wxcpActivityMapper.insert(activity);
+        // 灏侀潰璧� system 鐨勯檮浠朵腑闂磋〃锛屼笟鍔¤〃涓嶈惤鏂囦欢鍦板潃瀛楁
+        if (CollUtil.isNotEmpty(createReqVO.getBlobIds())) {
+            bindActivityAttachments(activity.getId(), createReqVO.getBlobIds());
+        }
         return activity.getId();
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void updateActivity(WxCpActivitySaveReqVO updateReqVO) {
         WxCpActivityDO activity = validateActivityExists(updateReqVO.getId());
         // 宸茬粨鏉熸垨宸插彇娑堢殑娲诲姩涓嶅啀鍏佽淇敼
@@ -101,12 +118,19 @@
         updateObj.setPushStatus(null);
         updateObj.setPushTime(null);
         wxcpActivityMapper.updateById(updateObj);
+        // blobIds 涓� null 琛ㄧず璇锋眰閲屾病甯﹁繖涓瓧娈碉紝瑙嗕负涓嶆敼鍔ㄥ皝闈紱浼犵┖鏁扮粍鎵嶆槸鏄庣‘瑕佹竻绌哄皝闈�
+        if (updateReqVO.getBlobIds() != null) {
+            bindActivityAttachments(activity.getId(), updateReqVO.getBlobIds());
+        }
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void deleteActivity(Long id) {
         validateActivityExists(id);
         wxcpActivityMapper.deleteById(id);
+        // 娲诲姩鍒犱簡锛屽皝闈㈤檮浠跺叧绯讳竴骞舵竻鎺夛紝閬垮厤娈嬬暀鎴愬鍎块檮浠�
+        storageAttachmentService.deleteAttachmentsByRecordTypeAndRecordId(ACTIVITY_RECORD_TYPE, id);
     }
 
     @Override
@@ -117,6 +141,53 @@
     @Override
     public PageResult<WxCpActivityDO> getActivityPage(WxCpActivityPageReqVO pageReqVO) {
         return wxcpActivityMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<SystemStorageBlobRespVO> getActivityAttachments(Long activityId) {
+        return listAttachments(ACTIVITY_RECORD_TYPE, activityId);
+    }
+
+    /**
+     * 缁戝畾娲诲姩灏侀潰闄勪欢
+     *
+     * 璧� system 妯″潡鐨勯檮浠朵腑闂磋〃锛坮ecord_type = wxcp_activity锛夛紝
+     * 涓氬姟琛ㄤ笉鍔犳枃浠跺湴鍧�鍒椼�佷笉鑷缓 upload 鎺ュ彛锛岀鍚堥」鐩粺涓�鏂囦欢绠$悊瑙勮寖銆�
+     *
+     * 浼犵┖闆嗗悎浼氭竻鎺夊叧鑱旇褰曚絾淇濈暀鏂囦欢鏈韩锛坆indAttachments 鍙垹涓棿琛ㄨ褰曪級銆�
+     * 娉ㄦ剰涓嶈鏀圭敤 deleteAttachmentsByRecordTypeAndRecordId 鏉�"鍏堝垹鍚庡姞"锛�
+     * 閭d釜鏂规硶浼氳繛 blob 涓�璧峰垹鎺夛紝鍚屼竴涓枃浠堕噸鏂扮粦瀹氭椂浼氬洜涓烘枃浠跺凡涓嶅瓨鍦ㄨ�屾煡涓嶅嚭鏉ャ��
+     */
+    private void bindActivityAttachments(Long activityId, List<Long> blobIds) {
+        SystemStorageAttachmentSaveReqVO bindReqVO = new SystemStorageAttachmentSaveReqVO();
+        bindReqVO.setApplication(ATTACHMENT_APPLICATION);
+        bindReqVO.setRecordType(ACTIVITY_RECORD_TYPE);
+        bindReqVO.setRecordId(activityId);
+        bindReqVO.setBlobItems(toBlobItems(blobIds));
+        storageAttachmentService.bindAttachments(bindReqVO);
+    }
+
+    private List<SystemStorageAttachmentSaveReqVO.BlobItem> toBlobItems(List<Long> blobIds) {
+        if (CollUtil.isEmpty(blobIds)) {
+            return Collections.emptyList();
+        }
+        return blobIds.stream()
+                .filter(Objects::nonNull)
+                .distinct()
+                .map(blobId -> {
+                    SystemStorageAttachmentSaveReqVO.BlobItem item = new SystemStorageAttachmentSaveReqVO.BlobItem();
+                    item.setBlobId(blobId);
+                    return item;
+                })
+                .toList();
+    }
+
+    private List<SystemStorageBlobRespVO> listAttachments(String recordType, Long recordId) {
+        SystemStorageAttachmentListReqVO listReqVO = new SystemStorageAttachmentListReqVO();
+        listReqVO.setApplication(ATTACHMENT_APPLICATION);
+        listReqVO.setRecordType(recordType);
+        listReqVO.setRecordId(recordId);
+        return storageAttachmentService.listAttachments(listReqVO);
     }
 
     @Override
@@ -256,10 +327,16 @@
             throw exception(SIGNUP_FULL);
         }
 
-        // 4. 鍘婚噸锛氭湁浼佷笟寰俊璐﹀彿鎸夎处鍙锋煡锛屽惁鍒欐寜鎵嬫満鍙锋煡
-        WxCpActivitySignupDO exists = StrUtil.isNotBlank(reqVO.getWxUserId())
-                ? wxcpSignupMapper.selectByActivityIdAndWxUserId(activity.getId(), reqVO.getWxUserId().trim())
-                : wxcpSignupMapper.selectByActivityIdAndMobile(activity.getId(), reqVO.getMobile().trim());
+        // 4. 鍘婚噸锛氭湁浼佷笟寰俊璐﹀彿鎸夎处鍙锋煡锛涙病鏈夎处鍙蜂絾鏈夋墜鏈哄彿鍒欐寜鎵嬫満鍙锋煡锛�
+        //    涓よ�呴兘娌℃湁鏃舵棤娉曞垽瀹氳韩浠斤紝涓嶅仛鍘婚噸鈥斺�斿惁鍒欑┖鎵嬫満鍙蜂細浜掔浉璇垽鎴愬悓涓�浜�
+        String wxUserId = StrUtil.trimToEmpty(reqVO.getWxUserId());
+        String mobile = StrUtil.trimToEmpty(reqVO.getMobile());
+        WxCpActivitySignupDO exists = null;
+        if (StrUtil.isNotBlank(wxUserId)) {
+            exists = wxcpSignupMapper.selectByActivityIdAndWxUserId(activity.getId(), wxUserId);
+        } else if (StrUtil.isNotBlank(mobile)) {
+            exists = wxcpSignupMapper.selectByActivityIdAndMobile(activity.getId(), mobile);
+        }
         if (exists != null && !Objects.equals(exists.getStatus(), WxCpSignupStatusEnum.CANCELED.getStatus())) {
             throw exception(SIGNUP_DUPLICATED);
         }
@@ -267,8 +344,8 @@
         if (exists != null) {
             wxcpSignupMapper.updateById(WxCpActivitySignupDO.builder()
                     .id(exists.getId())
-                    .name(reqVO.getName())
-                    .mobile(reqVO.getMobile())
+                    .name(StrUtil.trimToEmpty(reqVO.getName()))
+                    .mobile(mobile)
                     .deptName(reqVO.getDeptName())
                     .content(reqVO.getContent())
                     .remark(reqVO.getRemark())
@@ -276,9 +353,7 @@
                     .signupTime(now)
                     .checkInTime(null)
                     .build());
-            // 閲嶆柊鎶ュ悕鏃舵棫闄勪欢宸插け鏁堬紝鍏堟竻鎺夊啀缁戞柊鐨�
-            storageAttachmentService.deleteAttachmentsByRecordTypeAndRecordId(
-                    SIGNUP_RECORD_TYPE, exists.getId());
+            // 閲嶆柊鎶ュ悕鏃舵棫闄勪欢浣滃簾锛岀洿鎺ラ噸鏂扮粦瀹氾紙bindAttachments 浼氬厛娓呮棫鍏宠仈锛屼笖涓嶄細鍒犳帀鏂囦欢鏈韩锛�
             bindSignupAttachments(exists.getId(), reqVO.getBlobIds());
             incrementSignupCount(activity.getId());
             return exists.getId();
@@ -286,7 +361,10 @@
 
         // 5. 鏂板鎶ュ悕璁板綍
         WxCpActivitySignupDO signup = BeanUtils.toBean(reqVO, WxCpActivitySignupDO.class);
-        signup.setWxUserId(StrUtil.trimToEmpty(reqVO.getWxUserId()));
+        signup.setWxUserId(wxUserId);
+        // 濮撳悕銆佹墜鏈哄彿鏀逛负閫夊~锛氱粺涓�瀛樼┖涓茶�屼笉鏄� null锛岄伩鍏嶅悗缁寜鎵嬫満鍙锋煡閲嶆椂绌哄�艰涔夋贩涔�
+        signup.setName(StrUtil.trimToEmpty(reqVO.getName()));
+        signup.setMobile(mobile);
         signup.setStatus(WxCpSignupStatusEnum.SIGNED_UP.getStatus());
         signup.setSignupTime(now);
         wxcpSignupMapper.insert(signup);
@@ -300,36 +378,24 @@
     }
 
     /**
-     * 缁戝畾鎶ュ悕闄勪欢
+     * 缁戝畾鎶ュ悕闄勪欢锛堝叏閲忚鐩栵細鍏堟竻鎺夎鎶ュ悕璁板綍涓嬬殑鏃у叧鑱旓紝鍐嶇粦鏂扮殑锛�
      *
      * 璧� system 妯″潡鐨勯檮浠朵腑闂磋〃锛坮ecord_type = wxcp_activity_signup锛夛紝
      * 涓嶆柊寤� upload 鎺ュ彛銆佷笉钀芥枃浠跺湴鍧�瀛楁锛岀鍚堥」鐩粺涓�鏂囦欢绠$悊瑙勮寖銆�
+     * 浼犵┖闆嗗悎鍙竻鍏宠仈銆佷笉鍒犳枃浠舵湰韬��
      */
     private void bindSignupAttachments(Long signupId, List<Long> blobIds) {
-        if (CollUtil.isEmpty(blobIds)) {
-            return;
-        }
         SystemStorageAttachmentSaveReqVO bindReqVO = new SystemStorageAttachmentSaveReqVO();
-        bindReqVO.setApplication("file");
+        bindReqVO.setApplication(ATTACHMENT_APPLICATION);
         bindReqVO.setRecordType(SIGNUP_RECORD_TYPE);
         bindReqVO.setRecordId(signupId);
-        bindReqVO.setBlobItems(blobIds.stream()
-                .filter(Objects::nonNull)
-                .map(blobId -> {
-                    SystemStorageAttachmentSaveReqVO.BlobItem item = new SystemStorageAttachmentSaveReqVO.BlobItem();
-                    item.setBlobId(blobId);
-                    return item;
-                })
-                .toList());
+        bindReqVO.setBlobItems(toBlobItems(blobIds));
         storageAttachmentService.bindAttachments(bindReqVO);
     }
 
     @Override
     public List<SystemStorageBlobRespVO> getSignupAttachments(Long signupId) {
-        SystemStorageAttachmentListReqVO listReqVO = new SystemStorageAttachmentListReqVO();
-        listReqVO.setRecordType(SIGNUP_RECORD_TYPE);
-        listReqVO.setRecordId(signupId);
-        return storageAttachmentService.listAttachments(listReqVO);
+        return listAttachments(SIGNUP_RECORD_TYPE, signupId);
     }
 
     private void incrementSignupCount(Long activityId) {
diff --git a/yudao-server/src/main/resources/application-test.yaml b/yudao-server/src/main/resources/application-test.yaml
index 210d984..eacd4e3 100644
--- a/yudao-server/src/main/resources/application-test.yaml
+++ b/yudao-server/src/main/resources/application-test.yaml
@@ -8,7 +8,7 @@
     aes-key: # EncodingAESKey锛屾帴鏀跺姞瀵嗘秷鎭椂鎵嶉渶瑕�
     # 鎶ュ悕椤靛缃戝湴鍧�鍓嶇紑锛氬繀椤绘槸浼佷笟寰俊鎴愬憳鎵嬫満鑳借闂埌鐨勫湴鍧�锛堝唴缃戠┛閫忓煙鍚嶆垨姝e紡鍩熷悕锛夛紝
     # 鐢熸垚鐨勪簩缁寸爜鍐呭涓� {signupUrlPrefix}/admin-api/wxcp/activity/signup-page?id={娲诲姩缂栧彿}
-    signup-url-prefix: http://36.213.150.237:9007
+    signup-url-prefix: http://36.213.150.237:9008 # 鍚庣绔彛锛堝鍣� 9008->48080锛夛紱濉� 9007 浼氭墦鍒板墠绔紝鑰屽墠绔棤 /admin-api 浠g悊锛屾壂鐮佸繀 404
     qrcode-size: 400 # 鎶ュ悕浜岀淮鐮佽竟闀匡紙鍍忕礌锛夛紝涓嶉厤缃粯璁� 400
 server:
   port: 48080

--
Gitblit v1.9.3