Selaa lähdekoodia

券码回收:新增回收记录弹窗,已过期券码改为全量回收并优化导入提示

- 券码列表新增「回收记录」入口及弹窗(回收时间/类型/操作人/数量,支持下载回收券码)
- 已过期券码回收:数量改为文本展示并按可回收数量全量回收
- 回收成功后自动写入回收记录
- 回收类型移除「导错码券码回收」,仅保留未发放/已过期
- 导入券码提示更新(模板格式/不可重复/最多50000条)
- FSD §1/§2 配图增加换行间距

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
csk 1 kuukausi sitten
vanhempi
commit
82e1ab1a73

+ 10 - 0
diagrams/2026-06-07T022454/diagram.mmd

@@ -0,0 +1,10 @@
+sequenceDiagram
+    participant FE as 前端
+    participant BE as 后端
+    participant OSS as OSS存储
+    FE->>BE: 上传图片
+    BE->>BE: 校验格式
+    BE->>OSS: 保存原图
+    OSS-->>BE: 返回URL
+    BE->>BE: 生成水印图
+    BE-->>FE: 返回水印图URL

BIN
diagrams/2026-06-07T022454/diagram.png


+ 60 - 15
工作空间/产研/权益/汇丰全行/产品原型/pc-demo/src/views/EquityProductCoupons.vue

@@ -12,6 +12,9 @@
         <el-button type="primary" @click="openImportDialog">
           <el-icon><Upload /></el-icon>导入券码
         </el-button>
+        <el-button @click="openRecycleRecordDialog">
+          <el-icon><Document /></el-icon>回收记录
+        </el-button>
       </div>
 
       <el-table :data="pagedBatchList" stripe style="width: 100%">
@@ -77,15 +80,18 @@
 
       <el-form label-width="100px" label-position="left" style="margin-top: 24px;">
         <el-form-item label="回收数量" required>
-          <el-input-number
-            v-model="recycleForm.amount"
-            :min="1"
-            :max="recycleMaxAmount"
-            :placeholder="`输入范围1-${recycleMaxAmount}`"
-            :controls-position="''"
-            style="width: 100%"
-          ></el-input-number>
-          <div class="recycle-tip">本批次{{ currentRecycleTypeLabel }}最多可回收数量:{{ recycleMaxAmount }}</div>
+          <span v-if="recycleForm.type === 'expired'">{{ recycleMaxAmount }}</span>
+          <template v-else>
+            <el-input-number
+              v-model="recycleForm.amount"
+              :min="1"
+              :max="recycleMaxAmount"
+              :placeholder="`输入范围1-${recycleMaxAmount}`"
+              :controls-position="''"
+              style="width: 100%"
+            ></el-input-number>
+            <div class="recycle-tip">本批次{{ currentRecycleTypeLabel }}最多可回收数量:{{ recycleMaxAmount }}</div>
+          </template>
         </el-form-item>
       </el-form>
 
@@ -112,7 +118,11 @@
               <el-icon><Upload /></el-icon>选择文件
             </el-button>
             <template #tip>
-              <div class="el-upload__tip">支持 .xlsx / .csv,仅可上传一个文件</div>
+              <div class="el-upload__tip">
+                <div>*只支持模板格式,请先下载模板再导入</div>
+                <div>*不能导入相同的券码</div>
+                <div>*最多支持50000条,若超过请分次导入</div>
+              </div>
               <el-button type="text" @click="downloadTemplate">
                 <el-icon><Download /></el-icon>模板下载
               </el-button>
@@ -127,6 +137,23 @@
         </span>
       </template>
     </el-dialog>
+
+    <el-dialog title="回收记录" v-model="recycleRecordDialogVisible" width="900px">
+      <el-table :data="recycleRecords" stripe style="width: 100%">
+        <el-table-column prop="recycleTime" label="回收时间" width="180"></el-table-column>
+        <el-table-column prop="type" label="类型" width="150"></el-table-column>
+        <el-table-column prop="operator" label="操作人" width="120"></el-table-column>
+        <el-table-column prop="amount" label="回收数量" width="120"></el-table-column>
+        <el-table-column label="操作" min-width="140">
+          <template #default="scope">
+            <el-button type="text" size="small" @click="downloadRecycleCoupons(scope.row)">下载回收券码</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <template #footer>
+        <el-button @click="recycleRecordDialogVisible = false">关闭</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -139,17 +166,22 @@ export default {
     return {
       importDialogVisible: false,
       recycleDialogVisible: false,
+      recycleRecordDialogVisible: false,
       currentPage: 1,
       pageSize: 10,
       recycleRow: null,
+      recycleRecords: [
+        { recycleTime: '2026-05-10 14:22:08', type: '未发放券码回收', operator: '张三', amount: 120 },
+        { recycleTime: '2026-04-28 09:15:33', type: '已过期券码回收', operator: '李四', amount: 80 },
+        { recycleTime: '2026-04-12 16:40:51', type: '未发放券码回收', operator: '王五', amount: 200 }
+      ],
       recycleForm: {
         type: 'unissued',
         amount: undefined
       },
       recycleTypeOptions: [
         { label: '未发放券码回收', value: 'unissued' },
-        { label: '已过期券码回收', value: 'expired' },
-        { label: '导错码券码回收', value: 'wrong' }
+        { label: '已过期券码回收', value: 'expired' }
       ],
       importForm: {
         files: []
@@ -322,7 +354,6 @@ export default {
           const ts = row.expireTime ? new Date(row.expireTime).getTime() : 0
           return ts && ts < Date.now() ? Number(row.remainingCount) || 0 : 0
         }
-        case 'wrong': return Number(row.failCount) || 0
         default: return 0
       }
     }
@@ -385,15 +416,22 @@ export default {
     handleExportFail(row) {
       ElMessage.success(`已开始导出失败券码(${row.failCount} 条)`)
     },
+    openRecycleRecordDialog() {
+      this.recycleRecordDialogVisible = true
+    },
+    downloadRecycleCoupons() {
+      ElMessage.success('已开始下载回收券码')
+    },
     resetRecycleForm() {
       this.recycleRow = null
       this.recycleForm = { type: 'unissued', amount: undefined }
     },
     confirmRecycle() {
       const max = this.recycleMaxAmount
-      const amount = Number(this.recycleForm.amount)
+      // 已过期券码回收:数量为文本展示,直接按可回收数量全部回收
+      const amount = this.recycleForm.type === 'expired' ? max : Number(this.recycleForm.amount)
       if (!amount || amount < 1) {
-        ElMessage.warning('请输入回收数量')
+        ElMessage.warning(this.recycleForm.type === 'expired' ? '当前批次没有可回收的已过期券码' : '请输入回收数量')
         return
       }
       if (amount > max) {
@@ -403,6 +441,13 @@ export default {
       if (this.recycleRow && this.recycleForm.type === 'unissued') {
         this.recycleRow.remainingCount = Math.max(0, Number(this.recycleRow.remainingCount) - amount)
       }
+      const typeLabel = (this.recycleTypeOptions.find(o => o.value === this.recycleForm.type) || {}).label || ''
+      this.recycleRecords.unshift({
+        recycleTime: this.formatNow(),
+        type: typeLabel,
+        operator: '当前用户',
+        amount
+      })
       ElMessage.success('回收成功')
       this.recycleDialogVisible = false
     }

+ 4 - 0
工作空间/产研/权益/汇丰全行/需求文档/汇丰银行权益中台-FSD.md

@@ -72,6 +72,8 @@
 
 <br>
 
+<br>
+
 ![BlockNote image](../../../../../.resources/image-1779243010146.png)![BlockNote image](../../../../../.resources/image-1779243019476.png)
 
 ## 2\. 用户登录
@@ -275,6 +277,8 @@
 
 <br>
 
+<br>
+
 ![BlockNote image](./screenshots/2-2-equity-add-source-rongshu.png)![BlockNote image](./screenshots/dialog-rongshu-product.png)
 
 **C. 是否权益平台兑换 = 否**