Ver código fonte

feat(admin): ActivityEdit 表单校验 + 创建成功弹窗

Xiaogang Liao 2 meses atrás
pai
commit
eee133e64f
2 arquivos alterados com 118 adições e 41 exclusões
  1. 3 2
      cfc-web/package-lock.json
  2. 115 39
      cfc-web/src/views/admin/ActivityEdit.vue

+ 3 - 2
cfc-web/package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "cfc-web",
-  "version": "1.0.0",
+  "version": "1.0.2",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "cfc-web",
-      "version": "1.0.0",
+      "version": "1.0.2",
       "dependencies": {
         "@wangeditor/editor": "^5.1.23",
         "@wangeditor/editor-for-vue": "^1.0.2",
@@ -3534,6 +3534,7 @@
       "version": "5.1.23",
       "resolved": "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.23.tgz",
       "integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==",
+      "license": "MIT",
       "dependencies": {
         "@uppy/core": "^2.1.1",
         "@uppy/xhr-upload": "^2.0.3",

+ 115 - 39
cfc-web/src/views/admin/ActivityEdit.vue

@@ -15,11 +15,23 @@
         </div>
       </div>
 
-      <el-form label-width="120px" v-loading="loading">
-        <el-form-item label="活动标题">
+      <el-form label-width="120px" v-loading="loading" :model="form" :rules="formRules" ref="form">
+        <el-form-item label="活动标题" prop="title">
           <el-input v-model="form.title" placeholder="请输入活动标题" :disabled="readonly" />
         </el-form-item>
 
+        <el-form-item label="活动类型" prop="activityType">
+          <el-select v-model="form.activityType" placeholder="请选择活动类型" style="width:100%" :disabled="readonly">
+            <el-option label="线下活动" value="offline" />
+            <el-option label="线上活动" value="online" />
+            <el-option label="主题活动" value="campaign" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="活动描述" prop="description">
+          <el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入活动描述" :disabled="readonly" />
+        </el-form-item>
+
         <el-form-item label="封面图片">
           <template v-if="!readonly">
             <el-upload
@@ -40,18 +52,6 @@
           <span v-else style="color:#999">无封面</span>
         </el-form-item>
 
-        <el-form-item label="活动类型">
-          <el-select v-model="form.activityType" placeholder="请选择活动类型" style="width:100%" :disabled="readonly">
-            <el-option label="线下活动" value="offline" />
-            <el-option label="线上活动" value="online" />
-            <el-option label="主题活动" value="campaign" />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="活动描述">
-          <el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入活动描述" :disabled="readonly" />
-        </el-form-item>
-
         <el-form-item label="五维权重">
           <dimension-weight-picker v-model="form.dimensionWeights" :show-presets="true" :readonly="readonly" />
         </el-form-item>
@@ -75,12 +75,12 @@
 
         <el-row :gutter="16">
           <el-col :span="12">
-            <el-form-item label="开始时间">
+            <el-form-item label="开始时间" prop="startTime">
               <el-date-picker v-model="form.startTime" type="datetime" placeholder="选择开始时间" style="width:100%" :disabled="readonly" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="结束时间">
+            <el-form-item label="结束时间" prop="endTime">
               <el-date-picker v-model="form.endTime" type="datetime" placeholder="选择结束时间" style="width:100%" :disabled="readonly" />
             </el-form-item>
           </el-col>
@@ -119,6 +119,19 @@
         </el-form-item>
       </el-form>
     </el-card>
+
+    <!-- 创建成功弹窗 -->
+    <el-dialog title="创建成功" :visible.sync="successDialogVisible" width="420px" :close-on-click-modal="false" :show-close="false">
+      <div style="text-align:center;padding:10px 0;">
+        <i class="el-icon-circle-check" style="font-size:48px;color:#67C23A;"></i>
+        <p style="font-size:16px;margin-top:12px;">活动「{{ form.title }}」已创建成功</p>
+      </div>
+      <div slot="footer" style="text-align:center;">
+        <el-button @click="handleContinueAdd">继续添加</el-button>
+        <el-button @click="$router.push('/activities')">返回列表</el-button>
+        <el-button type="primary" @click="handlePublishAndBack" :loading="publishing">直接发布</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -138,6 +151,7 @@ export default {
       publishing: false,
       readonly: false,
       activityStatus: '',
+      successDialogVisible: false,
       form: {
         title: '',
         coverImage: '',
@@ -154,6 +168,23 @@ export default {
         visibleScope: '',
         visibleTo: '',
         checkinPoints: 0
+      },
+      formRules: {
+        title: [
+          { required: true, message: '请填写活动标题', trigger: 'blur' }
+        ],
+        activityType: [
+          { required: true, message: '请选择活动类型', trigger: 'change' }
+        ],
+        description: [
+          { required: true, message: '请填写活动描述', trigger: 'blur' }
+        ],
+        startTime: [
+          { required: true, message: '请选择开始时间', trigger: 'change' }
+        ],
+        endTime: [
+          { required: true, message: '请选择结束时间', trigger: 'change' }
+        ]
       }
     }
   },
@@ -243,12 +274,10 @@ export default {
       this.$message.error('封面上传失败,请重试')
     },
     async saveActivity(publishNow) {
-      if (!this.form.title) {
-        this.$message.warning('请填写活动标题')
-        return
-      }
-      if (!this.form.startTime || !this.form.endTime) {
-        this.$message.warning('请填写开始时间和结束时间')
+      // 表单验证
+      try {
+        await this.$refs.form.validate()
+      } catch (e) {
         return
       }
       if (publishNow) {
@@ -273,32 +302,29 @@ export default {
           visibleTo: this.form.visibleTo,
           checkinPoints: this.form.checkinPoints || 0
         }
-        let activityId = null
         if (this.isEdit) {
+          // 编辑模式:保存后直接返回列表
           payload.id = this.form._activityId || this.$route.query.id
           await updateActivity(payload)
-          activityId = payload.id
+          if (this.form.dimensionWeights && this.form.dimensionWeights.length) {
+            try {
+              await saveDimensionWeights('activity', payload.id, this.form.dimensionWeights)
+            } catch (e) {
+              console.error('保存维度权重失败', e)
+            }
+          }
+          this.$message.success('更新成功')
+          this.$router.push('/activities')
         } else {
+          // 创建模式:保存后弹窗
           const res = await createActivity(payload)
           if (res.data && res.data.id) {
-            activityId = res.data.id
+            this.createdActivityId = res.data.id
           }
           this.isEdit = true
+          this.saving = false
+          this.successDialogVisible = true
         }
-        if (activityId && this.form.dimensionWeights && this.form.dimensionWeights.length) {
-          try {
-            await saveDimensionWeights('activity', activityId, this.form.dimensionWeights)
-          } catch (e) {
-            console.error('保存维度权重失败', e)
-          }
-        }
-        if (publishNow && activityId) {
-          await publishActivity(activityId)
-          this.$message.success('发布成功')
-        } else {
-          this.$message.success(this.isEdit ? '更新成功' : '创建成功')
-        }
-        this.$router.push('/activities')
       } catch (e) {
         this.$message.error('保存失败')
       } finally {
@@ -306,6 +332,56 @@ export default {
         this.publishing = false
       }
     },
+    handleContinueAdd() {
+      this.successDialogVisible = false
+      this.form = {
+        title: '',
+        coverImage: '',
+        activityType: '',
+        description: '',
+        dimensionCode: '',
+        dimensionWeights: [],
+        location: '',
+        maxParticipants: null,
+        priceYuan: null,
+        startTime: null,
+        endTime: null,
+        visibility: 'public',
+        visibleScope: '',
+        visibleTo: '',
+        checkinPoints: 0
+      }
+      this.isEdit = false
+      this.createdActivityId = null
+      this.$refs.form && this.$refs.form.clearValidate()
+    },
+    async handlePublishAndBack() {
+      this.successDialogVisible = false
+      const activityId = this.createdActivityId
+      if (!activityId) {
+        this.$router.push('/activities')
+        return
+      }
+      // 先保存维度权重
+      if (this.form.dimensionWeights && this.form.dimensionWeights.length) {
+        try {
+          await saveDimensionWeights('activity', activityId, this.form.dimensionWeights)
+        } catch (e) {
+          console.error('保存维度权重失败', e)
+        }
+      }
+      // 发布
+      try {
+        this.publishing = true
+        await publishActivity(activityId)
+        this.$message.success('发布成功')
+      } catch (e) {
+        this.$message.error('发布失败')
+      } finally {
+        this.publishing = false
+      }
+      this.$router.push('/activities')
+    },
     editFromReadonly() {
       this.readonly = false
     }