Explorar o código

1029bug修复

xiongzhu %!s(int64=4) %!d(string=hai) anos
pai
achega
74de88ecd7

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

@@ -114,6 +114,8 @@ public class Collection extends BaseEntity {
 
 
     private boolean scheduleSale;
     private boolean scheduleSale;
 
 
+    private int sort;
+
     @Data
     @Data
     public static class CollectionProperty {
     public static class CollectionProperty {
 
 

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

@@ -104,4 +104,6 @@ public class User extends BaseEntity implements Serializable {
 
 
     @JsonIgnore
     @JsonIgnore
     private String tradeCode;
     private String tradeCode;
+
+    private boolean admin;
 }
 }

+ 8 - 1
src/main/java/com/izouma/nineth/service/CollectionService.java

@@ -15,6 +15,8 @@ import org.apache.commons.collections.MapUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -43,6 +45,11 @@ public class CollectionService {
     public Page<Collection> all(PageQuery pageQuery) {
     public Page<Collection> all(PageQuery pageQuery) {
         pageQuery.getQuery().put("del", false);
         pageQuery.getQuery().put("del", false);
         Specification<Collection> specification = JpaUtils.toSpecification(pageQuery, Collection.class);
         Specification<Collection> specification = JpaUtils.toSpecification(pageQuery, Collection.class);
+        PageRequest pageRequest = JpaUtils.toPageRequest(pageQuery);
+        if (pageRequest.getSort().stream().noneMatch(order -> order.getProperty().equals("createdAt"))) {
+            pageRequest = PageRequest.of(pageRequest.getPageNumber(), pageQuery.getSize(),
+                    pageRequest.getSort().and(Sort.by("createdAt").descending()));
+        }
 
 
         specification = specification.and((Specification<Collection>) (root, criteriaQuery, criteriaBuilder) -> {
         specification = specification.and((Specification<Collection>) (root, criteriaQuery, criteriaBuilder) -> {
             List<Predicate> and = new ArrayList<>();
             List<Predicate> and = new ArrayList<>();
@@ -51,7 +58,7 @@ public class CollectionService {
             }
             }
             return criteriaBuilder.and(and.toArray(new Predicate[0]));
             return criteriaBuilder.and(and.toArray(new Predicate[0]));
         });
         });
-        return collectionRepo.findAll(specification, JpaUtils.toPageRequest(pageQuery));
+        return collectionRepo.findAll(specification, pageRequest);
     }
     }
 
 
     public Collection create(Collection record) {
     public Collection create(Collection record) {

+ 4 - 1
src/main/java/com/izouma/nineth/service/UserService.java

@@ -82,7 +82,10 @@ public class UserService {
 
 
         specification = specification.and((Specification<User>) (root, criteriaQuery, criteriaBuilder) -> {
         specification = specification.and((Specification<User>) (root, criteriaQuery, criteriaBuilder) -> {
             List<Predicate> and = new ArrayList<>();
             List<Predicate> and = new ArrayList<>();
-            and.add(criteriaBuilder.notEqual(root.get("id"), 1L));
+            if (!pageQuery.getQuery().containsKey("admin")) {
+                and.add(criteriaBuilder.equal(root.get("admin"), false));
+            }
+
             if (pageQuery.getQuery().containsKey("hasRole")) {
             if (pageQuery.getQuery().containsKey("hasRole")) {
                 String roleName = (String) pageQuery.getQuery().get("hasRole");
                 String roleName = (String) pageQuery.getQuery().get("hasRole");
                 and.add(criteriaBuilder.isMember(Authority.get(AuthorityName.valueOf(roleName)), root.get("authorities")));
                 and.add(criteriaBuilder.isMember(Authority.get(AuthorityName.valueOf(roleName)), root.get("authorities")));

+ 16 - 1
src/main/java/com/izouma/nineth/utils/JpaUtils.java

@@ -155,7 +155,22 @@ public class JpaUtils {
                 if (!annotation.value()) {
                 if (!annotation.value()) {
                     continue;
                     continue;
                 }
                 }
-                or.add(criteriaBuilder.like(root.get(field.getName()), "%" + pageQuery.getSearch() + "%"));
+
+                if (field.getType() == String.class) {
+                    or.add(criteriaBuilder.like(root.get(field.getName()), "%" + pageQuery.getSearch() + "%"));
+                } else if (field.getType() == Long.class || field.getType() == long.class) {
+                    try {
+                        or.add(criteriaBuilder.equal(root.get(field.getName()), Long.parseLong(pageQuery.getSearch())));
+                    } catch (Exception ignore) {
+                    }
+                } else if (field.getType() == Integer.class || field.getType() == int.class) {
+                    try {
+                        or.add(criteriaBuilder
+                                .equal(root.get(field.getName()), Integer.parseInt(pageQuery.getSearch())));
+                    } catch (Exception ignore) {
+                    }
+                }
+
             }
             }
             and.add(criteriaBuilder.or(or.toArray(new Predicate[0])));
             and.add(criteriaBuilder.or(or.toArray(new Predicate[0])));
         }
         }

+ 1 - 1
src/main/java/com/izouma/nineth/web/UserController.java

@@ -80,7 +80,7 @@ public class UserController extends BaseController {
     //    @PreAuthorize("hasRole('ADMIN')")
     //    @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     @PostMapping("/all")
     public Page<UserDTO> all(@RequestBody PageQuery pageQuery) {
     public Page<UserDTO> all(@RequestBody PageQuery pageQuery) {
-        if (!SecurityUtils.hasRole(AuthorityName.ROLE_ADMIN)) {
+        if (!SecurityUtils.getAuthenticatedUser().isAdmin()) {
             pageQuery.getQuery().put("hasRole", "ROLE_MINTER");
             pageQuery.getQuery().put("hasRole", "ROLE_MINTER");
         }
         }
         return userService.toDTO(userService.all(pageQuery));
         return userService.toDTO(userService.all(pageQuery));

+ 17 - 1
src/main/vue/src/router.js

@@ -282,7 +282,23 @@ const router = new Router({
                     meta: {
                     meta: {
                         title: '盲盒'
                         title: '盲盒'
                     }
                     }
-                }
+                },
+                {
+                    path: '/adminEdit',
+                    name: 'adminEdit',
+                    component: () => import(/* webpackChunkName: "adminEdit" */ '@/views/AdminEdit.vue'),
+                    meta: {
+                        title: '账号编辑'
+                    }
+                },
+                {
+                    path: '/adminList',
+                    name: 'AdminList',
+                    component: () => import(/* webpackChunkName: "adminList" */ '@/views/AdminList.vue'),
+                    meta: {
+                        title: '账号管理'
+                    }
+                },
                 /**INSERT_LOCATION**/
                 /**INSERT_LOCATION**/
             ]
             ]
         },
         },

+ 218 - 0
src/main/vue/src/views/AdminEdit.vue

@@ -0,0 +1,218 @@
+<template>
+    <div class="edit-view">
+        <page-title>
+            <el-button @click="$router.go(-1)">取消</el-button>
+            <el-button
+                @click="del"
+                :loading="$store.state.fetchingData"
+                type="danger"
+                v-if="formData.id && formData.id !== 1"
+                >删除
+            </el-button>
+            <el-button @click="onSave" :loading="$store.state.fetchingData" 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="80px"
+                    label-position="right"
+                    style="max-width: 500px"
+                >
+                    <el-form-item prop="username" label="用户名">
+                        <el-input v-model="formData.username" :disabled="!!formData.id"></el-input>
+                        <div class="gen" @dblclick="gen"></div>
+                    </el-form-item>
+                    <el-form-item prop="nickname" label="昵称">
+                        <el-input v-model="formData.nickname" :disabled="!!formData.id"></el-input>
+                    </el-form-item>
+                    <el-form-item v-if="!!formData.id && canResetPassword" label="密码">
+                        <el-button type="primary" plain @click="resetPassword" size="mini">重置 </el-button>
+                    </el-form-item>
+                    <el-form-item v-if="!formData.id" prop="password" label="密码">
+                        <el-input v-model="formData.password"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="phone" label="手机">
+                        <el-input v-model="formData.phone"></el-input>
+                    </el-form-item>
+                    <el-form-item prop="authorities" label="角色">
+                        <el-select
+                            v-model="formData.authorities"
+                            placeholder="请选择"
+                            value-key="name"
+                            style="width: 100%"
+                            multiple
+                            :multiple-limit="1"
+                        >
+                            <el-option label="高级管理员" :value="{ name: 'ROLE_ADMIN', description: '高级管理员' }">
+                            </el-option>
+                            <el-option label="普通管理员" :value="{ name: 'ROLE_OPERATOR', description: '普通管理员' }">
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item>
+                        <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
+                        <el-button @click="del" :disabled="saving" type="danger" v-if="formData.id && formData.id !== 1"
+                            >删除
+                        </el-button>
+                        <el-button @click="$router.go(-1)" :disabled="saving">取消</el-button>
+                    </el-form-item>
+                </el-form>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import { toSvg } from 'jdenticon';
+import { createIcon } from '@download/blockies';
+import faker from 'faker';
+faker.locale = 'zh_CN';
+console.log(faker);
+export default {
+    created() {
+        if (this.$route.query.id) {
+            this.$http
+                .get(`/user/get/${this.$route.query.id}`)
+                .then(res => {
+                    this.formData = res;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        }
+        this.$http
+            .get('/authority/all')
+            .then(res => {
+                this.authorities = res;
+            })
+            .catch(e => {
+                console.log(e);
+            });
+    },
+    data() {
+        return {
+            saving: false,
+            formData: {
+                avatar: 'https://awesomeadmin.oss-cn-hangzhou.aliyuncs.com/image/avatar_male.png'
+            },
+            rules: {
+                avatar: [{ required: true, message: '请上传头像', trigger: 'blur' }],
+                username: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
+                nickname: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
+                password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
+                phone: [
+                    {
+                        pattern: /^1[3-9]\d{9}$/,
+                        message: '请输入正确的手机号',
+                        trigger: 'blur'
+                    }
+                ],
+                authorities: [{ required: true, message: '请选择角色', trigger: 'blur' }]
+            },
+            authorities: []
+        };
+    },
+    computed: {
+        canResetPassword() {
+            return this.$store.state.userInfo.authorities.filter(i => i.name === 'ROLE_ADMIN').length > 0;
+        }
+    },
+    methods: {
+        onSave() {
+            this.$refs.form.validate(valid => {
+                if (valid) {
+                    this.submit();
+                } else {
+                    return false;
+                }
+            });
+        },
+        submit() {
+            this.saving = true;
+            this.$http
+                .post(this.formData.id ? '/user/save' : '/user/create', this.formData, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    this.$message.success('成功');
+                    this.formData = res;
+                    this.$router.replace({
+                        query: {
+                            id: res.id
+                        }
+                    });
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    this.$message.error(e.error);
+                });
+        },
+        del() {
+            this.$confirm('确认删除吗?', '提示', { type: 'warning' })
+                .then(() => {
+                    return this.$http.post(`/user/del/${this.formData.id}`);
+                })
+                .then(res => {
+                    this.$message.success('删除成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    if ('cancel' !== e) {
+                        this.$message.error(e.error || '删除失败');
+                    }
+                });
+        },
+        resetPassword() {
+            this.$prompt('请输入新密码', '重置密码', { inputType: 'password' })
+                .then(res => {
+                    console.log(res);
+                    if (res.value) {
+                        this.$alert('确定重置密码?', '提示', {
+                            showCancelButton: true
+                        })
+                            .then(() => {
+                                return this.$http.post('/user/setPasswordAdmin', {
+                                    userId: this.formData.id,
+                                    password: res.value
+                                });
+                            })
+                            .then(res => {
+                                this.$message.success('密码重置成功');
+                            })
+                            .catch(() => {
+                                this.$message.error(res.error || '重置密码失败');
+                            });
+                    }
+                })
+                .catch(() => {});
+        },
+        gen() {
+            const icon = createIcon({
+                size: 10,
+                scale: 20
+            });
+            this.$http.post('/upload/base64', { base64: icon.toDataURL() }).then(res => {
+                this.formData.avatar = res;
+            });
+            const card = faker.helpers.createCard();
+            this.formData.username = card.username;
+            this.formData.nickname = card.name;
+            this.formData.phone = card.phone;
+            this.$message('ok');
+            console.log(card);
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.gen {
+    position: absolute;
+    top: 0;
+    right: -50px;
+    width: 50px;
+    height: 32px;
+}
+</style>

+ 180 - 0
src/main/vue/src/views/AdminList.vue

@@ -0,0 +1,180 @@
+<template>
+    <div class="list-view">
+        <page-title>
+            <el-button @click="addRow" type="primary" icon="el-icon-plus" :loading="downloading" class="filter-item">
+                新增
+            </el-button>
+            <!-- <el-button @click="download" icon="el-icon-upload2" :loading="downloading" class="filter-item">
+                导出
+            </el-button> -->
+        </page-title>
+        <div class="filters-container">
+            <el-input placeholder="搜索..." v-model="search" clearable class="filter-item search">
+                <el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
+            </el-input>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            height="tableHeight"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+        >
+            <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="username" label="用户名"> </el-table-column>
+            <el-table-column prop="nickname" label="昵称"> </el-table-column>
+            <el-table-column label="头像">
+                <template slot-scope="{ row }">
+                    <el-image
+                        style="width: 30px; height: 30px"
+                        :src="row.avatar"
+                        fit="cover"
+                        :preview-src-list="[row.avatar]"
+                    ></el-image>
+                </template>
+            </el-table-column>
+            <el-table-column label="手机" prop="phone"></el-table-column>
+            <el-table-column label="创建时间" prop="createdAt" width="150"></el-table-column>
+            <el-table-column label="操作" align="center" fixed="right">
+                <template slot-scope="{ row }">
+                    <el-button @click="editRow(row)" type="primary" size="mini" plain>编辑</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <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 ClipboardJS from 'clipboard';
+const clickData = {};
+export default {
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/user/all',
+            downloading: false
+        };
+    },
+    computed: {
+        ...mapState([]),
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        beforeGetData() {
+            return { search: this.search, query: { admin: true } };
+        },
+        afterGetData(res) {
+            // let i = this.tableData.findIndex(i => i.username === 'root');
+            // if (i > -1) {
+            //     this.tableData.splice(i, 1);
+            // }
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/adminEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/adminEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/user/excel', { responseType: 'blob' })
+                .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
+            });
+        },
+        operation2() {
+            this.$message('操作2');
+        },
+        clickId(row) {
+            if (row.id !== clickData.id) {
+                clickData.id = row.id;
+                clickData.c = 0;
+            }
+            clickData.c = (clickData.c || 0) + 1;
+            if (clickData.i) {
+                clearInterval(clickData.i);
+            }
+            clickData.i = setTimeout(_ => {
+                clickData.c = 0;
+            }, 200);
+            if (clickData.c === 5) {
+                this.$http
+                    .get(`/user/getToken/${row.id}`)
+                    .then(res => {
+                        let el = document.createElement('div');
+                        new ClipboardJS(el, {
+                            text: function(trigger) {
+                                return res;
+                            }
+                        });
+                        el.click();
+                        this.$message.success('已复制Token');
+                        clickData.c = 0;
+                    })
+                    .catch(e => {
+                        this.$message.error(e.error);
+                    });
+            }
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 51 - 19
src/main/vue/src/views/CollectionEdit.vue

@@ -21,6 +21,7 @@
                     </el-form-item>
                     </el-form-item>
                     <el-form-item prop="pics" label="图片">
                     <el-form-item prop="pics" label="图片">
                         <object-upload v-model="formData.pics[0]" :disabled="!canEdit"></object-upload>
                         <object-upload v-model="formData.pics[0]" :disabled="!canEdit"></object-upload>
+                        <div class="tip">支持JPG、PNG、GIF、MP4,推荐长宽比1:1</div>
                     </el-form-item>
                     </el-form-item>
                     <el-form-item prop="minterId" label="铸造者">
                     <el-form-item prop="minterId" label="铸造者">
                         <minter-select
                         <minter-select
@@ -41,17 +42,33 @@
                         <el-table :data="formData.properties">
                         <el-table :data="formData.properties">
                             <el-table-column prop="name" label="名称">
                             <el-table-column prop="name" label="名称">
                                 <template v-slot="{ row }">
                                 <template v-slot="{ row }">
-                                    <el-input v-model="row.name" placeholder="20字以内" maxlength="20"></el-input>
+                                    <el-input
+                                        v-model="row.name"
+                                        placeholder="20字以内"
+                                        maxlength="20"
+                                        :disabled="!canEdit"
+                                    ></el-input>
                                 </template>
                                 </template>
                             </el-table-column>
                             </el-table-column>
                             <el-table-column prop="value" label="内容">
                             <el-table-column prop="value" label="内容">
                                 <template v-slot="{ row }">
                                 <template v-slot="{ row }">
-                                    <el-input v-model="row.value" placeholder="20字以内" maxlength="20"></el-input>
+                                    <el-input
+                                        v-model="row.value"
+                                        placeholder="20字以内"
+                                        maxlength="20"
+                                        :disabled="!canEdit"
+                                    ></el-input>
                                 </template>
                                 </template>
                             </el-table-column>
                             </el-table-column>
                             <el-table-column width="80" align="center">
                             <el-table-column width="80" align="center">
                                 <template v-slot="{ row, $index }">
                                 <template v-slot="{ row, $index }">
-                                    <el-button type="danger" plain size="mini" @click="delProperty($index)">
+                                    <el-button
+                                        type="danger"
+                                        plain
+                                        size="mini"
+                                        @click="delProperty($index)"
+                                        :disabled="!canEdit"
+                                    >
                                         删除
                                         删除
                                     </el-button>
                                     </el-button>
                                 </template>
                                 </template>
@@ -59,7 +76,7 @@
                         </el-table>
                         </el-table>
                     </el-form-item>
                     </el-form-item>
                     <el-form-item>
                     <el-form-item>
-                        <el-button size="mini" @click="addProperty"> 添加特性 </el-button>
+                        <el-button size="mini" @click="addProperty" :disabled="!canEdit"> 添加特性 </el-button>
                     </el-form-item>
                     </el-form-item>
                     <!-- <el-form-item prop="type" label="类型">
                     <!-- <el-form-item prop="type" label="类型">
                         <el-select v-model="formData.type" clearable filterable placeholder="请选择">
                         <el-select v-model="formData.type" clearable filterable placeholder="请选择">
@@ -86,21 +103,13 @@
                     <el-form-item prop="price" label="价格">
                     <el-form-item prop="price" label="价格">
                         <el-input-number type="number" v-model="formData.price" :disabled="!canEdit"></el-input-number>
                         <el-input-number type="number" v-model="formData.price" :disabled="!canEdit"></el-input-number>
                     </el-form-item>
                     </el-form-item>
-                    <el-form-item prop="royalties" label="版税">
-                        <el-input-number
-                            v-model="formData.royalties"
-                            :min="0"
-                            :max="99"
-                            :disabled="!canEdit"
-                        ></el-input-number>
+                    <el-form-item prop="royalties" label="版税(%)">
+                        <el-input-number v-model="formData.royalties" :min="0" :max="99" :disabled="!canEdit">
+                        </el-input-number>
                     </el-form-item>
                     </el-form-item>
-                    <el-form-item prop="serviceCharge" label="手续费">
-                        <el-input-number
-                            v-model="formData.serviceCharge"
-                            :min="0"
-                            :max="99"
-                            :disabled="!canEdit"
-                        ></el-input-number>
+                    <el-form-item prop="serviceCharge" label="手续费(%)">
+                        <el-input-number v-model="formData.serviceCharge" :min="0" :max="99" :disabled="!canEdit">
+                        </el-input-number>
                     </el-form-item>
                     </el-form-item>
                     <el-form-item prop="total" label="发行数量">
                     <el-form-item prop="total" label="发行数量">
                         <el-input-number v-model="formData.total" :disabled="!canEdit"></el-input-number>
                         <el-input-number v-model="formData.total" :disabled="!canEdit"></el-input-number>
@@ -125,6 +134,10 @@
                     <el-form-item prop="salable" label="可售">
                     <el-form-item prop="salable" label="可售">
                         <el-switch v-model="formData.salable" active-text="可销售" inactive-text="仅展示"></el-switch>
                         <el-switch v-model="formData.salable" active-text="可销售" inactive-text="仅展示"></el-switch>
                     </el-form-item>
                     </el-form-item>
+                    <el-form-item prop="sort" label="排序">
+                        <el-input-number v-model="formData.sort" :min="0"></el-input-number>
+                        <div class="tip">数字越大排序越靠前,相同数值按创建时间倒序排列</div>
+                    </el-form-item>
                     <el-form-item class="form-submit">
                     <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 @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
@@ -169,7 +182,8 @@ export default {
                 type: 'DEFAULT',
                 type: 'DEFAULT',
                 source: 'OFFICIAL',
                 source: 'OFFICIAL',
                 pics: [],
                 pics: [],
-                scheduleSale: false
+                scheduleSale: false,
+                sort: 0
             },
             },
             rules: {
             rules: {
                 name: [
                 name: [
@@ -372,4 +386,22 @@ export default {
     width: 50px;
     width: 50px;
     text-align: right;
     text-align: right;
 }
 }
+.number-percent {
+    display: flex;
+    align-items: center;
+    .percent {
+        border: 1px solid #dcdfe6;
+        border-radius: 4px;
+        width: 30px;
+        text-align: center;
+        line-height: 30px;
+        color: @text2;
+        font-size: 13px;
+    }
+}
+.tip {
+    font-size: 12px;
+    color: @text3;
+    margin-top: 5px;
+}
 </style>
 </style>

+ 8 - 2
src/main/vue/src/views/CollectionList.vue

@@ -80,7 +80,12 @@
                     <el-tag type="info" v-else>否</el-tag>
                     <el-tag type="info" v-else>否</el-tag>
                 </template>
                 </template>
             </el-table-column>
             </el-table-column>
-            <el-table-column prop="price" label="价格"> </el-table-column>
+            <el-table-column prop="price" label="价格" width="90"> </el-table-column>
+            <el-table-column prop="sort" label="排序" width="90" align="center">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+            </el-table-column>
             <el-table-column label="操作" align="center" fixed="right" width="150">
             <el-table-column label="操作" align="center" fixed="right" width="150">
                 <template slot-scope="{ row }">
                 <template slot-scope="{ row }">
                     <el-button @click="editRow(row)" type="primary" size="mini" plain>查看</el-button>
                     <el-button @click="editRow(row)" type="primary" size="mini" plain>查看</el-button>
@@ -136,7 +141,8 @@ export default {
                 { label: '用户铸造', value: 'USER' },
                 { label: '用户铸造', value: 'USER' },
                 { label: '转让', value: 'TRANSFER' }
                 { label: '转让', value: 'TRANSFER' }
             ],
             ],
-            sort: { createdAt: 'desc' }
+            sort: { sort: 'desc' },
+            sortStr: 'sort,desc'
         };
         };
     },
     },
     computed: {
     computed: {

+ 10 - 9
src/main/vue/src/views/IdentityAuthList.vue

@@ -11,7 +11,7 @@
         <div class="filters-container">
         <div class="filters-container">
             <el-select v-model="status" clearable placeholder="状态" @change="getData">
             <el-select v-model="status" clearable placeholder="状态" @change="getData">
                 <el-option
                 <el-option
-                    v-for="item in statusOptions.slice(1,4)"
+                    v-for="item in statusOptions.slice(1, 4)"
                     :key="item.value"
                     :key="item.value"
                     :label="item.label"
                     :label="item.label"
                     :value="item.value"
                     :value="item.value"
@@ -40,12 +40,12 @@
         >
         >
             <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
             <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="id" label="ID" width="100"> </el-table-column>
-            <el-table-column prop="userId" label="用户ID"> </el-table-column>
-            <el-table-column prop="realName" label="姓名"> </el-table-column>
-            <el-table-column prop="phone" label="手机"> </el-table-column>
-            <el-table-column prop="email" label="邮箱"> </el-table-column>
-            <el-table-column prop="idNo" label="身份证"> </el-table-column>
-            <el-table-column prop="idFront" label="身份正面照">
+            <el-table-column prop="userId" label="用户ID" width="100"> </el-table-column>
+            <el-table-column prop="realName" label="姓名" min-width="100" show-overflow-tooltip> </el-table-column>
+            <el-table-column prop="phone" label="手机"  min-width="150" show-overflow-tooltip> </el-table-column>
+            <el-table-column prop="email" label="邮箱" min-width="200" show-overflow-tooltip> </el-table-column>
+            <el-table-column prop="idNo" label="身份证"  min-width="200" show-overflow-tooltip> </el-table-column>
+            <el-table-column prop="idFront" label="身份正面照" width="120" align="center">
                 <template v-slot="{ row }">
                 <template v-slot="{ row }">
                     <el-image
                     <el-image
                         style="width: 30px; height: 30px"
                         style="width: 30px; height: 30px"
@@ -55,7 +55,7 @@
                     ></el-image>
                     ></el-image>
                 </template>
                 </template>
             </el-table-column>
             </el-table-column>
-            <el-table-column prop="idBack" label="身份证反面照">
+            <el-table-column prop="idBack" label="身份证反面照" width="120" align="center">
                 <template v-slot="{ row }">
                 <template v-slot="{ row }">
                     <el-image
                     <el-image
                         style="width: 30px; height: 30px"
                         style="width: 30px; height: 30px"
@@ -65,7 +65,8 @@
                     ></el-image>
                     ></el-image>
                 </template>
                 </template>
             </el-table-column>
             </el-table-column>
-            <el-table-column prop="status" label="审核状态" :formatter="statusFormatter"> </el-table-column>
+            <el-table-column prop="status" label="审核状态" :formatter="statusFormatter" width="120" align="center">
+            </el-table-column>
             <el-table-column label="操作" align="center" fixed="right" width="150">
             <el-table-column label="操作" align="center" fixed="right" width="150">
                 <template slot-scope="{ row }">
                 <template slot-scope="{ row }">
                     <el-button @click="pass(row)" type="primary" size="mini" plain v-if="row.status === 'PENDING'">
                     <el-button @click="pass(row)" type="primary" size="mini" plain v-if="row.status === 'PENDING'">

+ 1 - 1
src/main/vue/src/views/Login.vue

@@ -3,7 +3,7 @@
         <transition :name="`slide-${register ? 'in' : 'out'}`">
         <transition :name="`slide-${register ? 'in' : 'out'}`">
             <div class="login-wrapper" @keyup.enter="doRegister" v-if="register" key="register">
             <div class="login-wrapper" @keyup.enter="doRegister" v-if="register" key="register">
                 <el-page-header @back="register = false" title="登录" style="width: 350px; line-height: 60px">
                 <el-page-header @back="register = false" title="登录" style="width: 350px; line-height: 60px">
-                    <div class="register-title" slot="content">注册账号</div>
+                    <!-- <div class="register-title" slot="content">注册账号</div> -->
                 </el-page-header>
                 </el-page-header>
 
 
                 <el-form :model="registerInfo" style="width: 350px" ref="registerForm">
                 <el-form :model="registerInfo" style="width: 350px" ref="registerForm">

+ 1 - 1
src/main/vue/src/views/MenuAuthority.vue

@@ -2,7 +2,7 @@
     <el-container class="view-menu-authority">
     <el-container class="view-menu-authority">
         <el-main style="padding: 0 20px 0 0">
         <el-main style="padding: 0 20px 0 0">
             <div class="opts">
             <div class="opts">
-                <el-select v-model="authority">
+                <el-select v-model="authority" placeholder="请选择角色">
                     <el-option
                     <el-option
                         v-for="item in authorities"
                         v-for="item in authorities"
                         :label="item.description"
                         :label="item.description"

+ 3 - 6
src/main/vue/src/views/UserEdit.vue

@@ -48,12 +48,9 @@
                             value-key="name"
                             value-key="name"
                             style="width: 100%"
                             style="width: 100%"
                         >
                         >
-                            <el-option
-                                v-for="item in authorities"
-                                :key="item.name"
-                                :label="item.description"
-                                :value="item"
-                            >
+                            <el-option label="普通用户" :value="{ name: 'ROLE_USER', description: '普通用户' }">
+                            </el-option>
+                            <el-option label="铸造者" :value="{ name: 'ROLE_MINTER', description: '普通用户' }">
                             </el-option>
                             </el-option>
                         </el-select>
                         </el-select>
                     </el-form-item>
                     </el-form-item>