xiongzhu 4 лет назад
Родитель
Сommit
b5ad7622d4

+ 11 - 0
src/main/java/com/izouma/nineth/domain/AirDrop.java

@@ -12,6 +12,7 @@ import lombok.NoArgsConstructor;
 import javax.persistence.Column;
 import javax.persistence.Convert;
 import javax.persistence.Entity;
+import java.time.LocalDateTime;
 import java.util.List;
 
 @Data
@@ -37,6 +38,16 @@ public class AirDrop extends BaseEntity {
     @ApiModelProperty("兑换券备注")
     private String couponRemark;
 
+    private boolean couponLimited;
+
+    private boolean couponNeedGas;
+
+    @Convert(converter = LongArrayConverter.class)
+    @Column(columnDefinition = "TEXT")
+    private List<Long> couponCollectionIds;
+
+    private LocalDateTime couponExpiration;
+
     @Column(columnDefinition = "TEXT")
     @Convert(converter = StringArrayConverter.class)
     @ApiModelProperty("手机号")

+ 4 - 4
src/main/java/com/izouma/nineth/domain/Coupon.java

@@ -28,16 +28,16 @@ public class Coupon extends BaseEntity {
     @ApiModelProperty("备注")
     private String remark;
 
+    @ApiModelProperty("指定藏品")
     private boolean limited;
 
+    @ApiModelProperty("需要支付GAS")
+    private boolean needGas;
+
     @Convert(converter = LongArrayConverter.class)
     @Column(columnDefinition = "TEXT")
     private List<Long> collectionIds;
 
     private LocalDateTime expiration;
 
-    private boolean used;
-
-    private LocalDateTime useTime;
-
 }

+ 2 - 0
src/main/java/com/izouma/nineth/domain/Order.java

@@ -139,4 +139,6 @@ public class Order extends BaseEntity {
     private String address;
 
     private Long assetId;
+
+    private boolean hide;
 }

+ 48 - 0
src/main/java/com/izouma/nineth/domain/UserCoupon.java

@@ -0,0 +1,48 @@
+package com.izouma.nineth.domain;
+
+import com.izouma.nineth.converter.LongArrayConverter;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel("兑换券")
+public class UserCoupon extends BaseEntity {
+    private Long userId;
+
+    private Long couponId;
+
+    @ApiModelProperty("名称")
+    private String name;
+
+    @ApiModelProperty("备注")
+    private String remark;
+
+    private boolean limited;
+
+    private boolean needGas;
+
+    @Convert(converter = LongArrayConverter.class)
+    @Column(columnDefinition = "TEXT")
+    private List<Long> collectionIds;
+
+    private LocalDateTime expiration;
+
+    private boolean used;
+
+    private LocalDateTime useTime;
+
+}

+ 16 - 0
src/main/java/com/izouma/nineth/repo/UserCouponRepo.java

@@ -0,0 +1,16 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.UserCoupon;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+
+public interface UserCouponRepo extends JpaRepository<UserCoupon, Long>, JpaSpecificationExecutor<UserCoupon> {
+    @Query("update UserCoupon t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+}

+ 20 - 0
src/main/java/com/izouma/nineth/service/UserCouponService.java

@@ -0,0 +1,20 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.domain.UserCoupon;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.repo.UserCouponRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+public class UserCouponService {
+
+    private UserCouponRepo userCouponRepo;
+
+    public Page<UserCoupon> all(PageQuery pageQuery) {
+        return userCouponRepo.findAll(JpaUtils.toSpecification(pageQuery, UserCoupon.class), JpaUtils.toPageRequest(pageQuery));
+    }
+}

+ 7 - 0
src/main/java/com/izouma/nineth/web/OrderController.java

@@ -86,5 +86,12 @@ public class OrderController extends BaseController {
         }
 
     }
+
+    @PostMapping("/hide")
+    public void hide(@RequestParam Long id) {
+        Order order = orderRepo.findById(id).orElseThrow(new BusinessException("订单不存在"));
+        order.setHide(true);
+        orderRepo.save(order);
+    }
 }
 

+ 60 - 0
src/main/java/com/izouma/nineth/web/UserCouponController.java

@@ -0,0 +1,60 @@
+package com.izouma.nineth.web;
+import com.izouma.nineth.domain.UserCoupon;
+import com.izouma.nineth.service.UserCouponService;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.UserCouponRepo;
+import com.izouma.nineth.utils.ObjUtils;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/userCoupon")
+@AllArgsConstructor
+public class UserCouponController extends BaseController {
+    private UserCouponService userCouponService;
+    private UserCouponRepo userCouponRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public UserCoupon save(@RequestBody UserCoupon record) {
+        if (record.getId() != null) {
+            UserCoupon orig = userCouponRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return userCouponRepo.save(orig);
+        }
+        return userCouponRepo.save(record);
+    }
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<UserCoupon> all(@RequestBody PageQuery pageQuery) {
+        return userCouponService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public UserCoupon get(@PathVariable Long id) {
+        return userCouponRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        userCouponRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<UserCoupon> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}
+

+ 1 - 1
src/main/resources/genjson/Coupon.json

@@ -1 +1 @@
-{"tableName":"Coupon","className":"Coupon","remark":"兑换券","genTable":true,"genClass":true,"genList":true,"genForm":true,"genRouter":true,"javaPath":"/Users/drew/Projects/Java/9th/src/main/java/com/izouma/nineth","viewPath":"/Users/drew/Projects/Java/9th/src/main/vue/src/views","routerPath":"/Users/drew/Projects/Java/9th/src/main/vue/src","resourcesPath":"/Users/drew/Projects/Java/9th/src/main/resources","dataBaseType":"Mysql","fields":[{"name":"name","modelName":"name","remark":"名称","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"remark","modelName":"remark","remark":"备注","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"limited","modelName":"limited","remark":"指定藏品可用","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"collectionIds","modelName":"collectionIds","remark":"藏品ID","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"expiration","modelName":"expiration","remark":"到期时间","showInList":true,"showInForm":true,"formType":"datetime"},{"name":"used","modelName":"used","remark":"used","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"useTime","modelName":"useTime","remark":"useTime","showInList":true,"showInForm":true,"formType":"datetime"}],"readTable":false,"dataSourceCode":"dataSource","genJson":"","subtables":[],"update":false,"basePackage":"com.izouma.nineth","tablePackage":"com.izouma.nineth.domain.Coupon"}
+{"tableName":"Coupon","className":"Coupon","remark":"兑换券","genTable":true,"genClass":true,"genList":true,"genForm":true,"genRouter":false,"javaPath":"/Users/drew/Projects/Java/9th/src/main/java/com/izouma/nineth","viewPath":"/Users/drew/Projects/Java/9th/src/main/vue/src/views","routerPath":"/Users/drew/Projects/Java/9th/src/main/vue/src","resourcesPath":"/Users/drew/Projects/Java/9th/src/main/resources","dataBaseType":"Mysql","fields":[{"name":"name","modelName":"name","remark":"名称","showInList":true,"showInForm":true,"formType":"singleLineText","required":true},{"name":"remark","modelName":"remark","remark":"备注","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"limited","modelName":"limited","remark":"指定藏品","showInList":true,"showInForm":true,"formType":"switch","required":true},{"name":"needGas","modelName":"needGas","remark":"需要支付GAS","showInList":true,"showInForm":true,"formType":"switch","required":true},{"name":"collectionIds","modelName":"collectionIds","remark":"collectionIds","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"expiration","modelName":"expiration","remark":"expiration","showInList":true,"showInForm":true,"formType":"datetime","required":true}],"readTable":false,"dataSourceCode":"dataSource","genJson":"","subtables":[],"update":false,"basePackage":"com.izouma.nineth","tablePackage":"com.izouma.nineth.domain.Coupon"}

+ 1 - 0
src/main/resources/genjson/UserCoupon.json

@@ -0,0 +1 @@
+{"tableName":"UserCoupon","className":"UserCoupon","remark":"用户兑换券","genTable":true,"genClass":true,"genList":false,"genForm":false,"genRouter":true,"javaPath":"/Users/drew/Projects/Java/9th/src/main/java/com/izouma/nineth","viewPath":"/Users/drew/Projects/Java/9th/src/main/vue/src/views","routerPath":"/Users/drew/Projects/Java/9th/src/main/vue/src","resourcesPath":"/Users/drew/Projects/Java/9th/src/main/resources","dataBaseType":"Mysql","fields":[{"name":"name","modelName":"name","remark":"名称","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"remark","modelName":"remark","remark":"备注","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"limited","modelName":"limited","remark":"limited","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"needGas","modelName":"needGas","remark":"needGas","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"collectionIds","modelName":"collectionIds","remark":"collectionIds","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"expiration","modelName":"expiration","remark":"expiration","showInList":true,"showInForm":true,"formType":"datetime"},{"name":"used","modelName":"used","remark":"used","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"useTime","modelName":"useTime","remark":"useTime","showInList":true,"showInForm":true,"formType":"datetime"}],"readTable":false,"dataSourceCode":"dataSource","genJson":"","subtables":[],"update":false,"basePackage":"com.izouma.nineth","tablePackage":"com.izouma.nineth.domain.UserCoupon"}

+ 29 - 25
src/main/vue/src/router.js

@@ -302,67 +302,71 @@ const router = new Router({
                 {
                     path: '/privilegeOptionEdit',
                     name: 'PrivilegeOptionEdit',
-                    component: () => import(/* webpackChunkName: "privilegeOptionEdit" */ '@/views/PrivilegeOptionEdit.vue'),
+                    component: () =>
+                        import(/* webpackChunkName: "privilegeOptionEdit" */ '@/views/PrivilegeOptionEdit.vue'),
                     meta: {
-                       title: '特权配置编辑',
-                    },
+                        title: '特权配置编辑'
+                    }
                 },
                 {
                     path: '/privilegeOptionList',
                     name: 'PrivilegeOptionList',
-                    component: () => import(/* webpackChunkName: "privilegeOptionList" */ '@/views/PrivilegeOptionList.vue'),
+                    component: () =>
+                        import(/* webpackChunkName: "privilegeOptionList" */ '@/views/PrivilegeOptionList.vue'),
                     meta: {
-                       title: '特权配置',
-                    },
-               },
+                        title: '特权配置'
+                    }
+                },
                 {
                     path: '/privilegeOptionEdit',
                     name: 'PrivilegeOptionEdit',
-                    component: () => import(/* webpackChunkName: "privilegeOptionEdit" */ '@/views/PrivilegeOptionEdit.vue'),
+                    component: () =>
+                        import(/* webpackChunkName: "privilegeOptionEdit" */ '@/views/PrivilegeOptionEdit.vue'),
                     meta: {
-                       title: '特权配置编辑',
-                    },
+                        title: '特权配置编辑'
+                    }
                 },
                 {
                     path: '/privilegeOptionList',
                     name: 'PrivilegeOptionList',
-                    component: () => import(/* webpackChunkName: "privilegeOptionList" */ '@/views/PrivilegeOptionList.vue'),
+                    component: () =>
+                        import(/* webpackChunkName: "privilegeOptionList" */ '@/views/PrivilegeOptionList.vue'),
                     meta: {
-                       title: '特权配置',
-                    },
-               },
+                        title: '特权配置'
+                    }
+                },
                 {
                     path: '/airDropEdit',
                     name: 'AirDropEdit',
                     component: () => import(/* webpackChunkName: "airDropEdit" */ '@/views/AirDropEdit.vue'),
                     meta: {
-                       title: '空投编辑',
-                    },
+                        title: '空投编辑'
+                    }
                 },
                 {
                     path: '/airDropList',
                     name: 'AirDropList',
                     component: () => import(/* webpackChunkName: "airDropList" */ '@/views/AirDropList.vue'),
                     meta: {
-                       title: '空投',
-                    },
-               },
+                        title: '空投'
+                    }
+                },
                 {
                     path: '/couponEdit',
                     name: 'CouponEdit',
                     component: () => import(/* webpackChunkName: "couponEdit" */ '@/views/CouponEdit.vue'),
                     meta: {
-                       title: '兑换券编辑',
-                    },
+                        title: '兑换券编辑'
+                    }
                 },
                 {
                     path: '/couponList',
                     name: 'CouponList',
                     component: () => import(/* webpackChunkName: "couponList" */ '@/views/CouponList.vue'),
                     meta: {
-                       title: '兑换券',
-                    },
-               }
+                        title: '兑换券'
+                    }
+                }
                 /**INSERT_LOCATION**/
             ]
         },
@@ -414,4 +418,4 @@ router.beforeEach((to, from, next) => {
     }
 });
 
-export default router;
+export default router;

+ 113 - 19
src/main/vue/src/views/AirDropEdit.vue

@@ -33,17 +33,22 @@
                             </el-option>
                         </el-select>
                     </el-form-item>
-                    <el-form-item prop="couponName" label="兑换券名称" v-if="formData.type === 'coupon'">
-                        <el-input v-model="formData.couponName"></el-input>
+                    <el-form-item prop="couponId" label="兑换券" v-if="formData.type === 'coupon'">
+                        <el-input v-model="formData.couponId"></el-input>
                     </el-form-item>
-                    <el-form-item prop="couponRemark" label="兑换券备注" v-if="formData.type === 'coupon'">
-                        <el-input v-model="formData.couponRemark"></el-input>
+                    <el-form-item prop="userIds" label="空投对象">
+                        <el-table :data="users">
+                            <el-table-column type="index" label="#" width="50"></el-table-column>
+                            <el-table-column label="手机" prop="phone"></el-table-column>
+                            <el-table-column label="昵称" prop="nickname"></el-table-column>
+                            <el-table-column width="80" align="center">
+                                <template v-slot="{ row, $index }">
+                                    <el-button type="text" @click="delUser($index)">删除</el-button>
+                                </template>
+                            </el-table-column>
+                        </el-table>
+                        <el-button @click="addUser" size="mini">添加</el-button>
                     </el-form-item>
-                    <el-form-item prop="phone" label="手机号">
-                        <el-input type="textarea" v-model="formData.phone"></el-input>
-                    </el-form-item>
-                    <el-form-item prop="userIds" label="用户ID"> </el-form-item>
-
                     <el-form-item prop="result" label="result"> </el-form-item>
                     <el-form-item class="form-submit">
                         <el-button @click="onSave" :loading="saving" type="primary"> 保存 </el-button>
@@ -56,8 +61,27 @@
             </div>
         </div>
 
-        <el-dialog :visible.sync="showPhoneDialog">
-            <el-input v-model="phone" ></el-input>
+        <el-dialog
+            :visible.sync="showPhoneDialog"
+            title="添加空投对象"
+            width="500px"
+            :close-on-click-modal="false"
+            :show-close="!searchingPhone"
+        >
+            <el-form :model="{ phone }" ref="phoneForm">
+                <el-form-item prop="phone" :rules="[{ required: true, message: '请输入手机号' }]">
+                    <el-input
+                        v-model="phone"
+                        type="textarea"
+                        :autosize="{ minRows: 3 }"
+                        placeholder="可输入多个手机号,用空格或回车分隔"
+                    ></el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer">
+                <el-button @click="showPhoneDialog = false" :disabled="searchingPhone" size="mini">取消</el-button>
+                <el-button @click="savePhone" :loading="searchingPhone" size="mini" type="primary">确定</el-button>
+            </div>
         </el-dialog>
     </div>
 </template>
@@ -80,7 +104,9 @@ export default {
     data() {
         return {
             saving: false,
-            formData: {},
+            formData: {
+                couponLimited: false
+            },
             rules: {
                 name: [
                     {
@@ -89,26 +115,48 @@ export default {
                         trigger: 'blur'
                     }
                 ],
-                phone: [
+                type: [
                     {
                         required: true,
-                        message: '请输入手机号',
+                        message: '请输入空投类型',
                         trigger: 'blur'
                     }
                 ],
-                type: [
+                userIds: [
                     {
-                        required: true,
-                        message: '请输入空投类型',
+                        validator: (rule, value, callback) => {
+                            if (value && value.length > 0) {
+                                callback();
+                            } else {
+                                callback(new Error('请添加空投对象'));
+                            }
+                        },
+                        trigger: 'blur'
+                    }
+                ],
+                couponName: [{ required: true, message: '请输入兑换券名称' }],
+                couponCollectionIds: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (value && value.length > 0) {
+                                callback();
+                            } else {
+                                callback(new Error('请添加优惠券可用对象'));
+                            }
+                        },
                         trigger: 'blur'
                     }
-                ]
+                ],
+                couponExpiration: [{ required: true, message: '请输入兑换券过期时间' }]
             },
             typeOptions: [
                 { label: '藏品', value: 'asset' },
                 { label: '兑换券', value: 'coupon' }
             ],
-            phone: ''
+            phone: '',
+            showPhoneDialog: false,
+            searchingPhone: false,
+            users: []
         };
     },
     methods: {
@@ -153,6 +201,52 @@ export default {
                         this.$message.error((e || {}).error || '删除失败');
                     }
                 });
+        },
+        addUser() {
+            this.phone = '';
+            this.showPhoneDialog = true;
+            if (this.$refs.phoneForm) {
+                this.$nextTick(() => {
+                    this.$refs.phoneForm.clearValidate();
+                });
+            }
+        },
+        savePhone() {
+            this.$refs.phoneForm
+                .validate()
+                .then(res => {
+                    this.searchingPhone = true;
+                    this.$http
+                        .post('/user/searchByPhoneAdmin', { phone: this.phone })
+                        .then(res => {
+                            this.showPhoneDialog = false;
+                            this.searchingPhone = false;
+                            this.users = this.users.concat(res.users.filter(i => !this.users.find(e => e.id === i.id)));
+                            if (res.notFound && res.notFound.length) {
+                                this.$alert('未找到以下手机对应的用户:<br>' + res.notFound.join('、'), '', {
+                                    dangerouslyUseHTMLString: true
+                                });
+                            }
+                        })
+                        .catch(e => {
+                            this.searchingPhone = false;
+                            console.log(e);
+                        });
+                })
+                .catch(e => {
+                    console.log(e);
+                });
+        },
+        delUser(index) {
+            this.users.splice(index, 1);
+        }
+    },
+    watch: {
+        users(val) {
+            if (val) {
+                this.formData.userIds = val.map(i => i.id);
+                this.formData.phone = val.map(i => i.phone);
+            }
         }
     }
 };

+ 136 - 95
src/main/vue/src/views/CouponEdit.vue

@@ -2,51 +2,46 @@
     <div class="edit-view">
         <page-title>
             <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
-            <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
-                删除
-            </el-button>
+            <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id"> 删除 </el-button>
             <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
         </page-title>
         <div class="edit-view__content-wrapper">
             <div class="edit-view__content-section">
-                <el-form :model="formData" :rules="rules" ref="form" label-width="108px" label-position="right"
-                         size="small"
-                         style="max-width: 500px;">
-                        <el-form-item prop="name" label="名称">
-                                    <el-input v-model="formData.name"></el-input>
-                        </el-form-item>
-                        <el-form-item prop="remark" label="备注">
-                                    <el-input v-model="formData.remark"></el-input>
-                        </el-form-item>
-                        <el-form-item prop="limited" label="指定藏品可用">
-                                    <el-input v-model="formData.limited"></el-input>
-                        </el-form-item>
-                        <el-form-item prop="collectionIds" label="藏品ID">
-                                    <el-input v-model="formData.collectionIds"></el-input>
-                        </el-form-item>
-                        <el-form-item prop="expiration" label="到期时间">
-                                    <el-date-picker
-                                            v-model="formData.expiration"
-                                            type="datetime"
-                                            value-format="yyyy-MM-dd HH:mm:ss"
-                                            placeholder="选择日期时间">
-                                    </el-date-picker>
-                        </el-form-item>
-                        <el-form-item prop="used" label="used">
-                                    <el-input v-model="formData.used"></el-input>
-                        </el-form-item>
-                        <el-form-item prop="useTime" label="useTime">
-                                    <el-date-picker
-                                            v-model="formData.useTime"
-                                            type="datetime"
-                                            value-format="yyyy-MM-dd HH:mm:ss"
-                                            placeholder="选择日期时间">
-                                    </el-date-picker>
-                        </el-form-item>
+                <el-form
+                    :model="formData"
+                    :rules="rules"
+                    ref="form"
+                    label-width="108px"
+                    label-position="right"
+                    size="small"
+                    style="max-width: 500px"
+                >
+                    <el-form-item prop="name" label="名称">
+                        <el-input v-model="formData.name"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="remark" label="备注">
+                        <el-input v-model="formData.remark"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="needGas" label="需要支付GAS">
+                        <el-switch v-model="formData.needGas"></el-switch>
+                    </el-form-item>
+                    <el-form-item prop="limited" label="指定藏品">
+                        <el-switch v-model="formData.limited"></el-switch>
+                    </el-form-item>
+                    <el-form-item prop="collectionIds" label="藏品" v-if="formData.limited">
+                        <el-input v-model="formData.collectionIds"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="expiration" label="到期时间">
+                        <el-date-picker
+                            v-model="formData.expiration"
+                            type="datetime"
+                            value-format="yyyy-MM-dd HH:mm:ss"
+                            placeholder="选择日期时间"
+                        >
+                        </el-date-picker>
+                    </el-form-item>
                     <el-form-item class="form-submit">
-                        <el-button @click="onSave" :loading="saving" type="primary">
-                            保存
-                        </el-button>
+                        <el-button @click="onSave" :loading="saving" type="primary"> 保存 </el-button>
                         <el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
                             删除
                         </el-button>
@@ -58,71 +53,117 @@
     </div>
 </template>
 <script>
-    export default {
-        name: 'CouponEdit',
-        created() {
-            if (this.$route.query.id) {
-                this.$http
-                    .get('coupon/get/' + this.$route.query.id)
-                    .then(res => {
-                        this.formData = res;
-                    })
-                    .catch(e => {
-                        console.log(e);
-                        this.$message.error(e.error);
-                    });
-            }
-        },
-        data() {
-            return {
-                saving: false,
-                formData: {
-                },
-                rules: {
-                },
-            }
-        },
-        methods: {
-            onSave() {
-                this.$refs.form.validate((valid) => {
-                    if (valid) {
-                        this.submit();
-                    } else {
-                        return false;
-                    }
+export default {
+    name: 'CouponEdit',
+    created() {
+        if (this.$route.query.id) {
+            this.$http
+                .get('coupon/get/' + this.$route.query.id)
+                .then(res => {
+                    this.formData = res;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
                 });
+        }
+    },
+    data() {
+        return {
+            saving: false,
+            formData: {
+                limited: true,
+                needGas: true
             },
-            submit() {
-                let data = {...this.formData};
-
-                this.saving = true;
-                this.$http
-                    .post('/coupon/save', data, {body: 'json'})
-                    .then(res => {
-                        this.saving = false;
-                        this.$message.success('成功');
-                        this.$router.go(-1);
-                    })
-                    .catch(e => {
-                        console.log(e);
-                        this.saving = false;
-                        this.$message.error(e.error);
-                    });
+            rules: {
+                name: [
+                    {
+                        required: true,
+                        message: '请输入名称',
+                        trigger: 'blur'
+                    }
+                ],
+                limited: [
+                    {
+                        required: true,
+                        message: '请输入指定藏品',
+                        trigger: 'blur'
+                    }
+                ],
+                needGas: [
+                    {
+                        required: true,
+                        message: '请输入需要支付GAS',
+                        trigger: 'blur'
+                    }
+                ],
+                expiration: [
+                    {
+                        required: true,
+                        message: '请输入到期时间',
+                        trigger: 'blur'
+                    }
+                ],
+                collectionIds: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (value && value.length > 0) {
+                                callback();
+                            } else {
+                                callback(new Error('请添加藏品'));
+                            }
+                        },
+                        trigger: 'blur'
+                    }
+                ]
             },
-            onDelete() {
-                this.$confirm('删除将无法恢复,确认要删除么?', '警告', {type: 'error'}).then(() => {
-                    return this.$http.post(`/coupon/del/${this.formData.id}`)
-                }).then(() => {
+            collections: []
+        };
+    },
+    methods: {
+        onSave() {
+            this.$refs.form.validate(valid => {
+                if (valid) {
+                    this.submit();
+                } else {
+                    return false;
+                }
+            });
+        },
+        submit() {
+            let data = { ...this.formData };
+
+            this.saving = true;
+            this.$http
+                .post('/coupon/save', data, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    this.$message.success('成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    this.$message.error(e.error);
+                });
+        },
+        onDelete() {
+            this.$confirm('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/coupon/del/${this.formData.id}`);
+                })
+                .then(() => {
                     this.$message.success('删除成功');
                     this.$router.go(-1);
-                }).catch(e => {
+                })
+                .catch(e => {
                     if (e !== 'cancel') {
                         console.log(e);
                         this.$message.error((e || {}).error || '删除失败');
                     }
-                })
-            },
+                });
         }
     }
+};
 </script>
 <style lang="less" scoped></style>

+ 138 - 131
src/main/vue/src/views/CouponList.vue

@@ -1,61 +1,64 @@
 <template>
-    <div  class="list-view">
+    <div class="list-view">
         <page-title>
-            <el-button @click="addRow" type="primary" icon="el-icon-plus" :disabled="fetchingData || downloading" class="filter-item">
+            <el-button
+                @click="addRow"
+                type="primary"
+                icon="el-icon-plus"
+                :disabled="fetchingData || downloading"
+                class="filter-item"
+            >
                 新增
             </el-button>
-            <el-button @click="download" icon="el-icon-upload2" :loading="downloading" :disabled="fetchingData" class="filter-item">
+            <!-- <el-button
+                @click="download"
+                icon="el-icon-upload2"
+                :loading="downloading"
+                :disabled="fetchingData"
+                class="filter-item"
+            >
                 导出
-            </el-button>
+            </el-button> -->
         </page-title>
         <div class="filters-container">
             <el-input
-                    placeholder="搜索..."
-                    v-model="search"
-                    clearable
-                    class="filter-item search"
-                    @keyup.enter.native="getData"
+                placeholder="搜索..."
+                v-model="search"
+                clearable
+                class="filter-item search"
+                @keyup.enter.native="getData"
             >
                 <el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
             </el-input>
         </div>
-        <el-table :data="tableData" row-key="id" ref="table"
-                  header-row-class-name="table-header-row"
-                  header-cell-class-name="table-header-cell"
-                  row-class-name="table-row" cell-class-name="table-cell"
-                  :height="tableHeight" v-loading="fetchingData">
-            <el-table-column v-if="multipleMode" align="center" type="selection"
-                             width="50">
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            :height="tableHeight"
+            v-loading="fetchingData"
+        >
+            <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+            <el-table-column prop="id" label="ID" width="100"> </el-table-column>
+            <el-table-column prop="name" label="名称"> </el-table-column>
+            <el-table-column prop="remark" label="备注" show-overflow-tooltip> </el-table-column>
+            <el-table-column prop="limited" label="指定藏品">
+                <template slot-scope="{ row }">
+                    <el-tag :type="row.limited ? '' : 'info'">{{ row.limited }}</el-tag>
+                </template>
             </el-table-column>
-            <el-table-column prop="id" label="ID" width="100">
+            <el-table-column prop="needGas" label="需要支付GAS">
+                <template slot-scope="{ row }">
+                    <el-tag :type="row.needGas ? '' : 'info'">{{ row.needGas }}</el-tag>
+                </template>
             </el-table-column>
-                                <el-table-column prop="name" label="名称"
->
-                    </el-table-column>
-                    <el-table-column prop="remark" label="备注"
->
-                    </el-table-column>
-                    <el-table-column prop="limited" label="指定藏品可用"
->
-                    </el-table-column>
-                    <el-table-column prop="collectionIds" label="藏品ID"
->
-                    </el-table-column>
-                    <el-table-column prop="expiration" label="到期时间"
->
-                    </el-table-column>
-                    <el-table-column prop="used" label="used"
->
-                    </el-table-column>
-                    <el-table-column prop="useTime" label="useTime"
->
-                    </el-table-column>
-            <el-table-column
-                    label="操作"
-                    align="center"
-                    fixed="right"
-                    width="150">
-                <template slot-scope="{row}">
+            <el-table-column prop="expiration" label="到期时间"> </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="150">
+                <template slot-scope="{ row }">
                     <el-button @click="editRow(row)" type="primary" size="mini" plain>编辑</el-button>
                     <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</el-button>
                 </template>
@@ -70,112 +73,116 @@
                     <el-button @click="toggleMultipleMode(false)">取消</el-button>
                 </el-button-group>
             </div> -->
-            <el-pagination background @size-change="onSizeChange"
-                           @current-change="onCurrentChange" :current-page="page"
-                           :page-sizes="[10, 20, 30, 40, 50]" :page-size="pageSize"
-                           layout="total, sizes, prev, pager, next, jumper"
-                           :total="totalElements">
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
             </el-pagination>
         </div>
-
     </div>
 </template>
 <script>
-    import { mapState } from "vuex";
-    import pageableTable from "@/mixins/pageableTable";
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
 
-    export default {
-        name: 'CouponList',
-        mixins: [pageableTable],
-        data() {
-            return {
-                multipleMode: false,
-                search: "",
-                url: "/coupon/all",
-                downloading: false,
-            }
+export default {
+    name: 'CouponList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/coupon/all',
+            downloading: false
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        beforeGetData() {
+            return { search: this.search, query: { del: false } };
         },
-        computed: {
-            selection() {
-                return this.$refs.table.selection.map(i => i.id);
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
             }
         },
-        methods: {
-            beforeGetData() {
-                return { search: this.search, query: { del: false } };
-            },
-            toggleMultipleMode(multipleMode) {
-                this.multipleMode = multipleMode;
-                if (!multipleMode) {
-                    this.$refs.table.clearSelection();
+        addRow() {
+            this.$router.push({
+                path: '/couponEdit',
+                query: {
+                    ...this.$route.query
                 }
-            },
-            addRow() {
-                this.$router.push({
-                    path: "/couponEdit",
-                    query: {
-                        ...this.$route.query
-                    }
-                });
-            },
-            editRow(row) {
-                this.$router.push({
-                    path: "/couponEdit",
-                    query: {
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/couponEdit',
+                query: {
                     id: row.id
-                    }
-                });
-            },
-            download() {
-                this.downloading = true;
-                this.$axios
-                    .get("/coupon/excel", { 
-                        responseType: "blob",
-                        params: { size: 10000 }
-                    })
-                    .then(res => {
-                        console.log(res);
-                        this.downloading = false;
-                        const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
-                        const link = document.createElement("a");
-                        link.href = downloadUrl;
-                        link.setAttribute(
-                            "download",
-                            res.headers["content-disposition"].split("filename=")[1]
-                        );
-                        document.body.appendChild(link);
-                        link.click();
-                        link.remove();
-                    })
-                    .catch(e => {
-                        console.log(e);
-                        this.downloading = false;
-                        this.$message.error(e.error);
-                    });
-            },
-            operation1() {
-                this.$notify({
-                    title: '提示',
-                    message: this.selection
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/coupon/excel', {
+                    responseType: 'blob',
+                    params: { size: 10000 }
+                })
+                .then(res => {
+                    console.log(res);
+                    this.downloading = false;
+                    const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                    const link = document.createElement('a');
+                    link.href = downloadUrl;
+                    link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+                    document.body.appendChild(link);
+                    link.click();
+                    link.remove();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.downloading = false;
+                    this.$message.error(e.error);
                 });
-            },
-            operation2() {
-                this.$message('操作2');
-            },
-            deleteRow(row) {
-                this.$alert('删除将无法恢复,确认要删除么?', '警告', {type: 'error'}).then(() => {
-                    return this.$http.post(`/coupon/del/${row.id}`)
-                }).then(() => {
+        },
+        operation1() {
+            this.$notify({
+                title: '提示',
+                message: this.selection
+            });
+        },
+        operation2() {
+            this.$message('操作2');
+        },
+        deleteRow(row) {
+            this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/coupon/del/${row.id}`);
+                })
+                .then(() => {
                     this.$message.success('删除成功');
                     this.getData();
-                }).catch(e => {
+                })
+                .catch(e => {
                     if (e !== 'cancel') {
                         this.$message.error(e.error);
                     }
-                })
-            },
+                });
         }
     }
+};
 </script>
 <style lang="less" scoped>
 </style>