前端項(xiàng)目搭建

1.使用vite構(gòu)建vue3

1.1.執(zhí)行命令

npm create vite

輸入項(xiàng)目名字 elm-frontend



選擇框架-vue



選擇js標(biāo)準(zhǔn)-JavaScript

1.2.項(xiàng)目初始化安裝

進(jìn)入項(xiàng)目目錄,安裝默認(rèn)依賴及vue-router,axios,qs,font-awesome

npm i
npm i vue-router
npm i axios
npm i qs
npm i font-awesome

2.項(xiàng)目初始化

2.1.刪除默認(rèn)生成的代碼

11.png

修改App.vue

<template>
  <router-view></router-view>
</template>

修改style.css

html,body,div,span,h1,h2,h3,h4,h5,h6,ul,ol,li,p {
    margin: 0;
    padding: 0;
    font-family: "微軟雅黑";
}
html,body,#app {
    width: 100%;
}
ul,ol {
    list-style: none;
}
a {
    text-decoration: none;
}

修改index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="shortcut icon" >
    <title>餓了么</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

2.2創(chuàng)建路由文件,及修改main.js使用路由

router/index.js

import {createRouter,createWebHashHistory} from 'vue-router'

const routes = [

]
//創(chuàng)建路由實(shí)例
const router = createRouter({
    history: createWebHashHistory(),
    routes
  });
//路由守衛(wèi)
router.beforeEach( (to, from, next) => {
  // 檢查 sessionStorage 中是否有登錄信息
  const user = sessionStorage.getItem('user')
  // 如果目標(biāo)路由需要認(rèn)證且用戶未登錄
  if ( !user && to.meta.isAuth ) {
    router.push('/login') // 重定向到登錄頁
  } else {
    next() // 繼續(xù)導(dǎo)航
  }
})  
export default router;

main.js

import { createApp } from 'vue'
import App from './App.vue'
import './style.css'
import 'font-awesome/css/font-awesome.min.css'
import router from './router';

const app = createApp(App);
app.use(router);
app.mount('#app');

2.3.創(chuàng)建 axios 實(shí)例并封裝,配置攔截器

新建api/index.js

import axios from 'axios';
// 創(chuàng)建 axios 實(shí)例
const request = axios.create({
    baseURL: 'http://localhost:9999/elm',
    timeout: 3000 // 請求超時時間
});

// 響應(yīng)攔截器
request.interceptors.response.use(
    response => {
        // 獲取響應(yīng)數(shù)據(jù)
        const res = response.data;
        //直接返回響應(yīng)數(shù)據(jù)
        return res;
    },
    error => {
        // 處理響應(yīng)錯誤
        console.log('響應(yīng)錯誤:' + error); // 打印錯誤信息
    }
);
export default request;

2.4.通用組件 TabMenu.vue(底部菜單)

<template>
    <ul class="footer">
      <li @click="toIndex">
        <i class="fa fa-home"></i>
        <p>首頁</p>
      </li>
      <li>
        <i class="fa fa-compass"></i>
        <p>發(fā)現(xiàn)</p>
      </li>
      <li @click="toOrderList">
        <i class="fa fa-file-text-o"></i>
        <p>訂單</p>
      </li>
      <li>
        <i class="fa fa-user-o"></i>
        <p>我的</p>
      </li>
    </ul>
  </template>
  
  <script setup>
  import { useRouter } from "vue-router";
  
  const router = useRouter();
  
  const toIndex = () => {
    router.push({ path: "/" });
  };
  const toOrderList = () => {
    router.push({ path: "/orderList" });
  };
  </script>
  
  <style scoped>
  .wrapper .footer {
    width: 100%;
    height: 14vw;
    border-top: solid 1px #ddd;
    background-color: #fff;
  
    position: fixed;
    left: 0;
    bottom: 0;
  
    display: flex;
    justify-content: space-around;
    align-items: center;
  }
  
  .wrapper .footer li {
    /*li本身的尺寸完全由內(nèi)容撐起*/
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  
    color: #999;
    user-select: none;
    cursor: pointer;
  }
  
  .wrapper .footer li p {
    font-size: 2.8vw;
  }
  
  .wrapper .footer li i {
    font-size: 5vw;
  }
  </style>

3.組件開發(fā)

3.1.Index.vue

<template>
  <div class="wrapper">
    <!-- header部分 -->
    <header>
      <div class="icon-location-box">
        <div class="icon-location"></div>
      </div>
      <div class="location-text">
        東軟河口園區(qū)<i class="fa fa-caret-down"></i>
      </div>
    </header>
    <div class="search">
      <div class="search-fixed-top" ref="fixedBox">
        <!-- 搜索框部分中間的白框 -->
        <div class="search-box">
          <i class="fa fa-search"></i>
          <input  type="text" placeholder="搜索餓了么商家">
        </div>
      </div>
    </div>

    <!-- 點(diǎn)餐分類部分 -->
    <ul class="foodtype">
      <li @click="toBusinessList(1)">
        <img src="../assets/dcfl01.png" />
        <p>美食</p>
      </li>
      <li @click="toBusinessList(2)">
        <img src="../assets/dcfl02.png" />
        <p>早餐</p>
      </li>
      <li @click="toBusinessList(3)">
        <img src="../assets/dcfl03.png" />
        <p>跑腿代購</p>
      </li>
      <li @click="toBusinessList(4)">
        <img src="../assets/dcfl04.png" />
        <p>漢堡披薩</p>
      </li>
      <li @click="toBusinessList(5)">
        <img src="../assets/dcfl05.png" />
        <p>甜品飲品</p>
      </li>
      <li @click="toBusinessList(6)">
        <img src="../assets/dcfl06.png" />
        <p>速食簡餐</p>
      </li>
      <li @click="toBusinessList(7)">
        <img src="../assets/dcfl07.png" />
        <p>地方小吃</p>
      </li>
      <li @click="toBusinessList(8)">
        <img src="../assets/dcfl08.png" />
        <p>米粉面館</p>
      </li>
      <li @click="toBusinessList(9)">
        <img src="../assets/dcfl09.png" />
        <p>包子粥鋪</p>
      </li>
      <li @click="toBusinessList(10)">
        <img src="../assets/dcfl10.png" />
        <p>炸雞炸串</p>
      </li>
    </ul>

    <!-- 橫幅廣告部分(注意:此處有背景圖片) -->
    <div class="banner">
      <h3>品質(zhì)套餐</h3>
      <p>搭配齊全吃得好</p>
      <a>立即搶購 &gt;</a>
    </div>

    <!-- 超級會員部分 -->
    <div class="supermember">
      <div class="left">
        <img src="../assets/super_member.png" />
        <h3>超級會員</h3>
        <p>&#8226; 每月享超值權(quán)益</p>
      </div>
      <div class="right">立即開通 &gt;</div>
    </div>

    <!-- 推薦商家部分 -->
    <div class="recommend">
      <div class="recommend-line"></div>
      <p>推薦商家</p>
      <div class="recommend-line"></div>
    </div>

    <!-- 推薦方式部分 -->
    <ul class="recommendtype">
      <li>綜合排序<i class="fa fa-caret-down"></i></li>
      <li>距離最近</li>
      <li>銷量最高</li>
      <li>篩選<i class="fa fa-filter"></i></li>
    </ul>

    <!-- 推薦商家列表部分 -->
    <ul class="business">
      <li >
        <img src="" />
        <div class="business-info">
          <div class="business-info-h">
            <h3>name</h3>
            <div class="business-info-like">&#8226;</div>
          </div>
          <div class="business-info-star">
            <div class="business-info-star-left">
              <i class="fa fa-star"></i>
              <i class="fa fa-star"></i>
              <i class="fa fa-star"></i>
              <i class="fa fa-star"></i>
              <i class="fa fa-star"></i>
            </div>
            <div class="business-info-star-right">蜂鳥專送</div>
          </div>
          <div class="business-info-delivery">
            <p>&#165;28起送 | &#165;3配送</p>
          </div>
          <div class="business-info-explain">
            <div>描述</div>
          </div>
          <div class="business-info-promotion">
            <div class="business-info-promotion-left">
              <div class="business-info-promotion-left-incon">新</div>
              <p>餓了么新用戶首單立減9元</p>
            </div>
          </div>
          
        </div>
      </li>
    </ul>
    <!-- 底部菜單部分 -->
    <TabMenu></TabMenu>
  </div>
</template>

<script setup>
import TabMenu from '../components/TabMenu.vue'
import { ref, onBeforeMount} from "vue";
import { useRouter } from "vue-router";
import axios from '../api'


</script>

<style scoped>
/****************** 總?cè)萜?******************/
.wrapper {
  width: 100%;
  height: 100%;
}

/****************** header ******************/
.wrapper header {
  width: 100%;
  height: 12vw;
  background-color: #0097ff;

  display: flex;
  align-items: center;
}

.wrapper header .icon-location-box {
  width: 3.5vw;
  height: 3.5vw;
  margin: 0 1vw 0 3vw;
}

.wrapper header .location-text {
  font-size: 4.5vw;
  font-weight: 700;
  color: #fff;
}

.wrapper header .location-text .fa-caret-down {
  margin-left: 1vw;
}

/****************** search ******************/
.wrapper .search {
  width: 100%;
  height: 13vw;
}

.wrapper .search .search-fixed-top {
  width: 100%;
  height: 13vw;
  background-color: #0097ff;
  display: flex;
  justify-content: center;
  align-items: center;
}

.wrapper .search .search-fixed-top .search-box {
  width: 90%;
  height: 9vw;
  background-color: #fff;
  border-radius: 2px;

  display: flex;
  justify-content: center;
  align-items: center;

  font-size: 3.5vw;
  color: #aeaeae;
  font-family: "宋體";
  /*此樣式是讓文本選中狀態(tài)無效*/
  user-select: none;
}

.wrapper .search .search-fixed-top .search-box .fa-search {
  margin-right: 1vw;
}
.search-box input{
  width: 40vw;
  height: 5vh;
  border: none;
  outline: none;
}
.search-box input::placeholder {
color: #AEAEAE; 
opacity: 0.8; 
}
/****************** 點(diǎn)餐分類部分 ******************/
.wrapper .foodtype {
  width: 100%;
  height: 48vw;

  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  /*要使用align-content。10個子元素將自動換行為兩行,而且兩行作為一個整體垂直居中*/
  align-content: center;
}

.wrapper .foodtype li {
  /*一共10個子元素,通過計(jì)算,子元素寬度在16.7 ~ 20 之間,才能保證換兩行*/
  width: 18vw;
  height: 20vw;

  display: flex;
  /*彈性盒子主軸方向設(shè)為column,然后仍然是垂直水平方向居中*/
  flex-direction: column;
  justify-content: center;
  align-items: center;

  user-select: none;
  cursor: pointer;
}

.wrapper .foodtype li img {
  width: 12vw;
  /*視頻講解時高度設(shè)置為12vw,實(shí)際上設(shè)置為10.3vw更佳*/
  height: 10.3vw;
}

.wrapper .foodtype li p {
  font-size: 3.2vw;
  color: #666;
}

/****************** 橫幅廣告部分 ******************/
.wrapper .banner {
  /**
         * 設(shè)置容器寬度95%,然后水平居中,這樣兩邊留白; 
         * 這里不能用padding,因?yàn)楸尘皥D片也會覆蓋padding
         */
  width: 95%;
  margin: 0 auto;
  height: 29vw;

  /*此三個樣式組合,可以保證背景圖片充滿整個容器*/
  background-image: url(../assets/index_banner.png);
  background-repeat: no-repeat;
  background-size: cover;

  box-sizing: border-box;
  padding: 2vw 6vw;
}

.wrapper .banner h3 {
  font-size: 4.2vw;
  margin-bottom: 1.2vw;
}

.wrapper .banner p {
  font-size: 3.4vw;
  color: #666;
  margin-bottom: 2.4vw;
}

.wrapper .banner a {
  font-size: 3vw;
  color: #c79060;
  font-weight: 700;
}

/****************** 超級會員部分 ******************/
.wrapper .supermember {
  /*這里也設(shè)置容器寬度95%,不能用padding,因?yàn)楸尘吧矔錆Mpadding*/
  width: 95%;
  margin: 0 auto;
  height: 11.5vw;
  background-color: #feedc1;
  margin-top: 1.3vw;
  border-radius: 2px;
  color: #644f1b;

  display: flex;
  justify-content: space-between;
  align-items: center;
}

.wrapper .supermember .left {
  display: flex;
  align-items: center;
  margin-left: 4vw;
  user-select: none;
}

.wrapper .supermember .left img {
  width: 6vw;
  height: 6vw;
  margin-right: 2vw;
}

.wrapper .supermember .left h3 {
  font-size: 4vw;
  margin-right: 2vw;
}

.wrapper .supermember .left p {
  font-size: 3vw;
}

.wrapper .supermember .right {
  font-size: 3vw;
  margin-right: 4vw;
  cursor: pointer;
}

/****************** 推薦商家部分 ******************/
.wrapper .recommend {
  width: 100%;
  height: 14vw;
  display: flex;
  justify-content: center;
  align-items: center;
}

.wrapper .recommend .recommend-line {
  width: 6vw;
  height: 0.2vw;
  background-color: #888;
}

.wrapper .recommend p {
  font-size: 4vw;
  margin: 0 4vw;
}

/****************** 推薦方式部分 ******************/
.wrapper .recommendtype {
  width: 100%;
  height: 5vw;
  margin-bottom: 5vw;

  display: flex;
  justify-content: space-around;
  align-items: center;
}

.wrapper .recommendtype li {
  font-size: 3.5vw;
  color: #555;
}

/****************** 推薦商家列表部分 ******************/
.wrapper .business {
  width: 100%;
  margin-bottom: 14vw;
}

.wrapper .business li {
  width: 100%;
  box-sizing: border-box;
  padding: 2.5vw;
  user-select: none;
  border-bottom: solid 1px #ddd;

  display: flex;
}

.wrapper .business li img {
  width: 18vw;
  height: 18vw;
}

.wrapper .business li .business-info {
  width: 100%;
  box-sizing: border-box;
  padding-left: 3vw;
}

.wrapper .business li .business-info .business-info-h {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 2vw;
}

.wrapper .business li .business-info .business-info-h h3 {
  font-size: 4vw;
  color: #333;
}

.wrapper .business li .business-info .business-info-h .business-info-like {
  width: 1.6vw;
  height: 3.4vw;
  background-color: #666;
  color: #fff;
  font-size: 4vw;
  margin-right: 4vw;

  display: flex;
  justify-content: center;
  align-items: center;
}

.wrapper .business li .business-info .business-info-star {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 2vw;
  font-size: 3.1vw;
}

.wrapper
  .business
  li
  .business-info
  .business-info-star
  .business-info-star-left {
  display: flex;
  align-items: center;
}

.wrapper
  .business
  li
  .business-info
  .business-info-star
  .business-info-star-left
  .fa-star {
  color: #fec80e;
  margin-right: 0.5vw;
}

.wrapper
  .business
  li
  .business-info
  .business-info-star
  .business-info-star-left
  p {
  color: #666;
  margin-left: 1vw;
}

.wrapper
  .business
  li
  .business-info
  .business-info-star
  .business-info-star-right {
  background-color: #0097ff;
  color: #fff;
  font-size: 2.4vw;
  border-radius: 2px;
  padding: 0 0.6vw;
}

.wrapper .business li .business-info .business-info-delivery {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 2vw;

  color: #666;
  font-size: 3.1vw;
}

.wrapper .business li .business-info .business-info-explain {
  display: flex;
  align-items: center;
  margin-bottom: 3vw;
}

.wrapper .business li .business-info .business-info-explain div {
  border: solid 1px #ddd;
  font-size: 2.8vw;
  color: #666;
  border-radius: 3px;
  padding: 0 0.1vw;
}

.wrapper .business li .business-info .business-info-promotion {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1.8vw;
}

.wrapper
  .business
  li
  .business-info
  .business-info-promotion
  .business-info-promotion-left {
  display: flex;
  align-items: center;
}

.wrapper
  .business
  li
  .business-info
  .business-info-promotion
  .business-info-promotion-left
  .business-info-promotion-left-incon {
  width: 4vw;
  height: 4vw;
  background-color: #70bc46;
  border-radius: 3px;
  font-size: 3vw;
  color: #fff;

  display: flex;
  justify-content: center;
  align-items: center;
}

.wrapper
  .business
  li
  .business-info
  .business-info-promotion
  .business-info-promotion-left
  p {
  color: #666;
  font-size: 3vw;
  margin-left: 2vw;
}

.wrapper
  .business
  li
  .business-info
  .business-info-promotion
  .business-info-promotion-right {
  display: flex;
  align-items: center;
  font-size: 2.5vw;
  color: #999;
}

.wrapper
  .business
  li
  .business-info
  .business-info-promotion
  .business-info-promotion-right
  p {
  margin-right: 2vw;
}
</style>

3.2.BusinessList.vue 商家列表組件

<template>
    <div class="wrapper">
      <!-- header部分 -->
      <header>
        <p>商家列表</p>
      </header>
  
      <!-- 商家列表部分 -->
      <ul class="business">
        <li >
          <div class="business-img">
            <img src="" />
          </div>
          <div class="business-info">
            <h3>商家名</h3>
            <p>
              &#165;1起送 | &#165;5配送
            </p>
            <p>商家說明</p>
          </div>
        </li>
      </ul>
  
      <!-- 底部菜單部分 -->
      <TabMenu></TabMenu>
    </div>
  </template>
  
  <script setup>
  import Footer from "../components/TabMenu.vue";
  import {ref,reactive} from 'vue'
  import {useRouter,useRoute} from 'vue-router'
  import axios from '@/api'
  
  
  </script>
  
  <style scoped>
  /****************** 總?cè)萜?******************/
  .wrapper {
    width: 100%;
    height: 100%;
  }
  
  /****************** header部分 ******************/
  .wrapper header {
    width: 100%;
    height: 12vw;
    background-color: #0097ff;
    color: #fff;
    font-size: 4.8vw;
  
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1000;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  /****************** 商家列表部分 ******************/
  .wrapper .business {
    width: 100%;
    margin-top: 12vw;
    margin-bottom: 14vw;
  }
  
  .wrapper .business li {
    width: 100%;
    box-sizing: border-box;
    padding: 2.5vw;
    border-bottom: solid 1px #ddd;
    user-select: none;
    cursor: pointer;
  
    display: flex;
    align-items: center;
  }
  
  .wrapper .business li .business-img {
    /*這里設(shè)置為相當(dāng)定位,成為business-img-quantity元素的父元素*/
    position: relative;
  }
  
  .wrapper .business li .business-img img {
    width: 20vw;
    height: 20vw;
  }
  
  .wrapper .business li .business-img .business-img-quantity {
    width: 5vw;
    height: 5vw;
    background-color: red;
    color: #fff;
    font-size: 3.6vw;
    border-radius: 2.5vw;
  
    display: flex;
    justify-content: center;
    align-items: center;
  
    /*設(shè)置成絕對定位,不占文檔流空間*/
    position: absolute;
    right: -1.5vw;
    top: -1.5vw;
  }
  
  .wrapper .business li .business-info {
    margin-left: 3vw;
  }
  
  .wrapper .business li .business-info h3 {
    font-size: 3.8vw;
    color: #555;
  }
  
  .wrapper .business li .business-info p {
    font-size: 3vw;
    color: #888;
    margin-top: 2vw;
  }
  </style>

3.3.BusinessInfo.vue 商家信息組件

<template>
    <div class="wrapper">
      <!-- header部分 -->
      <header>
        <p>商家信息</p>
      </header>
  
      <!-- 商家logo部分 -->
      <div class="business-logo">
        <img src="" />
      </div>
  
      <!-- 商家信息部分 -->
      <div class="business-info">
        <h1>商家名</h1>
        <p>
          &#165;10起送 &#165;5配送
        </p>
        <p>商家說明</p>
      </div>
  
      <!-- 食品列表部分 -->
      <ul class="food">
        <li>
          <div class="food-left">
            <img src="" />
            <div class="food-left-info">
              <h3>食品名</h3>
              <p>食品說明</p>
              <p>&#165;10</p>
            </div>
          </div>
          <div class="food-right">
            <div>
              <i
                class="fa fa-minus-circle"
              ></i>
            </div>
            <p>
              <span>1</span>
            </p>
            <div>
              <i class="fa fa-plus-circle"></i>
            </div>
          </div>
        </li>
      </ul>
  
      <!-- 購物車部分 -->
      <div class="cart">
        <div class="cart-left">
          <div class="cart-left-icon">
            <i class="fa fa-shopping-cart"></i>
            <div class="cart-left-icon-quantity">
             3
            </div>
          </div>
          <div class="cart-left-info">
            <p>&#165;100</p>
            <p>另需配送費(fèi)3元</p>
          </div>
        </div>
        <div class="cart-right">
          <!-- 達(dá)到起送費(fèi) -->
          <div class="cart-right-item-not-enough">
            去結(jié)算
          </div>
        </div>
      </div>
    </div>
  </template>
  
  <script setup>
  import {ref,reactive} from 'vue'
  import {useRouter,useRoute} from 'vue-router'
  import axios from '../api'

  </script>
  
  <style scoped>
  /****************** 總?cè)萜?******************/
  .wrapper {
    width: 100%;
    height: 100%;
  }
  
  /****************** header部分 ******************/
  .wrapper header {
    width: 100%;
    height: 12vw;
    background-color: #0097ff;
    color: #fff;
    font-size: 4.8vw;
  
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1000;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  /****************** 商家logo部分 ******************/
  .wrapper .business-logo {
    width: 100%;
    height: 35vw;
    /*使用上外邊距避開header部分*/
    margin-top: 12vw;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .wrapper .business-logo img {
    width: 40vw;
    height: 30vw;
    border-radius: 5px;
  }
  
  /****************** 商家信息部分 ******************/
  .wrapper .business-info {
    width: 100%;
    height: 20vw;
  
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
  .wrapper .business-info h1 {
    font-size: 5vw;
  }
  .wrapper .business-info p {
    font-size: 3vw;
    color: #666;
    margin-top: 1vw;
  }
  
  /****************** 食品列表部分 ******************/
  .wrapper .food {
    width: 100%;
    /*使用下外邊距避開footer部分*/
    margin-bottom: 14vw;
  }
  .wrapper .food li {
    width: 100%;
    box-sizing: border-box;
    padding: 2.5vw;
    user-select: none;
  
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .wrapper .food li .food-left {
    display: flex;
    align-items: center;
  }
  .wrapper .food li .food-left img {
    width: 20vw;
    height: 20vw;
  }
  .wrapper .food li .food-left .food-left-info {
    margin-left: 3vw;
  }
  .wrapper .food li .food-left .food-left-info h3 {
    font-size: 3.8vw;
    color: #555;
  }
  .wrapper .food li .food-left .food-left-info p {
    font-size: 3vw;
    color: #888;
    margin-top: 2vw;
  }
  .wrapper .food li .food-right {
    width: 16vw;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .wrapper .food li .food-right .fa-minus-circle {
    font-size: 5.5vw;
    color: #999;
    cursor: pointer;
  }
  .wrapper .food li .food-right p {
    font-size: 3.6vw;
    color: #333;
  }
  .wrapper .food li .food-right .fa-plus-circle {
    font-size: 5.5vw;
    color: #0097ef;
    cursor: pointer;
  }
  
  /****************** 購物車部分 ******************/
  .wrapper .cart {
    width: 100%;
    height: 14vw;
  
    position: fixed;
    left: 0;
    bottom: 0;
  
    display: flex;
  }
  .wrapper .cart .cart-left {
    flex: 2;
    background-color: #505051;
    display: flex;
  }
  .wrapper .cart .cart-left .cart-left-icon {
    width: 16vw;
    height: 16vw;
    box-sizing: border-box;
    border: solid 1.6vw #444;
    border-radius: 8vw;
    background-color: #3190e8;
    font-size: 7vw;
    color: #fff;
  
    display: flex;
    justify-content: center;
    align-items: center;
  
    margin-top: -4vw;
    margin-left: 3vw;
  
    position: relative;
  }
  .wrapper .cart .cart-left .cart-left-icon-quantity {
    width: 5vw;
    height: 5vw;
    border-radius: 2.5vw;
    background-color: red;
    color: #fff;
    font-size: 3.6vw;
  
    display: flex;
    justify-content: center;
    align-items: center;
  
    position: absolute;
    right: -1.5vw;
    top: -1.5vw;
  }
  .wrapper .cart .cart-left .cart-left-info p:first-child {
    font-size: 4.5vw;
    color: #fff;
    margin-top: 1vw;
  }
  .wrapper .cart .cart-left .cart-left-info p:last-child {
    font-size: 2.8vw;
    color: #aaa;
  }
  
  .wrapper .cart .cart-right {
    flex: 1;
  }
  /*達(dá)到起送費(fèi)時的樣式*/
  /*
  .wrapper .cart .cart-right .cart-right-item {
    width: 100%;
    height: 100%;
    background-color: #38ca73;
    color: #fff;
    font-size: 4.5vw;
    font-weight: 700;
    user-select: none;
    cursor: pointer;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
   */
  /*不夠起送費(fèi)時的樣式(只有背景色和鼠標(biāo)樣式的區(qū)別)*/
  
  .cart-right-item-not-enough{
          width: 100%;
          height: 100%;
          background-color: #535356;
          color: #fff;
          font-size: 4.5vw;
          font-weight: 700;
          user-select: none;
          
          display: flex;
          justify-content: center;
          align-items: center;
      }
  </style>

3.4.Login.vue組件 登錄組件

<template>
    <div class="wrapper">
      <!-- header部分 -->
      <header>
        <p>用戶登陸</p>
      </header>
  
      <!-- 表單部分 -->
      <ul class="form-box">
        <li>
          <div class="title">手機(jī)號碼:</div>
          <div class="content">
            <input type="text"  placeholder="手機(jī)號碼" />
          </div>
        </li>
        <li>
          <div class="title">密碼:</div>
          <div class="content">
            <input type="password" placeholder="密碼" />
          </div>
        </li>
      </ul>
  
      <div class="button-login">
        <button>登陸</button>
      </div>
      <div class="button-register">
        <button>去注冊</button>
      </div>
  
      <!-- 底部菜單部分 -->
      <TabMenu></TabMenu>
    </div>
  </template>
  
  <script setup>
  import TabMenu from '../components/TabMenu.vue'
  import axios from "../api";
  import qs from 'qs'
  import { useRouter } from "vue-router";

  

  </script>
  
  <style scoped>
  /****************** 總?cè)萜?******************/
  .wrapper {
    width: 100%;
    height: 100%;
  }
  
  /****************** header部分 ******************/
  .wrapper header {
    width: 100%;
    height: 12vw;
    background-color: #0097ff;
    color: #fff;
    font-size: 4.8vw;
  
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1000;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  /****************** 表單部分 ******************/
  .wrapper .form-box {
    width: 100%;
    margin-top: 12vw;
  }
  
  .wrapper .form-box li {
    box-sizing: border-box;
    padding: 4vw 3vw 0 3vw;
    display: flex;
    align-items: center;
  }
  
  .wrapper .form-box li .title {
    flex: 0 0 18vw;
    font-size: 3vw;
    font-weight: 700;
    color: #666;
  }
  
  .wrapper .form-box li .content {
    flex: 1;
  }
  
  .wrapper .form-box li .content input {
    border: none;
    outline: none;
    width: 100%;
    height: 4vw;
    font-size: 3vw;
  }
  
  .wrapper .button-login {
    width: 100%;
    box-sizing: border-box;
    padding: 4vw 3vw 0 3vw;
  }
  
  .wrapper .button-login button {
    width: 100%;
    height: 10vw;
    font-size: 3.8vw;
    font-weight: 700;
    color: #fff;
    background-color: #38ca73;
    border-radius: 4px;
  
    border: none;
    outline: none;
  }
  
  .wrapper .button-register {
    width: 100%;
    box-sizing: border-box;
    padding: 4vw 3vw 0 3vw;
  }
  
  .wrapper .button-register button {
    width: 100%;
    height: 10vw;
    font-size: 3.8vw;
    font-weight: 700;
    /*與上面登陸按鈕不同的只有顏色、背景色、邊框不同*/
    color: #666;
    background-color: #eee;
    border: solid 1px #ddd;
    border-radius: 4px;
  
    border: none;
    outline: none;
  }
  
  /****************** 底部菜單部分 ******************/
  .wrapper .footer {
    width: 100%;
    height: 14vw;
    border-top: solid 1px #ddd;
    background-color: #fff;
  
    position: fixed;
    left: 0;
    bottom: 0;
  
    display: flex;
    justify-content: space-around;
    align-items: center;
  }
  
  .wrapper .footer li {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  
    color: #999;
    user-select: none;
    cursor: pointer;
  }
  
  .wrapper .footer li p {
    font-size: 2.8vw;
  }
  
  .wrapper .footer li i {
    font-size: 5vw;
  }
  </style>

3.5.Register.vue組件 注冊組件

<template>
    <div class="wrapper">
      <!-- header部分 -->
      <header>
        <p>用戶注冊</p>
      </header>
  
      <!-- 表單部分 -->
      <ul class="form-box">
        <li>
          <div class="title">手機(jī)號碼:</div>
          <div class="content">
            <input type="text"placeholder="手機(jī)號碼"/>
          </div>
        </li>
        <li>
          <div class="title">密碼:</div>
          <div class="content">
            <input type="password"  placeholder="密碼" />
          </div>
        </li>
        <li>
          <div class="title">確認(rèn)密碼:</div>
          <div class="content">
            <input type="password" placeholder="確認(rèn)密碼"/>
          </div>
        </li>
        <li>
          <div class="title">用戶名稱:</div>
          <div class="content">
            <input type="text"  placeholder="用戶名稱" />
          </div>
        </li>
        <li>
          <div class="title">性別:</div>
          <div class="content" style="font-size: 3vw">
            <input
              type="radio"
              value="男"
              style="width: 6vw; height: 3.2vw"
            />男
            <input
              type="radio"
              value="女"
              style="width: 6vw; height: 3.2vw"
            />女
          </div>
        </li>
        <li>
            <div class="title">配送地址:</div>
            <div class="content">
              <input type="text"  placeholder="配送地址" />
            </div>
        </li>
      </ul>
  
      <div class="button-login">
        <button>注冊</button>
      </div>
  
      <!-- 底部菜單部分 -->
      <TabMenu></TabMenu>
    </div>
  </template>
  
  <script setup>
  import TabMenu from '../components/TabMenu.vue'
  import { ref, reactive } from "vue";
  import { useRouter} from "vue-router";
  import axios from '../api'
  import qs from "qs";
 
  
  
  </script>
  
  <style scoped>
  /****************** 總?cè)萜?******************/
  .wrapper {
    width: 100%;
    height: 100%;
  }
  
  /****************** header部分 ******************/
  .wrapper header {
    width: 100%;
    height: 12vw;
    background-color: #0097ff;
    color: #fff;
    font-size: 4.8vw;
  
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1000;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  /****************** 表單部分 ******************/
  .wrapper .form-box {
    width: 100%;
    margin-top: 12vw;
  }
  
  .wrapper .form-box li {
    box-sizing: border-box;
    padding: 4vw 3vw 0 3vw;
    display: flex;
    align-items: center;
  }
  
  .wrapper .form-box li .title {
    flex: 0 0 18vw;
    font-size: 3vw;
    font-weight: 700;
    color: #666;
  }
  
  .wrapper .form-box li .content {
    flex: 1;
  }
  
  .wrapper .form-box li .content input {
    border: none;
    outline: none;
    width: 100%;
    height: 4vw;
    font-size: 3vw;
  }
  
  .wrapper .button-login {
    width: 100%;
    box-sizing: border-box;
    padding: 4vw 3vw 0 3vw;
  }
  
  .wrapper .button-login button {
    width: 100%;
    height: 10vw;
    font-size: 3.8vw;
    font-weight: 700;
    color: #fff;
    background-color: #38ca73;
    border-radius: 4px;
  
    border: none;
    outline: none;
  }
  
  .wrapper .button-register {
    width: 100%;
    box-sizing: border-box;
    padding: 4vw 3vw 0 3vw;
  }
  
  .wrapper .button-register button {
    width: 100%;
    height: 10vw;
    font-size: 3.8vw;
    font-weight: 700;
    color: #666;
    background-color: #eee;
    border-radius: 4px;
  
    border: none;
    outline: none;
    border: solid 1px #ddd;
  }
  </style>

3.6.Order.vue組件 訂單確認(rèn)組件

<template>
    <div class="wrapper">
      <!-- header部分 -->
      <header>
        <p>確認(rèn)訂單</p>
      </header>
  
      <!-- 訂單信息部分 -->
      <div class="order-info">
        <h5>訂單配送至:</h5>
        <div class="order-info-address">
          <p>沈陽市渾南區(qū)智慧四街1-121號</p>
          <i class="fa fa-angle-right"></i>
        </div>
        <p>
          苗苗先生 13050213330
        </p>
      </div>
  
      <h3>萬家餃子(軟件園E18店)</h3>
  
      <!-- 訂單明細(xì)部分 -->
      <ul class="order-detailed">
        <li>
          <div class="order-detailed-left">
            <img src="" />
            <p>三鮮餃子 x 2</p>
          </div>
          <p>&#165;30</p>
        </li>
      </ul>
      <div class="order-deliveryfee">
        <p>配送費(fèi)</p>
        <p>&#165;8</p>
      </div>
  
      <!-- 合計(jì)部分 -->
      <div class="total">
        <div class="total-left">&#165;38</div>
        <div class="total-right">確認(rèn)下單</div>
      </div>
    </div>
  </template>
  
  <script setup>
  import { ref, reactive } from "vue"
  import { useRouter, useRoute } from "vue-router"
  import axios from "..//api"
  import qs from "qs"
  
  </script>
  
  <style scoped>
  /****************** 總?cè)萜?******************/
  .wrapper {
    width: 100%;
    height: 100%;
  }
  
  /****************** header部分 ******************/
  .wrapper header {
    width: 100%;
    height: 12vw;
    background-color: #0097ff;
    color: #fff;
    font-size: 4.8vw;
  
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1000;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  /****************** 訂單信息部分 ******************/
  .wrapper .order-info {
    /*注意這里,不設(shè)置高,靠內(nèi)容撐開。因?yàn)榈刂酚锌赡苷坌?/
    width: 100%;
    margin-top: 12vw;
    background-color: #0097ef;
    box-sizing: border-box;
    padding: 2vw;
    color: #fff;
  }
  
  .wrapper .order-info h5 {
    font-size: 3vw;
    font-weight: 300;
  }
  
  .wrapper .order-info .order-info-address {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
  
    font-weight: 700;
    user-select: none;
    cursor: pointer;
    margin: 1vw 0;
  }
  
  .wrapper .order-info .order-info-address p {
    width: 90%;
    font-size: 5vw;
  }
  
  .wrapper .order-info .order-info-address i {
    font-size: 6vw;
  }
  
  .wrapper .order-info p {
    font-size: 3vw;
  }
  
  .wrapper h3 {
    box-sizing: border-box;
    padding: 3vw;
    font-size: 4vw;
    color: #666;
    border-bottom: solid 1px #ddd;
  }
  
  /****************** 訂單明細(xì)部分 ******************/
  .wrapper .order-detailed {
    width: 100%;
  }
  
  .wrapper .order-detailed li {
    width: 100%;
    height: 16vw;
    box-sizing: border-box;
    padding: 3vw;
    color: #666;
  
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  
  .wrapper .order-detailed li .order-detailed-left {
    display: flex;
    align-items: center;
  }
  
  .wrapper .order-detailed li .order-detailed-left img {
    width: 10vw;
    height: 10vw;
  }
  
  .wrapper .order-detailed li .order-detailed-left p {
    font-size: 3.5vw;
    margin-left: 3vw;
  }
  
  .wrapper .order-detailed li p {
    font-size: 3.5vw;
  }
  
  .wrapper .order-deliveryfee {
    width: 100%;
    height: 16vw;
    box-sizing: border-box;
    padding: 3vw;
    color: #666;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 3.5vw;
  }
  
  /****************** 訂單合計(jì)部分 ******************/
  .wrapper .total {
    width: 100%;
    height: 14vw;
  
    position: fixed;
    left: 0;
    bottom: 0;
  
    display: flex;
  }
  
  .wrapper .total .total-left {
    flex: 2;
    background-color: #505051;
    color: #fff;
    font-size: 4.5vw;
    font-weight: 700;
    user-select: none;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  .wrapper .total .total-right {
    flex: 1;
    background-color: #38ca73;
    color: #fff;
    font-size: 4.5vw;
    font-weight: 700;
    user-select: none;
    cursor: pointer;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  </style>

3.7.OrderList.vue 訂單列表組件

<template>
    <div class="wrapper">
      <!-- header部分 -->
      <header>
        <p>我的訂單</p>
      </header>
      <h3>訂單信息:</h3>
      <ul class="order">
        <li>
          <div class="order-info">
            <p>
              <img src="" >
              <span>萬家餃子</span>
            </p>
            <div class="order-info-right">
              <p style="margin-right: 2vw;">&#165;168</p>
              <i v-show="!showDetail" @click="showDetail=!showDetail" class="fa fa-caret-down"></i>
              <i v-show="showDetail" @click="showDetail=!showDetail" class="fa fa-caret-up"></i>
            </div>
          </div>
          <ul class="order-detailet" v-show="showDetail">
            <li>
              <p>蝦仁水餃x 2</p>
              <p>&#165;32</p>
            </li>
            <li>
              <p>配送費(fèi)</p>
              <p>&#165;5</p>
            </li>
            <li>
                <p>下單時間</p>
                <p>2025-08-20 15:33:20</p>
              </li>
          </ul>
        </li>
      </ul>
  
      <!-- 底部菜單部分 -->
      <TabMenu></TabMenu>
    </div>
  </template>
  
  <script setup>
  import { ref,onBeforeMount } from "vue";
  import TabMenu from '../components/TabMenu.vue'
  import axios from '../api'
  import qs from "qs";
  
  let showDetail = ref(false)

  </script>
  
  <style scoped>
  /****************** 總?cè)萜?******************/
  .wrapper {
    width: 100%;
    height: 100%;
    
  }
  
  /****************** header部分 ******************/
  .wrapper header {
    width: 100%;
    height: 12vw;
    background-color: #0097ff;
    color: #fff;
    font-size: 4.8vw;
  
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1000;
  
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  /****************** 歷史訂單列表部分 ******************/
  .wrapper h3 {
    margin-top: 12vw;
    box-sizing: border-box;
    padding: 4vw;
    font-size: 4vw;
    font-weight: 300;
    color: #999;
  }
  
  .wrapper .order {
    width: 100%;
  }
  
  .wrapper .order li {
    width: 95%;
    background-color: rgb(209, 237, 196);
    margin: 1vh auto;
    box-sizing: border-box;
    
  }
  
  .wrapper .order li .order-info {
    box-sizing: border-box;
    padding: 2vw 4vw;
    font-size: 4vw;
    color: #666;
  
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .wrapper .order li .order-info p:first-of-type{
    display: flex;
    align-items: center;
  }
  .wrapper .order li .order-info img{
    width: 10vw;
    height: 10vw;
    margin-right: 2vw;
  }
  .wrapper .order li .order-info .order-info-right {
    display: flex;
  }
  
  .wrapper .order li .order-info .order-info-right .order-info-right-icon {
    background-color: #f90;
    color: #fff;
    border-radius: 3px;
    margin-left: 2vw;
    user-select: none;
    cursor: pointer;
  }
  
  .wrapper .order li .order-detailet {
    width: 100%;
  }
  
  .wrapper .order li .order-detailet li {
    width: 100%;
    box-sizing: border-box;
    padding: 1vw 4vw;
    color: #666;
    font-size: 3vw;
  
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  </style>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容