Browse Source

绑定数据

tanyanfei 2 months ago
parent
commit
b39b6a5627
11 changed files with 18972 additions and 207 deletions
  1. 81 2
      css/index.css
  2. 2 1
      css/login.css
  3. 206 29
      detail.html
  4. BIN
      img/menu.png
  5. 159 74
      index.html
  6. 2 0
      js/axios.min.js
  7. 1 0
      js/public.js
  8. 18096 0
      js/vue.js
  9. 166 53
      list.html
  10. 143 14
      login.html
  11. 116 34
      record.html

+ 81 - 2
css/index.css

@@ -19,9 +19,10 @@ header{
     box-shadow: 0px 0px 4px 0 rgba(0,0,0,.5);
 }
 .logo{
-    width: 50px;
-    height: 50px;
+    width: 40px;
+    height: 40px;
     border-radius: 5px;
+    margin-top: 5px;
 }
 header a{
     color: #000;
@@ -55,6 +56,39 @@ header a{
     position: relative;
     top: 10px;
 }
+.login a{
+    padding: 0 10px;
+}
+.menu{
+    display: inline-block;
+    position: relative;
+    padding: 0 10px;
+    width: 100px;
+    cursor: pointer;
+}
+.menu:hover ul{
+    visibility: visible;
+    transition: .3s;
+}
+.menu ul{
+    background-color: #fff;
+    border-radius: 4px;
+    color: #333;
+    font-size: 13px;
+    line-height: 28px;
+    padding: 5px;
+    position: absolute;
+    width: 130px;
+    right: 5px;
+    visibility: hidden;
+}
+.menu ul li:hover{
+    background-color: #f5f5f5;
+    cursor: pointer;
+}
+.phone{
+    display: none;
+}
 .content{
     width: 1200px;
     max-width: 100%;
@@ -166,6 +200,15 @@ header a{
     color: #999;
     font-size: 13px;
 }
+.comment textarea{
+    width: 100%;
+    height: 100px;
+    border: 1px solid #ccc;
+    border-radius: 3px;
+    padding: 10px;
+    margin-bottom: 15px;
+    outline: none;
+}
 .form{
     text-align: center;
 }
@@ -180,6 +223,7 @@ header a{
 }
 .form textarea{
     height: 200px;
+    padding: 10px;
 }
 .form button{
     width: 150px;
@@ -232,6 +276,26 @@ footer{
     height: 200px;
     background-color: #000;
 }
+.slide{
+    background-color: #fff;
+    width: 150px;
+    position: absolute;
+    top: 60px;
+    left: 0;
+}
+.slide a{
+    display: block;
+    color: #333;
+    line-height: 30px;
+    border-bottom: 1px solid #f5f5f5;
+    padding: 10px 20px;
+}
+.slide-enter-from,.slide-leave-to{
+    transform: translateX(-100%);
+}
+.slide-enter-active,.slide-leave-active{
+    transition: .5s;
+}
 @media screen and (max-width: 768px){
     .content{
         padding: 0 15px;
@@ -243,4 +307,19 @@ footer{
     .nav{
         display: none;
     }
+    .phone{
+        display: inline-block;
+    }
+    .pc{
+        display: none;
+    }
+    .logo{
+        width: 30px;
+        height: 30px;
+        margin-left: 5px;
+        margin-top: 0;
+    }
+    .left_nav{
+        padding-top: 10px;
+    }
 } 

+ 2 - 1
css/login.css

@@ -3,11 +3,12 @@
     background-color: #fff;
     margin: 15px 0;
 }
-.addvx{
+.content .addvx{
     text-align: center;
     padding: 50px 0;
     line-height: 25px;
     font-size: 14px;
+    margin-right: 20px;
 }
 .addvx b{
     color: #0760C7;

+ 206 - 29
detail.html

@@ -5,6 +5,8 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>详情</title>
     <link rel="stylesheet" href="css/index.css">
+    <script src="js/axios.min.js"></script>
+    <script src="js/vue.js"></script>
 </head>
 <style>
     .search_left{
@@ -31,7 +33,7 @@
     }
     .tag{
         margin-top: 10px;
-        padding-left: 20px;
+        /* padding-left: 20px; */
     }
     .tag span{
         background-color: #000;
@@ -52,6 +54,11 @@
         padding: 40px 20px;
         border: 1px solid #ccc;
     }
+    .answer{
+        padding: 20px;
+        line-height: 26px;
+        text-align: left;
+    }
     .detail_right button{
         width: 150px;
         height: 40px;
@@ -81,70 +88,240 @@
     }
 </style>
 <body>
+<section id="app">
     <header>
-        <img class="logo" src="img/logo.jpg" alt="logo">
+        <div class="left_nav">
+            <img @click="show=!show" class="phone" width="30" src="img/menu.png" alt="">
+            <img class="logo" src="img/logo.jpg" alt="logo">
+        </div>
         <div class="nav">
-            <a class="act" href="">猿人学面试</a>
+            <a class="act" href="/index.html">猿人学面试</a>
             <a href="">爬虫比赛</a>
             <a href="">关于猿人学</a>
         </div>
         <div class="login">
-            <img width="30px" src="img/logo.jpg" alt="logo">
-            <a href="#">请先登录</a>
+            <div class="pc">
+                <img width="30px" src="img/logo.jpg" alt="logo">
+                <div v-if="userInfo" class="menu">
+                    {{userInfo.name}}
+                    <ul>
+                        <li><a href="/record.html">我的刷题记录</a></li>
+                        <li @click="logout"><a>退出登录</a></li>
+                    </ul>
+                </div>
+                <a v-else href="/login.html">请先登录</a>
+            </div>
+            <div class="phone">
+                <span v-if="userInfo">{{userInfo.name}}</span>
+                <a v-else href="/login.html">请先登录</a>
+            </div>
         </div>
     </header>
+    <transition name="slide">
+        <div class="slide" v-if="show">
+            <a class="act" href="/index.html">猿人学面试</a>
+            <a href="">爬虫比赛</a>
+            <a href="">关于猿人学</a>
+            <a v-if="userInfo" href="/record.html">我的刷题记录</a>
+            <a v-if="userInfo" @click="logout">退出登录</a>
+        </div>
+    </transition>
     <div class="content">
-        <p class="navtation"><a href="">回到首页</a> - <a href="">爬虫面试题</a> - 用哪些库用于数据库解析</p>
+        <p class="navtation"><a href="/index.html">回到首页</a> - <a href="/list.html">
+            <span v-if="detail.category=='crawler'">爬虫</span>  
+                <span v-else-if="detail.category=='js'">JS</span>
+                <span v-else>安卓</span>面试题</a> - {{detail.name}}</p>
         <div class="left search_left">
             <div class="part">
                 <p class="search">
-                    <input  type="text" placeholder="题目搜索">
+                    <input type="text" v-model="searchKeyword" @input="search" placeholder="题目搜索">
                 </p>
                 <ul class="list">
-                    <li><a href="">讲讲对script的理解</a></li>
-                    <li><a href="">讲讲对script的理解</a></li>
-                    <li><a href="">讲讲对script的理解</a></li>
-                    <li><a href="">讲讲对script的理解</a></li>
-                    <li><a href="">讲讲对script的理解</a></li>
-                    <li><a href="">讲讲对script的理解</a></li>
+                    <li v-for="item in list" :key="item.interviewId"><a :href="'/detail.html?id='+item.interviewId">{{item.name}}</a></li>
                 </ul>
             </div>
             <div class="part">
                 <h2 class="sec_title"><span>贡献面试题</span></h2>
-                <form class="form" action="">
-                    <input type="text" placeholder="面试题目">
-                    <textarea></textarea>
-                    <button>提交</button>
+                <form class="form">
+                    <input v-model="name" type="text" placeholder="面试题目">
+                    <textarea v-model="content"></textarea>
+                    <button type="button" @click="post">提交</button>
                 </form>
             </div>
         </div>
         <div class="right detail_right">
             <div class="part">
-                <b>51.用哪些库用于数据解析</b>
+                <b>{{detail.name}}</b>
                 <p class="tag">
-                    <span>tag</span><span>tag</span><span>tag</span>
+                    <span>{{detail.category}}</span>
                     <a href="">分享给朋友</a>
                 </p>
             </div>
             <div class="part">
                 <h2 class="sec_title"><span>答题讨论</span></h2>
-                <div class="discuss">
-                    <button>请登录</button>
+                <div class="discuss answer" v-if="userInfo">
+                    {{detail.content}}
+                </div>
+                <div class="discuss" v-else>
+                    <button @click="login">请登录</button>
                 </div>
             </div>
             <div class="part">
                 <h2 class="sec_title"><span>网友热议</span></h2>
-                <p class="user">
-                    蛋黄酱  2025.11.1
-                </p>
-                <p class="ans">
-                    vfbjosehuaoehvuhqaauihuoihcfuahqcuidhui
-                </p>
-                <div class="login_div">
-                    <button>登录后查看全部</button>
+                <template v-for="(item,index) in comment">
+                    <template v-if="index == 0">
+                        <p class="user">
+                            {{item.cname}}  {{item.ctime}}
+                        </p>
+                        <p class="ans">
+                            {{item.content}}
+                        </p>
+                    </template>
+                    <template v-else-if="index > 0 && userInfo">
+                        <p class="user">
+                            {{item.cname}}  {{item.ctime}}
+                        </p>
+                        <p class="ans">
+                            {{item.content}}
+                        </p>
+                    </template>
+                </template>
+                <div class="login_div" v-if="!userInfo">
+                    <button @click="login">登录后查看全部</button>
+                </div>
+                <div class="comment" v-if="userInfo">
+                    <textarea v-model="form.content" placeholder="留下你的想法..."></textarea>
+                    <button style="width: 100px;" @click="sendComment">提交评论</button>
                 </div>
             </div>
         </div>
     </div>
+</section>
+<script src="js/public.js"></script>
+<script>
+    const { createApp } = Vue;
+    createApp({
+        data() {
+            return {
+                name: '',
+                content: '',
+                userInfo: {},
+                id: '',
+                detail: {},
+                comment: [],
+                form: {
+                    content: '',
+                    interviewName: '',
+                    interviewId: ''
+                },
+                searchKeyword: '', // 添加 searchKeyword 变量
+                list: [], // 添加 list 变量用于存储题目列表
+                show: 0 // 添加 show 变量
+            }
+        },
+        created() {
+            this.id = new URLSearchParams(window.location.search).get('id') || '';
+            // 获取本地存储的用户ID并赋值给cid
+            const userInfo = JSON.parse(localStorage.getItem('userInfo'));
+            this.userInfo = userInfo;
+            this.getData();
+            this.getComment();
+        },
+        methods: {
+            login() {
+                window.location.href = '/login.html';
+            },
+            getData() {
+                // 列表
+                axios.get(url + '/api/yrx/que/info?interviewId=' + this.id).then(res => {
+                    if (res.data.code === 0) {
+                        this.detail = res.data.data;
+                        this.form.interviewId = this.detail.interviewId;
+                        this.form.interviewName = this.detail.name;
+                    }
+                });
+                // 获取题目列表
+                axios.get(url + '/api/yrx/que/list').then(res => {
+                    if (res.data.code === 0) {
+                        this.list = res.data.data.list;
+                    }
+                });
+            },
+            getComment() {
+                axios.get(url + '/api/yrx/que/comments/list?interviewId=' + this.id).then(res => {
+                    if (res.data.code === 0) {
+                        this.comment = res.data.data.list;
+                    }
+                });
+            },
+            sendComment() {
+                if (!this.form.content) {
+                    alert('评论内容不能为空');
+                    return;
+                }
+                const token = localStorage.getItem('token'); // 获取token
+                axios.post(url + '/api/yrx/que/comments', this.form, {
+                    headers: {
+                        'Authorization': `${token}` // 添加token到header
+                    }
+                })
+                .then(res => {
+                    if (res.data.code === 0) {
+                        alert('评论成功');
+                        this.form.content = '';
+                        this.getComment();
+                    }
+                })
+                .catch(err => {
+                    alert('评论失败,请重试');
+                    console.error(err);
+                });
+            },
+            post() { // 添加post方法
+                if (!this.name || !this.content) {
+                    alert('面试题目和内容不能为空');
+                    return;
+                }
+                const token = localStorage.getItem('token'); // 获取token
+                axios.post(url + '/api/yrx/que/user/post', { name: this.name, content: this.content }, {
+                    headers: {
+                        'Authorization': `${token}` // 添加token到header
+                    }
+                })
+                .then(res => {
+                    if (res.data.code === 0) {
+                        alert('提交成功');
+                        this.name = '';
+                        this.content = '';
+                    }
+                })
+                .catch(err => {
+                    alert('提交失败,请重试');
+                    console.error(err);
+                });
+            },
+            search() { // 添加 search 方法
+                axios.get(url + '/api/yrx/que/list', {
+                    params: {
+                        name: this.searchKeyword,
+                        category:this.detail.category,
+                        page:1,
+                        page_size:1000
+                    }
+                })
+                .then(res => {
+                    if (res.data.code === 0) {
+                        this.list = res.data.data.list;
+                    }
+                })
+            },
+            logout() { // 添加 logout 方法
+                localStorage.removeItem('userInfo');
+                localStorage.removeItem('token');
+                this.userInfo = null;
+            }
+        }
+    }).mount('#app');
+</script>
 </body>
 </html>

BIN
img/menu.png


+ 159 - 74
index.html

@@ -5,87 +5,172 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>猿人学面试</title>
     <link rel="stylesheet" href="css/index.css">
+    <script src="js/axios.min.js"></script>
+    <script src="js/vue.js"></script>
 </head>
 <body>
-    <header>
-        <img class="logo" src="img/logo.jpg" alt="logo">
-        <div class="nav">
-            <a class="act" href="">猿人学面试</a>
-            <a href="">爬虫比赛</a>
-            <a href="">关于猿人学</a>
-        </div>
-        <div class="login">
-            <img width="30px" src="img/logo.jpg" alt="logo">
-            <a href="#">请先登录</a>
-        </div>
-    </header>
-
-    <div class="content">
-        <div class="left">
-            <div class="banner">广告</div>
-        </div>
-        <div class="right">
-            <div class="banner">广告</div>
-        </div>
-        <div class="left">
-            <div class="part">
-                <h1 class="title"><span>JS逆向面试题</span></h1>
-                <ul class="list">
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                </ul>
-                <a href="" class="more">更多JS逆向面试题</a>
+    <section id="app">
+        <header>
+            <div class="left_nav">
+                <img @click="show=!show" class="phone" width="30" src="img/menu.png" alt="">
+                <img class="logo" src="img/logo.jpg" alt="logo">
             </div>
-            <div class="part">
-                <h1 class="title"><span>安卓逆向面试题</span></h1>
-                <ul class="list">
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                </ul>
-                <a href="" class="more">更多安卓逆向面试题</a>
+            <div class="nav">
+                <a class="act" href="/index.html">猿人学面试</a>
+                <a href="">爬虫比赛</a>
+                <a href="">关于猿人学</a>
             </div>
-            <div class="part">
-                <h1 class="title"><span>爬虫面试题</span></h1>
-                <ul class="list">
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                </ul>
-                <a href="" class="more">更多爬虫面试题</a>
+            <div class="login">
+                <div class="pc">
+                    <img width="30px" src="img/logo.jpg" alt="logo">
+                    <div v-if="userInfo" class="menu">
+                        {{userInfo.name}}
+                        <ul>
+                            <li><a href="/record.html">我的刷题记录</a></li>
+                            <li @click="logout"><a>退出登录</a></li>
+                        </ul>
+                    </div>
+                    <a v-else href="/login.html">请先登录</a>
+                </div>
+                <div class="phone">
+                    <span v-if="userInfo">{{userInfo.name}}</span>
+                    <a v-else href="/login.html">请先登录</a>
+                </div>
             </div>
-        </div>
-        <div class="right">
-            <div class="part">
-                <h2 class="sec_title"><span>面试排行榜</span>  <a href="">更多</a></h2>
-                <ul class="list list_100">
-                    <li><a href="">蛋黄酱</a><span>555</span></li>
-                    <li><a href="">蛋黄酱</a><span>555</span></li>
-                    <li><a href="">蛋黄酱</a><span>555</span></li>
-                    <li><a href="">蛋黄酱</a><span>555</span></li>
-                </ul>
+        </header>
+        <transition name="slide">
+            <div class="slide" v-if="show">
+                <a class="act" href="/index.html">猿人学面试</a>
+                <a href="">爬虫比赛</a>
+                <a href="">关于猿人学</a>
+                <a v-if="userInfo" href="/record.html">我的刷题记录</a>
+                <a v-if="userInfo" @click="logout">退出登录</a>
+            </div>
+        </transition>
+        <div class="content">
+            <div class="left">
+                <div class="banner">
+                    <img width="100%" height="100%" :src="img[0]" alt="">
+                </div>
+            </div>
+            <div class="right">
+                <div class="banner">
+                    <img width="100%" height="100%" :src="img[1]" alt="">
+                </div>
+            </div>
+            <div class="left" v-if="list.length>0">
+                <div class="part">
+                    <h1 class="title"><span>JS逆向面试题</span></h1>
+                    <ul class="list">
+                        <li v-for="item in list[0].list">
+                            <a :href="'/detail.html?id='+item.interviewId">{{item.name}}</a>
+                        </li>
+                    </ul>
+                    <a href="/list.html?cat=js" class="more">更多JS逆向面试题</a>
+                </div>
+                <div class="part">
+                    <h1 class="title"><span>安卓逆向面试题</span></h1>
+                    <ul class="list">
+                        <li v-for="item in list[1].list">
+                            <a :href="'/detail.html?id='+item.interviewId">{{item.name}}</a>
+                        </li>
+                    </ul>
+                    <a href="/list.html?cat=android" class="more">更多安卓逆向面试题</a>
+                </div>
+                <div class="part">
+                    <h1 class="title"><span>爬虫面试题</span></h1>
+                    <ul class="list">
+                        <li v-for="item in list[2].list">
+                            <a :href="'/detail.html?id='+item.interviewId">{{item.name}}</a>
+                        </li>
+                    </ul>
+                    <a href="/list.html?cat=crawler" class="more">更多爬虫面试题</a>
+                </div>
             </div>
-            <div class="part">
-                <h2 class="sec_title"><span>贡献面试题</span></h2>
-                <form class="form" action="">
-                    <input type="text" placeholder="面试题目">
-                    <textarea></textarea>
-                    <button>提交</button>
-                </form>
+            <div class="right">
+                <div class="part">
+                    <h2 class="sec_title"><span>面试排行榜</span>  <a href="">更多</a></h2>
+                    <ul class="list list_100">
+                        <li v-for="item in top"><a href="">{{item.cname}}</a><span>{{item.count}}</span></li>
+                    </ul>
+                </div>
+                <div class="part">
+                    <h2 class="sec_title"><span>贡献面试题</span></h2>
+                    <form class="form">
+                        <input v-model="name" type="text" placeholder="面试题目">
+                        <textarea v-model="content"></textarea>
+                        <button type="button" @click="post">提交</button>
+                    </form>
+                </div>
             </div>
         </div>
-    </div>
-
-    <footer></footer>
+        <footer></footer>
+    </section>
+    <script src="js/public.js"></script>
+    <script>
+        const { createApp } = Vue;
+        createApp({
+            data() {
+                return {
+                    show:0,
+                    list:[],
+                    img:[],
+                    top:[],
+                    name:'',
+                    content:'',
+                    userInfo:{}
+                }
+            },
+            created(){
+                const userInfo = JSON.parse(localStorage.getItem('userInfo'));
+                this.userInfo = userInfo;
+                this.getData();
+            },
+            methods:{
+                logout(){
+                    localStorage.removeItem('userInfo');
+                    localStorage.removeItem('token');
+                    this.userInfo = null;
+                },
+                getData(){
+                    axios.get(url+'/api/yrx/que/top').then(res=>{
+                        this.list = res.data.data;
+                    })
+                    axios.get(url+'/api/yrx/banner/list?position=index_left').then(res=>{
+                        this.img[0] = res.data.data[0].jumpUrl;
+                    })
+                    axios.get(url+'/api/yrx/banner/list?position=index_right').then(res=>{
+                        this.img[1] = res.data.data[0].jumpUrl;
+                    })
+                    axios.get(url+'/api/yrx/que/user/top').then(res=>{
+                        this.top = res.data.data;
+                    })
+                },
+                post(){
+                    if (!this.name || !this.content) {
+                        alert('面试题目和内容不能为空');
+                        return;
+                    }
+                    const token = localStorage.getItem('token'); // 获取token
+                    axios.post(url+'/api/yrx/que/user/post', { name: this.name, content: this.content }, {
+                        headers: {
+                            'Authorization': `${token}` // 添加token到header
+                        }
+                    })
+                    .then(res => {
+                        if(res.data.code === 0){
+                            alert('提交成功');
+                            this.name = '';
+                            this.content = '';
+                        }
+                    })
+                    .catch(err => {
+                        alert('提交失败,请重试');
+                        console.error(err);
+                    });
+                }
+            }
+        }).mount('#app');
+    </script>
 </body>
 </html>

File diff suppressed because it is too large
+ 2 - 0
js/axios.min.js


+ 1 - 0
js/public.js

@@ -0,0 +1 @@
+const url='http://118.190.145.217:8080';

File diff suppressed because it is too large
+ 18096 - 0
js/vue.js


+ 166 - 53
list.html

@@ -5,6 +5,8 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>面试题</title>
     <link rel="stylesheet" href="css/index.css">
+    <script src="js/axios.min.js"></script>
+    <script src="js/vue.js"></script>
 </head>
 <style>
     .list li{
@@ -13,62 +15,173 @@
     
 </style>
 <body>
-    <header>
-        <img class="logo" src="img/logo.jpg" alt="logo">
-        <div class="nav">
-            <a class="act" href="">猿人学面试</a>
-            <a href="">爬虫比赛</a>
-            <a href="">关于猿人学</a>
-        </div>
-        <div class="login">
-            <img width="30px" src="img/logo.jpg" alt="logo">
-            <a href="#">请先登录</a>
-        </div>
-    </header>
-    <div class="content">
-        <div class="left">
-            <div class="banner">广告</div>
-        </div>
-        <div class="right">
-            <div class="banner">广告</div>
-        </div>
-        <p class="navtation"><a href="">回到首页</a> - 爬虫面试题</p>
-        <div class="left">
-            <div class="part">
-                <ul class="list">
-                    <li><a href="">1.瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">2.瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">3.瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">4.瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">5.瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                    <li><a href="">6.瑞树的整个逆向流程瑞树的整个逆向流程</a></li>
-                </ul>
-                <p class="page">
-                    <button>上一页</button>
-                    <span><b>2</b>/5</span>
-                    <button>下一页</button>
-                </p>
+    <section id="app">
+        <header>
+            <div class="left_nav">
+                <img @click="show=!show" class="phone" width="30" src="img/menu.png" alt="">
+                <img class="logo" src="img/logo.jpg" alt="logo">
             </div>
-        </div>
-        <div class="right">
-            <div class="part">
-                <h2 class="sec_title"><span>面试排行榜</span>  <a href="">更多</a></h2>
-                <ul class="list list_100">
-                    <li><a href="">蛋黄酱</a><span>555</span></li>
-                    <li><a href="">蛋黄酱</a><span>555</span></li>
-                    <li><a href="">蛋黄酱</a><span>555</span></li>
-                    <li><a href="">蛋黄酱</a><span>555</span></li>
-                </ul>
+            <div class="nav">
+                <a class="act" href="/index.html">猿人学面试</a>
+                <a href="">爬虫比赛</a>
+                <a href="">关于猿人学</a>
+            </div>
+            <div class="login">
+                <div class="pc">
+                    <img width="30px" src="img/logo.jpg" alt="logo">
+                    <div v-if="userInfo" class="menu">
+                        {{userInfo.name}}
+                        <ul>
+                            <li><a href="/record.html">我的刷题记录</a></li>
+                            <li @click="logout"><a>退出登录</a></li>
+                        </ul>
+                    </div>
+                    <a v-else href="/login.html">请先登录</a>
+                </div>
+                <div class="phone">
+                    <span v-if="userInfo">{{userInfo.name}}</span>
+                    <a v-else href="/login.html">请先登录</a>
+                </div>
+            </div>
+        </header>
+        <transition name="slide">
+            <div class="slide" v-if="show">
+                <a class="act" href="/index.html">猿人学面试</a>
+                <a href="">爬虫比赛</a>
+                <a href="">关于猿人学</a>
+                <a v-if="userInfo" href="/record.html">我的刷题记录</a>
+                <a v-if="userInfo" @click="logout">退出登录</a>
+            </div>
+        </transition>
+        <div class="content">
+            <div class="left">
+                <div class="banner">
+                    <img width="100%" height="100%" :src="img[0]" alt="">
+                </div>
+            </div>
+            <div class="right">
+                <div class="banner">
+                    <img width="100%" height="100%" :src="img[1]" alt="">
+                </div>
+            </div>
+            <p class="navtation"><a href="/index.html">回到首页</a> - 
+                <span v-if="parm.category=='crawler'">爬虫</span>  
+                <span v-else-if="parm.category=='js'">JS</span>
+                <span v-else>安卓</span>  
+                面试题</p>
+            <div class="left">
+                <div class="part">
+                    <ul class="list">
+                        <li v-for="item in list">
+                            <a href="">{{item.name}}</a>
+                        </li>
+                    </ul>
+                    <p class="page">
+                        <button :disabled="parm.page==1?'disabled':''" @click="parm.page--,getData()">上一页</button>
+                        <span><b>{{parm.page}}</b>/{{pages}}</span>
+                        <button :disabled="parm.page==pages?'disabled':''" @click="parm.page++,getData()">下一页</button>
+                    </p>
+                </div>
             </div>
-            <div class="part">
-                <h2 class="sec_title"><span>贡献面试题</span></h2>
-                <form class="form" action="">
-                    <input type="text" placeholder="面试题目">
-                    <textarea></textarea>
-                    <button>提交</button>
-                </form>
+            <div class="right">
+                <div class="part">
+                    <h2 class="sec_title"><span>面试排行榜</span>  <a href="">更多</a></h2>
+                    <ul class="list list_100">
+                        <li v-for="item in top"><a href="">{{item.cname}}</a><span>{{item.count}}</span></li>
+                    </ul>
+                </div>
+                <div class="part">
+                    <h2 class="sec_title"><span>贡献面试题</span></h2>
+                    <form class="form" action="">
+                        <input v-model="name" type="text" placeholder="面试题目">
+                        <textarea v-model="content"></textarea>
+                        <button type="button" @click="post">提交</button>
+                    </form>
+                </div>
             </div>
         </div>
-    </div>
+    </section>
+    <script src="js/public.js"></script>
+    <script>
+        const { createApp } = Vue;
+        createApp({
+            data() {
+                return {
+                    list:[],
+                    parm:{
+                        category:'js',
+                        page:1,
+                        page_size:20
+                    },
+                    total:0,
+                    img:[],
+                    top:[],
+                    name: '',
+                    content: '',
+                    show: 0, // 添加 show 变量
+                    userInfo: {} // 添加 userInfo 变量
+                }
+            },
+            computed:{
+                pages(){
+                    return Math.ceil(this.total/20);
+                }
+            },
+            created(){
+                this.parm.category = new URLSearchParams(window.location.search).get('cat') || 'js'; // 获取URL中的cat参数并赋值给category
+                this.getData();
+                const userInfo = JSON.parse(localStorage.getItem('userInfo')); // 获取本地存储的用户信息
+                this.userInfo = userInfo;
+            },
+            methods:{
+                getData(){
+                    // 首页
+                    axios.get(url+'/api/yrx/banner/list?position=index_left').then(res=>{
+                        this.img[0] = res.data.data[0].jumpUrl;
+                    })
+                    axios.get(url+'/api/yrx/banner/list?position=index_right').then(res=>{
+                        this.img[1] = res.data.data[0].jumpUrl;
+                    })
+                    axios.get(url+'/api/yrx/que/user/top').then(res=>{
+                        this.top = res.data.data;
+                    })
+                    // 列表
+                    axios.get(url+'/api/yrx/que/list', { params: this.parm }).then(res=>{
+                        this.list = res.data.data.list;
+                        this.total = res.data.data.total;
+                    })
+                    
+                },
+                post(){ // 添加post方法
+                    if (!this.name || !this.content) {
+                        alert('面试题目和内容不能为空');
+                        return;
+                    }
+                    const token = localStorage.getItem('token'); // 获取token
+                    axios.post(url+'/api/yrx/que/user/post', { name: this.name, content: this.content }, {
+                        headers: {
+                            'Authorization': `${token}` // 添加token到header
+                        }
+                    })
+                    .then(res => {
+                        if(res.data.code === 0){
+                            alert('提交成功');
+                            this.name = '';
+                            this.content = '';
+                        }
+                    })
+                    .catch(err => {
+                        alert('提交失败,请重试');
+                        console.error(err);
+                    });
+                },
+                logout() { // 添加 logout 方法
+                    localStorage.removeItem('userInfo');
+                    localStorage.removeItem('token');
+                    this.userInfo = null;
+                }
+            }
+        }).mount('#app');
+    </script>
 </body>
 </html>

+ 143 - 14
login.html

@@ -6,23 +6,49 @@
     <title>登录</title>
     <link rel="stylesheet" href="css/index.css">
     <link rel="stylesheet" href="css/login.css">
+    <script src="js/axios.min.js"></script>
+    <script src="js/vue.js"></script>
 </head>
 <body>
+<section id="app">
     <header>
-        <img class="logo" src="img/logo.jpg" alt="logo">
+        <div class="left_nav">
+            <img @click="show=!show" class="phone" width="30" src="img/menu.png" alt="">
+            <img class="logo" src="img/logo.jpg" alt="logo">
+        </div>
         <div class="nav">
-            <a class="act" href="">猿人学面试</a>
+            <a class="act" href="/index.html">猿人学面试</a>
             <a href="">爬虫比赛</a>
             <a href="">关于猿人学</a>
         </div>
         <div class="login">
-            <img width="30px" src="img/logo.jpg" alt="logo">
-            <a href="#">请先登录</a>
+            <div class="pc">
+                <img width="30px" src="img/logo.jpg" alt="logo">
+                <div v-if="userInfo" class="menu">
+                    {{userInfo.name}}
+                    <ul>
+                        <li><a href="/record.html">我的刷题记录</a></li>
+                        <li @click="logout"><a>退出登录</a></li>
+                    </ul>
+                </div>
+                <a v-else href="/login.html">请先登录</a>
+            </div>
+            <div class="phone">
+                <span v-if="userInfo">{{userInfo.name}}</span>
+                <a v-else href="/login.html">请先登录</a>
+            </div>
         </div>
     </header>
-    <div class="content">
-        <p class="navtation"><a href="">首页</a> - 登录页</p>
-        <div class="addvx">
+    <transition name="slide">
+        <div class="slide" v-if="show">
+            <a class="act" href="/index.html">猿人学面试</a>
+            <a href="">爬虫比赛</a>
+            <a href="">关于猿人学</a>
+        </div>
+    </transition>
+    <div class="content" style="justify-content: center;">
+        <p class="navtation"><a href="/index.html">首页</a> - {{showLogin?'登录页':'注册页'}}</p>
+        <div class="addvx" v-if="!showLogin">
             扫码加我微信 <br>
             <b>免费领取注册邀请码</b><br>
             <img width="200" src="img/logo.jpg" alt=""><br>
@@ -30,20 +56,123 @@
             拉你入猿人学 - 面试交流群
         </div>
         <div class="signup">
-            <form action="" class="form reg">
+            <form v-if="!showLogin"  class="form reg" >
                 <label>昵称</label>
-                <input type="text" placeholder="昵称将会展示出来">
+                <input type="text" v-model="form.nickname" placeholder="昵称将会展示出来">
                 <label>注册账号</label>
-                <input type="text" placeholder="登录时的账号">
+                <input type="text" v-model="form.name" placeholder="登录时的账号">
                 <label>登录密码</label>
-                <input type="password">
+                <input type="password" v-model="form.password">
                 <label>确认密码</label>
-                <input type="password">
+                <input type="password" v-model="form.repassword">
                 <label>注册邀请码</label>
-                <input type="text" placeholder="右侧扫码加我微信,免费领取">
-                <button>立即注册</button>
+                <input type="text" v-model="form.invitationCode" placeholder="右侧扫码加我微信,免费领取">
+                <button type="button" @click="submitForm">立即注册</button>
+                <p align="center"><a style="cursor: pointer;" @click="showLogin=1">去登录</a></p>
+            </form>
+            <form v-else  class="form reg"  style="padding: 30px;">
+                <label>账号</label>
+                <input type="text" v-model="loginForm.name" placeholder="账号">
+                <label>密码</label>
+                <input type="password" placeholder="密码" v-model="loginForm.password">
+                <button type="button" @click="login">立即登录</button>
+                <p align="center"><a style="cursor: pointer;" @click="showLogin=0">去注册</a></p>
             </form>
         </div>
     </div>
+</section>
+<script src="js/public.js"></script>
+<script>
+    const { createApp } = Vue;
+    createApp({
+        data() {
+            return {
+                showLogin: true,
+                form: {
+                    name: "",
+                    nickname: "",
+                    password: "",
+                    repassword: "",
+                    invitationCode: ""
+                },
+                loginForm: {
+                    name: "",
+                    password: ""
+                },
+                userInfo: {}, // 添加 userInfo 变量
+                show: 0 // 添加 show 变量
+            }
+        },
+        created() {
+            const userInfo = JSON.parse(localStorage.getItem('userInfo')); // 获取本地存储的用户信息
+            this.userInfo = userInfo;
+        },
+        methods: {
+            submitForm() {
+                if (!this.form.name || !this.form.nickname || !this.form.password || !this.form.repassword || !this.form.invitationCode) {
+                    alert('所有字段都不能为空');
+                    return;
+                }
+                if (this.form.password !== this.form.repassword) {
+                    alert('两次输入的密码不一致');
+                    return;
+                }
+                axios.post(url + '/api/account/regist', this.form)
+                    .then(res => {
+                        localStorage.setItem('token',res.data.data.token);
+                        this.getUser();
+                        window.location.href = '/index.html';
+                    })
+                    .catch(err => {
+                        alert('提交失败,请重试');
+                        console.error(err);
+                    });
+            },
+            login() {
+                if (!this.loginForm.name || !this.loginForm.password) {
+                    alert('所有字段都不能为空');
+                    return;
+                }
+                axios.post(url + '/api/account/login', this.loginForm)
+                    .then(res => {
+                        
+                        if(res.data.code==0){
+                            // alert('登录成功');
+                            localStorage.setItem('token',res.data.data.token);
+                            this.getUser();
+                            setTimeout(() => {
+                                window.location.href = '/index.html';
+                            }, 500);
+                        }else{
+                            alert(res.data.message);
+                        }
+                    })
+                    .catch(err => {
+                        alert('登录失败,请重试');
+                        console.error(err);
+                    });
+            },
+            getUser(){
+                // 获取token
+                const token = localStorage.getItem('token');
+                axios.get(url + '/api/account/userinfo', {
+                    headers: {
+                        'Authorization': `${token}`
+                    }
+                })
+                .then(res => {
+                    if (res.data.code === 0) {
+                        localStorage.setItem('userInfo', JSON.stringify(res.data.data));
+                    } 
+                })
+            },
+            logout() { // 添加 logout 方法
+                localStorage.removeItem('userInfo');
+                localStorage.removeItem('token');
+                this.userInfo = null;
+            }
+        }
+    }).mount('#app');
+</script>
 </body>
 </html>

+ 116 - 34
record.html

@@ -5,6 +5,8 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>面试题</title>
     <link rel="stylesheet" href="css/index.css">
+    <script src="js/axios.min.js"></script>
+    <script src="js/vue.js"></script>
 </head>
 <style>
     .record li{
@@ -20,66 +22,146 @@
     }
 </style>
 <body>
+<section id="app">
     <header>
-        <img class="logo" src="img/logo.jpg" alt="logo">
+        <div class="left_nav">
+            <img @click="show=!show" class="phone" width="30" src="img/menu.png" alt="">
+            <img class="logo" src="img/logo.jpg" alt="logo">
+        </div>
         <div class="nav">
-            <a class="act" href="">猿人学面试</a>
+            <a class="act" href="/index.html">猿人学面试</a>
             <a href="">爬虫比赛</a>
             <a href="">关于猿人学</a>
         </div>
         <div class="login">
-            <img width="30px" src="img/logo.jpg" alt="logo">
-            <a href="#">请先登录</a>
+            <div class="pc">
+                <img width="30px" src="img/logo.jpg" alt="logo">
+                <div v-if="userInfo" class="menu">
+                    {{userInfo.name}}
+                    <ul>
+                        <li><a href="/record.html">我的刷题记录</a></li>
+                        <li @click="logout"><a>退出登录</a></li>
+                    </ul>
+                </div>
+                <a v-else href="/login.html">请先登录</a>
+            </div>
+            <div class="phone">
+                <span v-if="userInfo">{{userInfo.name}}</span>
+                <a v-else href="/login.html">请先登录</a>
+            </div>
         </div>
     </header>
+    <transition name="slide">
+        <div class="slide" v-if="show">
+            <a class="act" href="/index.html">猿人学面试</a>
+            <a href="">爬虫比赛</a>
+            <a href="">关于猿人学</a>
+            <a v-if="userInfo" href="/record.html">我的刷题记录</a>
+            <a v-if="userInfo" @click="logout">退出登录</a>
+        </div>
+    </transition>
     <div class="content">
         <p class="navtation"><a href="">首页</a> - 刷题记录</p>
         <div class="left">
             <div class="part">
                 <p><b style="font-size: 15px;">蛋黄酱</b>的面试刷题</p>
                 <ul class="list record">
-                    <li><a href="">
-                        1.瑞树的整个逆向流程瑞树的整个逆向流程 <br>
-                        <span>2025-03-12 12:00</span>
-                    </a></li>
-                    <li><a href="">
-                        1.瑞树的整个逆向流程瑞树的整个逆向流程 <br>
-                        <span>2025-03-12 12:00</span>
-                    </a></li>
-                    <li><a href="">
-                        1.瑞树的整个逆向流程瑞树的整个逆向流程 <br>
-                        <span>2025-03-12 12:00</span>
-                    </a></li>
-                    <li><a href="">
-                        1.瑞树的整个逆向流程瑞树的整个逆向流程 <br>
-                        <span>2025-03-12 12:00</span>
-                    </a></li>
-                    <li><a href="">
-                        1.瑞树的整个逆向流程瑞树的整个逆向流程 <br>
-                        <span>2025-03-12 12:00</span>
-                    </a></li>
-                    <li><a href="">
-                        1.瑞树的整个逆向流程瑞树的整个逆向流程 <br>
-                        <span>2025-03-12 12:00</span>
+                    <li v-for="(item,i) in list"><a href="">
+                        {{i+1}}.{{item.name}} <br>
+                        <span>{{item.ctime}}</span>
                     </a></li>
                 </ul>
                 <p class="page">
-                    <button>上一页</button>
-                    <span><b>2</b>/5</span>
-                    <button>下一页</button>
+                    <button :disabled="parm.page==1?'disabled':''" @click="parm.page--,getData()">上一页</button>
+                    <span><b>{{parm.page}}</b>/{{pages}}</span>
+                    <button :disabled="parm.page==pages?'disabled':''" @click="parm.page++,getData()">下一页</button>
                 </p>
             </div>
         </div>
         <div class="right">
             <div class="part">
                 <h2 class="sec_title"><span>贡献面试题</span></h2>
-                <form class="form" action="">
-                    <input type="text" placeholder="面试题目">
-                    <textarea></textarea>
-                    <button>提交</button>
+                <form class="form">
+                    <input v-model="name" type="text" placeholder="面试题目">
+                    <textarea v-model="content"></textarea>
+                    <button type="button" @click="post">提交</button>
                 </form>
             </div>
         </div>
     </div>
+</section>
+<script src="js/public.js"></script>
+<script>
+    const { createApp } = Vue;
+    createApp({
+        data() {
+            return {
+                list:[],
+                parm:{
+                    cid:'',
+                    page:1,
+                    page_size:20
+                },
+                total:0,
+                name: '',
+                content: '',
+                userInfo:{},
+                show: 0 // 添加 show 变量
+            }
+        },
+        computed:{
+            pages(){
+                return Math.ceil(this.total/20);
+            }
+        },
+        created(){
+            // 获取本地存储的用户ID并赋值给cid
+            const userInfo = JSON.parse(localStorage.getItem('userInfo'));
+            if (!userInfo) {
+                window.location.href = 'login.html';
+            }
+            this.userInfo = userInfo;
+            this.parm.cid = userInfo ? userInfo.id : '';
+            this.getData();
+        },
+        methods:{
+            getData(){
+                // 列表
+                axios.get(url+'/api/yrx/que/user/records', { params: this.parm }).then(res=>{
+                    this.list = res.data.data.list;
+                    this.total = res.data.data.total;
+                })
+            },
+            post(){ // 添加post方法
+                if (!this.name || !this.content) {
+                    alert('面试题目和内容不能为空');
+                    return;
+                }
+                const token = localStorage.getItem('token'); // 获取token
+                axios.post(url+'/api/yrx/que/user/post', { name: this.name, content: this.content }, {
+                    headers: {
+                        'Authorization': `${token}` // 添加token到header
+                    }
+                })
+                .then(res => {
+                    if(res.data.code === 0){
+                        alert('提交成功');
+                        this.name = '';
+                        this.content = '';
+                    }
+                })
+                .catch(err => {
+                    alert('提交失败,请重试');
+                    console.error(err);
+                });
+            },
+            logout() { // 添加 logout 方法
+                localStorage.removeItem('userInfo');
+                localStorage.removeItem('token');
+                this.userInfo = null;
+            }
+        }
+    }).mount('#app');
+</script>
 </body>
 </html>