前端项目搭建

1.使用vite构建vue3

1.1.执行命令

npm create vite

输入项目名字 elm-frontend



选择框架-vue



选择js标准-JavaScript

1.2.项目初始化安装

进入项目目录,安装默认依赖及vue-router,axios,qs,font-awesome

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

2.项目初始化

2.1.删除默认生成的代码

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" href="//cube.elemecdn.com/c/54/38fa90be5da041bbec3945fb82c00png.png">
    <title>饿了么</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

2.2创建路由文件,及修改main.js使用路由

router/index.js

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

const routes = [

]
//创建路由实例
const router = createRouter({
    history: createWebHashHistory(),
    routes
  });
//路由守卫
router.beforeEach( (to, from, next) => {
  // 检查 sessionStorage 中是否有登录信息
  const user = sessionStorage.getItem('user')
  // 如果目标路由需要认证且用户未登录
  if ( !user && to.meta.isAuth ) {
    router.push('/login') // 重定向到登录页
  } else {
    next() // 继续导航
  }
})  
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.创建 axios 实例并封装,配置拦截器

新建api/index.js

import axios from 'axios';
// 创建 axios 实例
const request = axios.create({
    baseURL: 'http://localhost:9999/elm',
    timeout: 3000 // 请求超时时间
});

// 响应拦截器
request.interceptors.response.use(
    response => {
        // 获取响应数据
        const res = response.data;
        //直接返回响应数据
        return res;
    },
    error => {
        // 处理响应错误
        console.log('响应错误:' + 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>发现</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本身的尺寸完全由内容撑起*/
    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.组件开发

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">
        东软河口园区<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>

    <!-- 点餐分类部分 -->
    <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>品质套餐</h3>
      <p>搭配齐全吃得好</p>
      <a>立即抢购 &gt;</a>
    </div>

    <!-- 超级会员部分 -->
    <div class="supermember">
      <div class="left">
        <img src="../assets/super_member.png" />
        <h3>超级会员</h3>
        <p>&#8226; 每月享超值权益</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>
/****************** 总容器 ******************/
.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: "宋体";
  /*此样式是让文本选中状态无效*/
  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; 
}
/****************** 点餐分类部分 ******************/
.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个子元素,通过计算,子元素宽度在16.7 ~ 20 之间,才能保证换两行*/
  width: 18vw;
  height: 20vw;

  display: flex;
  /*弹性盒子主轴方向设为column,然后仍然是垂直水平方向居中*/
  flex-direction: column;
  justify-content: center;
  align-items: center;

  user-select: none;
  cursor: pointer;
}

.wrapper .foodtype li img {
  width: 12vw;
  /*视频讲解时高度设置为12vw,实际上设置为10.3vw更佳*/
  height: 10.3vw;
}

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

/****************** 横幅广告部分 ******************/
.wrapper .banner {
  /**
         * 设置容器宽度95%,然后水平居中,这样两边留白; 
         * 这里不能用padding,因为背景图片也会覆盖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 {
  /*这里也设置容器宽度95%,不能用padding,因为背景色也会充满padding*/
  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>
  /****************** 总容器 ******************/
  .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 {
    /*这里设置为相当定位,成为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;
  
    /*设置成绝对定位,不占文档流空间*/
    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>另需配送费3元</p>
          </div>
        </div>
        <div class="cart-right">
          <!-- 达到起送费 -->
          <div class="cart-right-item-not-enough">
            去结算
          </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>
  /****************** 总容器 ******************/
  .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;
  }
  /*达到起送费时的样式*/
  /*
  .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;
  }
   */
  /*不够起送费时的样式(只有背景色和鼠标样式的区别)*/
  
  .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">手机号码:</div>
          <div class="content">
            <input type="text"  placeholder="手机号码" />
          </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>
  /****************** 总容器 ******************/
  .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">手机号码:</div>
          <div class="content">
            <input type="text"placeholder="手机号码"/>
          </div>
        </li>
        <li>
          <div class="title">密码:</div>
          <div class="content">
            <input type="password"  placeholder="密码" />
          </div>
        </li>
        <li>
          <div class="title">确认密码:</div>
          <div class="content">
            <input type="password" placeholder="确认密码"/>
          </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>
  /****************** 总容器 ******************/
  .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组件 订单确认组件

<template>
    <div class="wrapper">
      <!-- header部分 -->
      <header>
        <p>确认订单</p>
      </header>
  
      <!-- 订单信息部分 -->
      <div class="order-info">
        <h5>订单配送至:</h5>
        <div class="order-info-address">
          <p>沈阳市浑南区智慧四街1-121号</p>
          <i class="fa fa-angle-right"></i>
        </div>
        <p>
          苗苗先生 13050213330
        </p>
      </div>
  
      <h3>万家饺子(软件园E18店)</h3>
  
      <!-- 订单明细部分 -->
      <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>配送费</p>
        <p>&#165;8</p>
      </div>
  
      <!-- 合计部分 -->
      <div class="total">
        <div class="total-left">&#165;38</div>
        <div class="total-right">确认下单</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>
  /****************** 总容器 ******************/
  .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 {
    /*注意这里,不设置高,靠内容撑开。因为地址有可能折行*/
    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;
  }
  
  /****************** 订单明细部分 ******************/
  .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;
  }
  
  /****************** 订单合计部分 ******************/
  .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>配送费</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>
  /****************** 总容器 ******************/
  .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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容