Переглянути джерело

Merge branch 'master' of http://git.izouma.com/xiongzhu/9th

panhui 4 роки тому
батько
коміт
86e248cf77

+ 4 - 2
src/main/java/com/izouma/nineth/web/CollectionController.java

@@ -3,18 +3,18 @@ package com.izouma.nineth.web;
 import com.izouma.nineth.domain.Collection;
 import com.izouma.nineth.dto.CollectionDTO;
 import com.izouma.nineth.dto.CreateBlindBox;
-import com.izouma.nineth.service.CollectionService;
 import com.izouma.nineth.dto.PageQuery;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.CollectionRepo;
+import com.izouma.nineth.service.CollectionService;
 import com.izouma.nineth.service.LikeService;
 import com.izouma.nineth.utils.ObjUtils;
 import com.izouma.nineth.utils.SecurityUtils;
 import com.izouma.nineth.utils.excel.ExcelUtils;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.data.domain.Page;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
@@ -67,12 +67,14 @@ public class CollectionController extends BaseController {
 
     @GetMapping("/{id}/like")
     @ApiOperation("点赞")
+    @CacheEvict("collection")
     public void like(@PathVariable Long id) {
         likeService.like(SecurityUtils.getAuthenticatedUser().getId(), id);
     }
 
     @GetMapping("/{id}/unlike")
     @ApiOperation("取消点赞")
+    @CacheEvict("collection")
     public void unlike(@PathVariable Long id) {
         likeService.unlike(SecurityUtils.getAuthenticatedUser().getId(), id);
     }

+ 5 - 1
src/main/pc-space/src/components/PageHeader.vue

@@ -21,7 +21,7 @@
                             <img class="img" :src="avatarBox" />
                         </span>
                         <el-dropdown-menu slot="dropdown">
-                            <el-dropdown-item command="nickname" style="word-break: keep-all"> </el-dropdown-item>
+                            <el-dropdown-item command="nickname" style="word-break: keep-all">1111 </el-dropdown-item>
                             <div class="border1"></div>
                             <el-dropdown-item command="supply" style="word-break: keep-all">去认证 </el-dropdown-item>
                             <el-dropdown-item command="edit" style="word-break: keep-all">编辑资料 </el-dropdown-item>
@@ -79,6 +79,10 @@ export default {
         onCommand(command) {
             if (command === 'edit') {
                 this.$router.push('/accountdata');
+            } else if (command === 'logout') {
+                localStorage.removeItem('webToken');
+                this.updateUserInfo(null);
+                this.$router.push('/');
             }
         }
     }

+ 136 - 0
src/main/pc-space/src/components/SecurityPhone.vue

@@ -0,0 +1,136 @@
+<template>
+    <div class="container">
+        <el-steps :space="180" :active="2" align-center>
+            <el-step title="验证当前手机号"></el-step>
+            <el-step title="绑定新手机号"></el-step>
+            <el-step title="完成"></el-step>
+        </el-steps>
+        <el-form :label-position="labelPosition" ref="form2" label-width="340px" :model="ruleForm" :rules="rules">
+            <el-form-item label="新手机号" prop="phone">
+                <el-input style="width: 300px" v-model="ruleForm.phone" placeholder="请输入新的手机号码"></el-input>
+            </el-form-item>
+            <el-form-item label="验证码" prop="code">
+                <el-input style="width: 300px" v-model="ruleForm.code" placeholder="请输入4位验证码">
+                    <span @click="send" style="color: #00ffcb; cursor: pointer; font-size: 13px" slot="suffix">{{
+                        time === 0 ? '发送验证码' : `重新发送${time}s`
+                    }}</span>
+                </el-input>
+            </el-form-item>
+        </el-form>
+        <div class="btn">
+            <el-button type="primary" @click="phoneSend">确认</el-button>
+            <div class="btn2" @click="Jump">返回</div>
+        </div>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+export default {
+    data() {
+        return {
+            labelPosition: 'right',
+            ruleForm: {
+                phone: '',
+                code: ''
+            },
+            time: 0,
+            rules: {}
+        };
+    },
+    computed: {
+        ...mapState(['userInfo'])
+    },
+    methods: {
+        send() {
+            this.sendCode(this.ruleForm.phone);
+        },
+        phoneSend() {
+            if (!/^1[3-9]\d{9}$/.test(this.ruleForm.phone)) {
+                this.$message.error('请输入正确手机号');
+                return;
+            }
+            this.$http
+                .get('/sms/verify', {
+                    phone: this.ruleForm.phone,
+                    code: this.ruleForm.code
+                })
+                .then(() => {
+                    this.$http
+                        .post('/user/changePhone', { phone: this.ruleForm.phone })
+                        .then(() => {
+                            this.$message.warning('更改成功');
+                            localStorage.removeItem('webToken');
+                            this.$store.commit('updateUserInfo', null);
+                        })
+                        .catch(e => {
+                            this.$message.error(e.error);
+                        });
+                })
+                .catch(e => {
+                    this.$message.error(e.error);
+                });
+        },
+        Jump() {
+            this.$emit('Jump');
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+/deep/ .el-steps {
+    margin-left: 385px;
+}
+/deep/.el-step:nth-child(1) {
+    .el-step__icon {
+        background: linear-gradient(143deg, #00ffcb 0%, #006eff 100%, #006eff 100%);
+        color: #ffffff;
+        border: 0;
+    }
+}
+/deep/.el-step:nth-child(2) {
+    .el-step__icon {
+        background: linear-gradient(143deg, #00ffcb 0%, #006eff 100%, #006eff 100%) !important;
+        color: #ffffff;
+        border: 0;
+    }
+}
+/deep/.el-step:nth-child(3) {
+    .el-step__icon {
+        background: #c8c9cc;
+        color: #ffffff;
+        border: 0;
+    }
+}
+/deep/ .el-step__title.is-process {
+    font-weight: 400;
+    color: #939599;
+}
+/deep/ .el-step__title.is-wait {
+    color: #939599;
+}
+.container {
+    .btn {
+        margin: 80px 0 0 110px;
+        display: flex;
+        justify-content: center;
+        .btn2 {
+            width: 130px;
+            height: 36px;
+            background: #c4c7cc;
+            border-radius: 4px;
+            cursor: pointer;
+            color: #ffffff;
+            font-size: 13px;
+            text-align: center;
+            line-height: 36px;
+            margin-left: 20px;
+        }
+    }
+    /deep/ .el-button {
+        width: 130px;
+        height: 36px;
+        background: linear-gradient(133deg, #00ffcb 0%, #006eff 100%);
+        border-radius: 4px;
+    }
+}
+</style>

+ 156 - 0
src/main/pc-space/src/components/SingleUpload.vue

@@ -0,0 +1,156 @@
+<template>
+    <el-upload
+        class="single-upload"
+        :action="uploadUrl"
+        :headers="headers"
+        :show-file-list="false"
+        :on-success="onSuccess"
+        :before-upload="beforeUpload"
+    >
+        <div></div>
+        <div class="wrapper">
+            <img v-if="imageUrl" :src="imageUrl" class="upload-image" />
+            <i v-else class="el-icon-plus single-uploader-icon"></i>
+            <div v-if="loading" class="loading">
+                <i class="el-icon-loading"></i>
+            </div>
+        </div>
+        <div slot="tip" class="el-upload__tip">
+            <slot></slot>
+        </div>
+    </el-upload>
+</template>
+<script>
+import resolveUrl from 'resolve-url';
+export default {
+    created() {
+        this.uploadUrl = resolveUrl(this.$baseUrl, 'upload/file');
+        this.updateImageUrl(this.value);
+    },
+    props: {
+        value: String,
+        usePrefix: {
+            type: Boolean,
+            default: true
+        },
+        size: {
+            tupe: Number,
+            // 单位M
+            default: 1
+        },
+        url: {
+            type: String
+        }
+    },
+    data() {
+        return {
+            imageUrl: '',
+            loading: false,
+            uploadUrl: ''
+        };
+    },
+    computed: {
+        headers() {
+            return {
+                Authorization: 'Bearer ' + localStorage.getItem('webToken')
+            };
+        }
+    },
+    methods: {
+        onSuccess(res, file) {
+            this.loading = false;
+            this.imageUrl = URL.createObjectURL(file.raw);
+            var newVal = '';
+            if (res instanceof Array) {
+                newVal = res[0];
+            } else {
+                newVal = res;
+            }
+            this.$emit('input', newVal);
+        },
+        onError(err, file, fileList) {
+            console.log(err);
+            console.log(file);
+            console.log(fileList);
+            this.loading = false;
+        },
+        beforeUpload(file) {
+            const isLt = file.size / 1024 / 1024 < this.size;
+            const isJPG = file.type === 'image/jpg' || file.type === 'image/png' || file.type === 'image/jpeg';
+            if (!isJPG) {
+                this.$message.error('上传图片只能是JPG、JPEG、PNG格式');
+            }
+            if (!isLt) {
+                this.$message.error('文件大小不能超过' + this.size + ' MB!');
+            }
+            return isJPG && isLt;
+        },
+        updateImageUrl(url) {
+            this.imageUrl = url;
+        }
+    },
+    watch: {
+        value(val) {
+            this.updateImageUrl(val);
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.single-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+    border: 1px solid #494a4d;
+    background: #1c1e26;
+
+    &:hover {
+        border-color: @prim;
+    }
+}
+
+.upload-image {
+    height: 178px;
+    display: block;
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+
+    &:hover {
+        border-color: @prim;
+    }
+}
+
+.wrapper {
+    position: relative;
+}
+
+.single-upload .el-upload {
+    position: relative;
+}
+
+.loading {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    margin: auto;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgba(255, 255, 255, 0.6);
+    color: #333;
+    font-size: 24px;
+}
+</style>

+ 2 - 1
src/main/pc-space/src/main.js

@@ -7,6 +7,7 @@ import ElementUI from 'element-ui';
 import './styles/element/index.css';
 import common from './mixins/common';
 ElementUI.Dialog.props.closeOnClickModal.default = false;
+import SingleUpload from '@/components/SingleUpload';
 import './styles/font.less';
 import './styles/app.less';
 import eventBus from './eventBus';
@@ -18,7 +19,7 @@ Vue.prototype.$colors = {
 Vue.use(ElementUI);
 Vue.use(http);
 Vue.mixin(common);
-
+Vue.component('single-upload', SingleUpload);
 Vue.prototype.$EventBus = eventBus;
 
 Vue.config.productionTip = false;

+ 33 - 1
src/main/pc-space/src/router/index.js

@@ -13,7 +13,7 @@ import eventBus from '../eventBus';
 const routes = [
     {
         path: '/',
-        redirect: 'personal'
+        redirect: 'home'
     },
     {
         path: '/',
@@ -97,6 +97,38 @@ const routes = [
                         }
                     }
                 ]
+            },
+            {
+                path: '/security',
+                name: 'security',
+                component: () => import('../views/user/Security.vue'),
+                meta: {
+                    title: '账户与安全'
+                }
+            },
+            {
+                path: '/authentication',
+                name: 'authentication',
+                component: () => import('../views/user/Authentication.vue'),
+                meta: {
+                    title: '认证'
+                }
+            },
+            {
+                path: '/userauthentication',
+                name: 'userauthentication',
+                component: () => import('../views/user/UserAuthentication.vue'),
+                meta: {
+                    title: '个人认证'
+                }
+            },
+            {
+                path: '/enterpriseauthentication',
+                name: 'enterpriseauthentication',
+                component: () => import('../views/user/EnterpriseAuthentication.vue'),
+                meta: {
+                    title: '个人认证'
+                }
             }
         ]
     }

+ 12 - 1
src/main/pc-space/src/views/Index.vue

@@ -5,7 +5,13 @@
             <el-main class="main">
                 <router-view v-if="!loading" />
             </el-main>
-            <el-footer>
+            <el-footer
+                v-if="
+                    this.$route.name !== 'security' &&
+                    this.$route.name !== 'authentication' &&
+                    this.$route.name !== 'userauthentication'
+                "
+            >
                 <div class="footer center-content">
                     <div class="footer-l">
                         <img class="logo" src="../assets/img/nav_logo@3x.png" alt="" />
@@ -44,6 +50,7 @@
                 </div>
                 <div class="copyright">© 2012 - 2021 **** 版权所有</div>
             </el-footer>
+            <div class="bottom" v-else></div>
         </el-container>
     </el-container>
 </template>
@@ -73,6 +80,10 @@ export default {
     padding: 0;
     min-height: calc(100vh - 270px);
 }
+.bottom {
+    background: #1a1a1a;
+    height: 170px !important;
+}
 .el-footer {
     width: 100%;
     position: relative;

+ 11 - 4
src/main/pc-space/src/views/user/AccountData.vue

@@ -55,7 +55,7 @@
                     <div class="text2">登录账号</div>
                     <div class="text3">中国</div>
                 </div>
-                <div class="text4">修改</div>
+                <div class="text4" @click="Security">修改</div>
             </div>
             <div class="box">
                 <div class="text">
@@ -87,7 +87,7 @@
                     <div class="text2">实名认证</div>
                     <div class="text3">当前未实名认证</div>
                 </div>
-                <div class="text4">修改</div>
+                <div class="text4" @click="Auths">修改</div>
             </div>
         </div>
     </div>
@@ -99,7 +99,14 @@ export default {
     data() {
         return {};
     },
-    methods: {}
+    methods: {
+        Security() {
+            this.$router.push('/security');
+        },
+        Auths() {
+            this.$router.push('/authentication');
+        }
+    }
 };
 </script>
 <style lang="less" scoped>
@@ -121,7 +128,7 @@ export default {
                 display: flex;
                 .text1 {
                     font-size: 24px;
-                    color: #cccccc;
+                    color: #939599;
                 }
                 .text2 {
                     font-size: 17px;

+ 108 - 0
src/main/pc-space/src/views/user/Authentication.vue

@@ -0,0 +1,108 @@
+<template>
+    <div class="container center-content">
+        <div class="title">认证信息</div>
+        <div class="name">认证信息暂不允许修改,且无法替换认证类型,请谨慎选择</div>
+        <div class="box">
+            <div class="box1">
+                <img class="img" src="" alt="" />
+                <div class="text1">个人认证</div>
+                <div class="text2">个人通过实名认证后,绑定相对应银 行卡即可进行交易售卖</div>
+                <el-button>重新登录</el-button>
+            </div>
+            <div class="box1">
+                <img class="img" src="" alt="" />
+                <div class="text1">企业认证</div>
+                <div class="text2">企业通过营业执照认证后,并签署 相应合同即可进行售卖,冰箱周部 分定制化服务</div>
+                <el-button>重新登录</el-button>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    data() {
+        return {};
+    },
+    computed: {},
+    methods: {}
+};
+</script>
+
+<style lang="less" scoped>
+.container {
+    .btn {
+        display: flex;
+        justify-content: center;
+        margin: 80px 0 0 110px;
+        .btn2 {
+            width: 130px;
+            height: 36px;
+            background: #c4c7cc;
+            border-radius: 4px;
+            color: #ffffff;
+            font-size: 13px;
+            text-align: center;
+            line-height: 36px;
+            margin-left: 20px;
+        }
+    }
+    .title {
+        height: 42px;
+        font-size: 32px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 42px;
+        padding-top: 60px;
+    }
+    .name {
+        font-size: 12px;
+        font-weight: 400;
+        color: #939599;
+        line-height: 22px;
+        margin: 10px 0 40px;
+    }
+    .box {
+        display: flex;
+        margin-left: 178px;
+        .box1 {
+            width: 400px;
+            height: 484px;
+            background: #1c1e26;
+            border-radius: 8px;
+            margin-right: 52px;
+            text-align: center;
+            .img {
+                width: 56px;
+                height: 56px;
+                margin-top: 90px;
+            }
+            .text1 {
+                font-size: 16px;
+                font-weight: bold;
+                color: #ffffff;
+                line-height: 26px;
+                margin: 20px 0 10px;
+            }
+            .text2 {
+                width: 192px;
+                height: 66px;
+                font-size: 12px;
+                text-align: center;
+                font-weight: 400;
+                color: #939599;
+                line-height: 22px;
+                margin: 0 auto;
+            }
+            /deep/ .el-button {
+                width: 130px;
+                height: 36px;
+                background: linear-gradient(133deg, #00ffcb 0%, #006eff 100%);
+                border-radius: 4px;
+                margin-top: 60px;
+                color: #ffffff;
+            }
+        }
+    }
+}
+</style>

+ 258 - 0
src/main/pc-space/src/views/user/EnterpriseAuthentication.vue

@@ -0,0 +1,258 @@
+<template>
+    <div class="container center-content">
+        <div class="title">认证信息</div>
+        <div class="box">
+            <div class="name">企业认证 <span>账户实名认证后不能修改</span></div>
+            <div class="border"></div>
+            <el-form ref="form" :label-position="labelPosition" :model="sizeForm" :rules="registerRule">
+                <el-form-item label="法人姓名" prop="nickname">
+                    <el-input
+                        style="width: 300px"
+                        placeholder="请输入您的真实姓名"
+                        v-model="sizeForm.nickname"
+                    ></el-input>
+                </el-form-item>
+                <!-- <el-form-item label="手机号码" prop="phone">
+                    <el-input
+                        style="width: 300px"
+                        placeholder="请输入您的联系方式"
+                        :disabled="true"
+                        v-model="sizeForm.phone"
+                    ></el-input>
+                </el-form-item> -->
+
+                <el-form-item label="本人身份证 (正面图)" prop="photoFront">
+                    <single-upload class="upload" v-model="sizeForm.photoFront"></single-upload>
+                </el-form-item>
+                <div class="description">{{ explain }}</div>
+                <el-form-item label="本人身份证 (反面图)" prop="photoBackside">
+                    <single-upload class="upload" v-model="sizeForm.photoBackside"></single-upload>
+                </el-form-item>
+                <div class="description">{{ explain }}</div>
+                <el-form-item label="企业名称" prop="email">
+                    <el-input style="width: 300px" placeholder="请输入企业名称" v-model="sizeForm.email"></el-input>
+                </el-form-item>
+                <el-form-item label="工商营业执照注册号/统一社会信用代码" prop="documentNumber">
+                    <el-input
+                        style="width: 300px"
+                        placeholder="请输入18位身份证号"
+                        v-model="sizeForm.documentNumber"
+                    ></el-input>
+                </el-form-item>
+                <el-form-item label="营业执照" prop="photoBackside">
+                    <single-upload class="upload" v-model="sizeForm.photoBackside"></single-upload>
+                </el-form-item>
+                <div class="description">请上传清晰图片,格式JPG或PNG,大小不得超过 2 M</div>
+            </el-form>
+            <div class="btn">
+                <el-button type="primary" @click="onSubmit">提交审核</el-button>
+                <div class="btn1" @click="Jump">返回</div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import { mapState } from 'vuex';
+export default {
+    data() {
+        return {
+            labelPosition: 'right',
+            sizeForm: {
+                nickname: '',
+                documentNumber: '',
+                photoFront: '',
+                photoBackside: '',
+                phone: '',
+                email: '',
+                avatar: 'https://zhirongip.oss-cn-hangzhou.aliyuncs.com/image/2021-06-30-17-02-42uzAOUPcw.jpeg',
+                type: 'ID_CARD'
+            },
+            typeFl: {},
+            registerRule: {
+                documentNumber: { required: true, message: '请输入您的证件编号', trigger: 'blur' },
+                nickname: { required: true, message: '请输入您的真实姓名', trigger: 'blur' },
+                phone: { required: true, message: '请输入您的联系方式', trigger: 'blur' },
+                email: { type: 'email', required: true, message: '请输入您的邮箱', trigger: 'blur' },
+                photoFront: { required: true, message: '请添加您的身份证(正面)', trigger: 'blur' },
+                photoBackside: { required: true, message: '请添加您的身份证(反面)', trigger: 'blur' }
+            }
+        };
+    },
+    computed: {
+        ...mapState(['userInfo', 'personalInfo']),
+        explain() {
+            const list = [
+                '请上传身份证图片,格式JPG或PNG或JPEG,大小不超过1M',
+                '请上传证件照图片,格式JPG或PNG或JPEG,大小不超过1M'
+            ];
+            return list[this.typeFl == 'ID_CARD' ? 0 : 1];
+        },
+        type() {
+            return this.userInfo.authorities.find(item => {
+                return item.name == 'ROLE_INSTITUTION' || item.name == 'ROLE_PERSONAL';
+            });
+        }
+    },
+    created() {
+        this.$http
+            .get('/personal/my')
+            .then(res => {
+                this.sizeForm = {
+                    ...res,
+                    nickname: this.userInfo.nickname,
+                    phone: this.userInfo.phone,
+                    avatar: this.userInfo.avatar,
+                    email: this.userInfo.email
+                };
+            })
+            .catch(e => {
+                console.log(e);
+            });
+        this.sizeForm.nickname == this.userInfo.nickname, this.sizeForm.phone == this.userInfo.phone;
+    },
+    methods: {
+        Jump() {},
+        onSubmit() {
+            this.$refs.form.validate(valid => {
+                if (valid) {
+                    this.$confirm('提交资料需要审核,确定吗?', '提示', { type: 'warning' }).then(() => {
+                        this.preservation();
+                    });
+                }
+            });
+        },
+        preservation() {
+            let data = { ...this.sizeForm };
+            delete data.nickname;
+            delete data.phone;
+            delete data.email;
+            data.userId = this.userInfo.id;
+            this.saving = true;
+            let userInfo = {
+                ...this.userInfo,
+                nickname: this.sizeForm.nickname,
+                phone: this.sizeForm.phone,
+                avatar: this.sizeForm.avatar,
+                email: this.sizeForm.email
+            };
+            userInfo.authorities = [
+                ...userInfo.authorities,
+                {
+                    name: 'ROLE_PERSONAL'
+                }
+            ];
+
+            this.$http
+                .post('user/save', userInfo, {
+                    body: 'json'
+                })
+                .then(res => {
+                    this.sizeForm.avatar = res.avatar;
+                    this.$store.dispatch('getUserInfo');
+                    return this.$http.post('/personal/save', data, { body: 'json' }).then(res => {
+                        console.log(res);
+                        this.sizeForm = res;
+                        this.saving = false;
+                        this.$store.dispatch('getUserInfo');
+                        this.$router.push('/Authentication');
+                    });
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    this.$message.error(e.error);
+                });
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+.container {
+    /deep/ .el-form-item__label {
+        width: 294px;
+        text-align: right;
+        color: #ffffff;
+    }
+    /deep/ .el-form {
+        padding-left: 175px;
+    }
+    /deep/ .el-input__inner {
+        border: 1px solid #494a4d;
+        background: #1c1e26;
+        color: #ffffff;
+    }
+    /deep/ .el-form-item__error {
+        margin-left: 294px;
+    }
+    /deep/ .el-button {
+        width: 130px;
+        height: 36px;
+        background: linear-gradient(133deg, #00ffcb 0%, #006eff 100%);
+        border-radius: 4px;
+        margin: 0 !important;
+    }
+    .btn {
+        display: flex;
+        justify-content: center;
+        margin: 65px 0 0 58px;
+        .btn1 {
+            width: 130px;
+            height: 36px;
+            background: #c4c7cc;
+            border-radius: 4px;
+            color: #ffffff;
+            font-size: 13px;
+            text-align: center;
+            line-height: 36px;
+            margin-left: 20px;
+        }
+    }
+    .title {
+        height: 42px;
+        font-size: 32px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 42px;
+        padding: 60px 0;
+    }
+    .description {
+        font-size: 14px;
+        font-weight: 400;
+        color: #494a4d;
+        line-height: 24px;
+        margin: -11px 0 20px 294px;
+    }
+    .box {
+        height: 1277px;
+        background: #1c1e26;
+        padding: 17px 16px;
+        .border {
+            height: 1px;
+            background: #494a4d;
+            margin: 17px 0 60px;
+        }
+        .name {
+            font-size: 16px;
+            font-weight: bold;
+            color: #ffffff;
+            line-height: 26px;
+            span {
+                font-size: 12px;
+                font-weight: 400;
+                color: #939599;
+                line-height: 22px;
+            }
+        }
+        /deep/ .el-button {
+            width: 130px;
+            height: 36px;
+            background: linear-gradient(133deg, #00ffcb 0%, #006eff 100%);
+            border-radius: 4px;
+            margin-top: 60px;
+            color: #ffffff;
+        }
+    }
+}
+</style>

+ 6 - 11
src/main/pc-space/src/views/user/Fans.vue

@@ -9,26 +9,22 @@
                     <div class="box2">
                         <div class="name">
                             <div class="name1">创作者姓名</div>
-                            <div class="name2"></div>
+                            <img class="name2" src="../../assets/img/renzheng_icon@3x.png" alt="" />
                         </div>
                         <div class="text2">介绍</div>
                         <div class="box3">
                             <div class="box4">
-                                <div>
-                                    <div class="text4">粉丝 <span>233</span></div>
-                                </div>
-                                <div>
-                                    <div class="text4">已售 <span>233</span></div>
-                                </div>
+                                <div class="text4">粉丝 <span>233</span></div>
+                                <div class="text4">已售 <span>233</span></div>
                             </div>
                             <div class="btn">关注</div>
                         </div>
                     </div>
                 </div>
                 <div class="imgBox">
-                    <div class="imgBox1">111</div>
-                    <div class="imgBox1">111</div>
-                    <div class="imgBox1">111</div>
+                    <div class="imgBox1"></div>
+                    <div class="imgBox1"></div>
+                    <div class="imgBox1"></div>
                 </div>
             </div>
         </div>
@@ -81,7 +77,6 @@ export default {
                         .name2 {
                             width: 18px;
                             height: 18px;
-                            background: red;
                         }
                     }
                     .text2 {

+ 20 - 13
src/main/pc-space/src/views/user/Personal.vue

@@ -6,8 +6,7 @@
                 default-active="/accountdata"
                 router
                 class="el-menu-vertical-demo"
-                background-color="#545c64"
-                text-color="#fff"
+                text-color="#939599"
                 active-text-color="#00FFCB"
             >
                 <el-submenu index="1">
@@ -19,14 +18,18 @@
                     <el-menu-item index="1-2">地址管理</el-menu-item>
                     <el-menu-item index="1-3">我赞过的</el-menu-item>
                 </el-submenu>
-                <el-menu-item index="2">
-                    <i class="el-icon-menu"></i>
-                    <span slot="title">交易信息</span>
-                </el-menu-item>
-                <el-menu-item index="3">
-                    <i class="el-icon-setting"></i>
-                    <span slot="title">铸造信息</span>
-                </el-menu-item>
+                <el-submenu index="2">
+                    <template slot="title">
+                        <i class="el-icon-menu"></i>
+                        <span>交易信息</span>
+                    </template>
+                </el-submenu>
+                <el-submenu index="3">
+                    <template slot="title">
+                        <i class="el-icon-menu"></i>
+                        <span>铸造信息</span>
+                    </template>
+                </el-submenu>
             </el-menu>
             <div class="main">
                 <router-view />
@@ -51,18 +54,22 @@ export default {
 </script>
 <style lang="less" scoped>
 .container {
+    padding-bottom: 200px;
     /deep/ .el-menu {
         width: 200px;
         background: #1c1e26 !important;
         margin-right: 30px;
         .el-submenu__title {
             background: #1c1e26 !important;
+            color: #ffffff !important;
+            font-size: 18px !important;
+            padding-left: 10px !important;
         }
         .el-menu-item {
             background: #1c1e26 !important;
-
-            &.is-active {
-                color: red;
+            span {
+                color: #ffffff !important;
+                font-size: 18px !important;
             }
         }
     }

+ 232 - 0
src/main/pc-space/src/views/user/Security.vue

@@ -0,0 +1,232 @@
+<template>
+    <div class="container center-content">
+        <div class="title">变更手机号</div>
+        <div class="box">
+            <div class="name">
+                <div class="name1">修改登录账户</div>
+                <div class="name2">修改手机号即同时修改登录账户名称</div>
+            </div>
+            <div class="border"></div>
+            <div class="content" v-if="flag">
+                <el-steps :space="180" :active="1" align-center>
+                    <el-step title="验证当前手机号"></el-step>
+                    <el-step title="绑定新手机号"></el-step>
+                    <el-step title="完成"></el-step>
+                </el-steps>
+                <el-form
+                    :label-position="labelPosition"
+                    ref="form"
+                    label-width="340px"
+                    :model="ruleForm"
+                    :rules="rules"
+                >
+                    <el-form-item label="当前手机号" prop="phone">
+                        <div class="phone">156****8686</div>
+                    </el-form-item>
+                    <el-form-item label="验证码" prop="code">
+                        <el-input style="width: 300px" v-model="ruleForm.code" placeholder="请输入4位验证码">
+                            <span
+                                @click="send"
+                                style="color: #00ffcb; cursor: pointer; font-size: 13px"
+                                slot="suffix"
+                                >{{ time === 0 ? '发送验证码' : `重新发送${time}s` }}</span
+                            >
+                        </el-input>
+                    </el-form-item>
+                </el-form>
+                <div class="btn">
+                    <el-button type="primary" @click="codeSend">确认</el-button>
+                    <div class="btn2" @click="Jump2">返回</div>
+                </div>
+            </div>
+            <div v-else>
+                <security-phone @Jump="Jump"></security-phone>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import SecurityPhone from '../../components/SecurityPhone.vue';
+import { mapState } from 'vuex';
+export default {
+    components: { SecurityPhone },
+    data() {
+        return {
+            flag: true,
+            labelPosition: 'right',
+            ruleForm: {
+                phone: '',
+                code: '',
+                pass: '',
+                password: '',
+                checkPass: '',
+                type: ''
+            },
+            time: 0,
+            rules: {
+                checkPass: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (value !== this.ruleForm.pass) {
+                                callback(new Error('两次密码输入不一致'));
+                            } else {
+                                callback();
+                            }
+                        },
+                        trigger: 'blur'
+                    },
+                    { required: true, message: '请再次输入密码', trigger: 'blur' }
+                ]
+            }
+        };
+    },
+    computed: {
+        ...mapState(['userInfo'])
+        // Phone() {
+        //     return this.userInfo.phone.slice(0, 3) + ' **** ' + this.userInfo.phone.slice(7, 11);
+        // }
+    },
+    // created() {
+    //     this.ruleForm.phone = this.userInfo.phone;
+    // },
+    methods: {
+        send() {
+            this.sendMsg(this.ruleForm.phone);
+        },
+        codeSend() {
+            this.flag = false;
+            // this.$http
+            //     .get('/sms/verify', {
+            //         phone: this.ruleForm.phone,
+            //         code: this.ruleForm.code
+            //     })
+            //     .then(() => {
+            //         this.ruleForm.code = '';
+            //         this.ruleForm.phone = '';
+            //         this.flag = false;
+            //     })
+            //     .catch(e => {
+            //         this.$message.error(e.error);
+            //     });
+        },
+        Jump() {
+            this.flag = true;
+            this.ruleForm.phone = this.userInfo.phone;
+        },
+        Jump2() {
+            this.$router.push('/accountdata');
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+/deep/ .el-steps {
+    margin-left: 385px;
+}
+/deep/.el-step:nth-child(1) {
+    .el-step__icon {
+        background: linear-gradient(143deg, #00ffcb 0%, #006eff 100%, #006eff 100%);
+        color: #ffffff;
+        border: 0;
+    }
+}
+/deep/.el-step:nth-child(2) {
+    .el-step__icon {
+        background: #c8c9cc;
+        color: #ffffff;
+        border: 0;
+    }
+}
+/deep/.el-step:nth-child(3) {
+    .el-step__icon {
+        background: #c8c9cc;
+        color: #ffffff;
+        border: 0;
+    }
+}
+/deep/ .el-step__title.is-process {
+    font-weight: 400;
+    color: #939599;
+}
+/deep/ .el-step__title.is-wait {
+    color: #939599;
+}
+.container {
+    .btn {
+        display: flex;
+        justify-content: center;
+        margin: 80px 0 0 110px;
+        .btn2 {
+            width: 130px;
+            height: 36px;
+            background: #c4c7cc;
+            border-radius: 4px;
+            cursor: pointer;
+            color: #ffffff;
+            font-size: 13px;
+            text-align: center;
+            line-height: 36px;
+            margin-left: 20px;
+        }
+    }
+    /deep/ .el-button {
+        width: 130px;
+        height: 36px;
+        background: linear-gradient(133deg, #00ffcb 0%, #006eff 100%);
+        border-radius: 4px;
+    }
+    /deep/ .el-step__title {
+        font-size: 13px;
+    }
+    /deep/ .el-form-item__label {
+        color: #ffffff;
+        margin-left: 175px;
+    }
+    /deep/ .el-form {
+        margin-top: 66px;
+    }
+    /deep/ .el-input__inner {
+        border: 1px solid #494a4d;
+        background: #1c1e26;
+    }
+    .title {
+        height: 42px;
+        font-size: 32px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 42px;
+        padding: 60px 0;
+    }
+    .box {
+        height: 539px;
+        background: #1c1e26;
+    }
+    .name {
+        .flex();
+        padding: 17px 16px;
+        .name1 {
+            font-size: 16px;
+            font-weight: bold;
+            color: #ffffff;
+            line-height: 26px;
+        }
+        .name2 {
+            font-size: 12px;
+            font-weight: 400;
+            color: #939599;
+            margin-left: 10px;
+        }
+    }
+    .phone {
+        color: #ffffff;
+        font-size: 18px;
+    }
+    .border {
+        height: 1px;
+        background: #494a4d;
+        margin: 0 16px 40px;
+    }
+}
+</style>

+ 253 - 0
src/main/pc-space/src/views/user/UserAuthentication.vue

@@ -0,0 +1,253 @@
+<template>
+    <div class="container center-content">
+        <div class="title">认证信息</div>
+        <div class="box">
+            <div class="name">个人认证 <span>账户实名认证后不能修改</span></div>
+            <div class="border"></div>
+            <el-form ref="form" :label-position="labelPosition" :model="sizeForm" :rules="registerRule">
+                <el-form-item label="姓名" prop="nickname">
+                    <el-input
+                        style="width: 300px"
+                        placeholder="请输入您的真实姓名"
+                        v-model="sizeForm.nickname"
+                    ></el-input>
+                </el-form-item>
+                <el-form-item label="手机号码" prop="phone">
+                    <el-input
+                        style="width: 300px"
+                        placeholder="请输入您的联系方式"
+                        :disabled="true"
+                        v-model="sizeForm.phone"
+                    ></el-input>
+                </el-form-item>
+                <el-form-item label="电子邮箱" prop="email">
+                    <el-input style="width: 300px" placeholder="请输入邮箱" v-model="sizeForm.email"></el-input>
+                </el-form-item>
+                <el-form-item label="身份证号" prop="documentNumber">
+                    <el-input
+                        style="width: 300px"
+                        placeholder="请输入18位身份证号"
+                        v-model="sizeForm.documentNumber"
+                    ></el-input>
+                </el-form-item>
+                <el-form-item label="本人身份证 (正面图)" prop="photoFront">
+                    <single-upload class="upload" v-model="sizeForm.photoFront"></single-upload>
+                </el-form-item>
+                <div class="description">{{ explain }}</div>
+                <el-form-item label="本人身份证 (反面图)" prop="photoBackside">
+                    <single-upload class="upload" v-model="sizeForm.photoBackside"></single-upload>
+                </el-form-item>
+                <div class="description">{{ explain }}</div>
+            </el-form>
+            <div class="btn">
+                <el-button type="primary" @click="onSubmit">提交审核</el-button>
+                <div class="btn1" @click="Jump">返回</div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import { mapState } from 'vuex';
+export default {
+    data() {
+        return {
+            labelPosition: 'right',
+            sizeForm: {
+                nickname: '',
+                documentNumber: '',
+                photoFront: '',
+                photoBackside: '',
+                phone: '',
+                email: '',
+                avatar: 'https://zhirongip.oss-cn-hangzhou.aliyuncs.com/image/2021-06-30-17-02-42uzAOUPcw.jpeg',
+                type: 'ID_CARD'
+            },
+            typeFl: {},
+            registerRule: {
+                documentNumber: { required: true, message: '请输入您的身份证号', trigger: 'blur' },
+                nickname: { required: true, message: '请输入您的真实姓名', trigger: 'blur' },
+                phone: { required: true, message: '请输入您的联系方式', trigger: 'blur' },
+                email: { type: 'email', required: true, message: '请输入您的邮箱', trigger: 'blur' },
+                photoFront: { required: true, message: '请添加您的身份证(正面)', trigger: 'blur' },
+                photoBackside: { required: true, message: '请添加您的身份证(反面)', trigger: 'blur' }
+            }
+        };
+    },
+    computed: {
+        ...mapState(['userInfo', 'personalInfo']),
+        explain() {
+            const list = [
+                '请上传身份证图片,格式JPG或PNG或JPEG,大小不超过1M',
+                '请上传证件照图片,格式JPG或PNG或JPEG,大小不超过1M'
+            ];
+            return list[this.typeFl == 'ID_CARD' ? 0 : 1];
+        },
+        type() {
+            return this.userInfo.authorities.find(item => {
+                return item.name == 'ROLE_INSTITUTION' || item.name == 'ROLE_PERSONAL';
+            });
+        }
+    },
+    created() {
+        this.$http
+            .get('/personal/my')
+            .then(res => {
+                this.sizeForm = {
+                    ...res,
+                    nickname: this.userInfo.nickname,
+                    phone: this.userInfo.phone,
+                    avatar: this.userInfo.avatar,
+                    email: this.userInfo.email
+                };
+            })
+            .catch(e => {
+                console.log(e);
+            });
+        this.sizeForm.nickname == this.userInfo.nickname, this.sizeForm.phone == this.userInfo.phone;
+    },
+    methods: {
+        Jump() {},
+        onSubmit() {
+            this.$refs.form.validate(valid => {
+                if (valid) {
+                    this.$confirm('提交资料需要审核,确定吗?', '提示', { type: 'warning' }).then(() => {
+                        this.preservation();
+                    });
+                }
+            });
+        },
+        preservation() {
+            let data = { ...this.sizeForm };
+            delete data.nickname;
+            delete data.phone;
+            delete data.email;
+            data.userId = this.userInfo.id;
+            this.saving = true;
+            let userInfo = {
+                ...this.userInfo,
+                nickname: this.sizeForm.nickname,
+                phone: this.sizeForm.phone,
+                avatar: this.sizeForm.avatar,
+                email: this.sizeForm.email
+            };
+            userInfo.authorities = [
+                ...userInfo.authorities,
+                {
+                    name: 'ROLE_PERSONAL'
+                }
+            ];
+
+            this.$http
+                .post('user/save', userInfo, {
+                    body: 'json'
+                })
+                .then(res => {
+                    this.sizeForm.avatar = res.avatar;
+                    this.$store.dispatch('getUserInfo');
+                    return this.$http.post('/personal/save', data, { body: 'json' }).then(res => {
+                        console.log(res);
+                        this.sizeForm = res;
+                        this.saving = false;
+                        this.$store.dispatch('getUserInfo');
+                        this.$router.push('/Authentication');
+                    });
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    this.$message.error(e.error);
+                });
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+.container {
+    /deep/ .el-form-item__label {
+        width: 94px;
+        text-align: right;
+        color: #ffffff;
+    }
+    /deep/ .el-form {
+        padding-left: 390px;
+    }
+    /deep/ .el-input__inner {
+        border: 1px solid #494a4d;
+        background: #1c1e26;
+        color: #ffffff;
+    }
+    /deep/ .el-form-item__error {
+        margin-left: 94px;
+    }
+    /deep/ .el-button {
+        width: 130px;
+        height: 36px;
+        background: linear-gradient(133deg, #00ffcb 0%, #006eff 100%);
+        border-radius: 4px;
+        margin: 0 !important;
+    }
+    .btn {
+        display: flex;
+        justify-content: center;
+        margin: 65px 0 0 78px;
+        .btn1 {
+            width: 130px;
+            height: 36px;
+            background: #c4c7cc;
+            border-radius: 4px;
+            color: #ffffff;
+            font-size: 13px;
+            text-align: center;
+            line-height: 36px;
+            margin-left: 20px;
+        }
+    }
+    .title {
+        height: 42px;
+        font-size: 32px;
+        font-weight: 400;
+        color: #ffffff;
+        line-height: 42px;
+        padding: 60px 0;
+    }
+    .description {
+        font-size: 14px;
+        font-weight: 400;
+        color: #494a4d;
+        line-height: 24px;
+        margin: -11px 0 20px 94px;
+    }
+    .box {
+        height: 1000px;
+        background: #1c1e26;
+        padding: 17px 16px;
+        .border {
+            height: 1px;
+            background: #494a4d;
+            margin: 17px 0 60px;
+        }
+        .name {
+            font-size: 16px;
+            font-weight: bold;
+            color: #ffffff;
+            line-height: 26px;
+            span {
+                font-size: 12px;
+                font-weight: 400;
+                color: #939599;
+                line-height: 22px;
+            }
+        }
+        /deep/ .el-button {
+            width: 130px;
+            height: 36px;
+            background: linear-gradient(133deg, #00ffcb 0%, #006eff 100%);
+            border-radius: 4px;
+            margin-top: 60px;
+            color: #ffffff;
+        }
+    }
+}
+</style>