Vue3项目基础准备

vue3脚手架项目基础准备

vue create vue3_cli_project
cd vue3_cli_project 
npm install 
npm run serve

关闭eslint代码检查

vue.config.js(vue-cli创建的项目)

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,	//关闭代码格式化校验工具
  devServer: {
    port: 8080, //修改启动,
    proxy: {
      '/api': {
        target: 'http://localhost:10029',//后端接口地址
        changeOrigin: true,//是否允许跨越
        pathRewrite: {
          '^/api': '/api'//重写,
        }
      }
    }
  },
  configureWebpack: {
    //关闭 webpack 的性能提示
    performance: {
      hints: false
    }
  },
})

常用依赖安装

element-plus包括其图标库

npm install element-plus @element-plus/icons-vue

css底板 该css文件引入到main.js中

* {
  box-sizing: border-box;
  font-family: PingFang SC, tahoma, arial, 'Microsoft Yahei', 'Hiragino Sans GB', '\5b8b\4f53', sans-serif;
}

body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
pre,
form,
fieldset,
legend,
button,
input,
textarea,
th,
td {
  margin: 0;
  padding: 0;
}

body,
button,
input,
select,
textarea {
  font: 12px/1.5tahoma, arial, \5b8b\4f53;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: 100%;
}

address,
cite,
dfn,
em,
var {
  font-style: normal;
}

code,
kbd,
pre,
samp {
  font-family: couriernew, courier, monospace;
}

small {
  font-size: 12px;
}

ul,
ol {
  list-style: none;
}

a {
  text-decoration: none;
  outline: none;
}

sup {
  vertical-align: text-top;
}

sub {
  vertical-align: text-bottom;
}

legend {
  color: #000;
}

fieldset,
img {
  border: 0;
}

button,
input,
select,
textarea {
  font-size: 100%;
  outline: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

body {
  color: #000;
  background-color: #fff;
}

body, html {
  width: 100%;
  height: 100%;
}

#app {
  height: 100%;
}

/* a,a:hover,a:active,a:visited,a:link,a:focus{
  color: #000;
} */

全量导入element-plus模块和icon图标组件

//main.js
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'	
import * as ElementPlusIconsVue from '@element-plus/icons-vue'	//element-icons
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'   //国际化

const app = createApp(App)
app.use(router)


app.use(ElementPlus, { locale: zhCn })
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

app..mount('#app')

scss

scss看个人使用习惯,酌情添加

npm install sass sass-loader node-sass --save-dev vue-style-loader --sava-dev

echarts

npm install echarts --save

axios

npm install axios --save

App.vue

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

<style lang="scss">
* {
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
  list-style: none;
  text-decoration: none;
  outline: none;
  min-height: 100vh;
}
</style>

router

router/index.js

import { createRouter, createWebHistory } from 'vue-router'
import { ElMessage } from 'element-plus'
import { h } from 'vue';

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: () => import('../views/LayoutView.vue')
    },
    {
      path: '/login',
      name: '登录页',
      component: () => import('../views/LoginView.vue')
    },
    {
      path: '/',
      name: "框架页",
      component: () => import('../views/LayoutView.vue'),
      redirect: '/home',
      children: [
        {
          path: 'home',
          name: "定位",
          component: () => import('../components/Map.vue')
        },
        {
          path: "ais",
          name: "AIS船只信息",
          component: () => import('../components/Ais.vue')
        },
        {
          path: "echarts",
          name: "Echarts图形绘制",
          component: () => import('../components/Chart.vue')
        },
      ]
    }

  ]
})

//登录状态时间的检查
// 设置登录过期时间(一天)86400000 
let expire = 43200000;

//路由守卫    
//全局守卫,登录拦截
//进行路由拦截:当没有登陆标识,直接打回登陆页面,如何避免退回到 登陆页呢?
router.beforeEach((to, from, next) => {
  // 从本地缓存中获取保存的 token 信息
  const tokenObj = JSON.parse(window.localStorage.getItem('isLogin'))
  if (to.path === "/login") {
    next()
  } else {
    // 如果没有token,强制跳转到登录页面;如果有,则判断token时间是否过期
    if (!tokenObj || !tokenObj.token) {
      next('/login')
    } else {
      let date = new Date().getTime();
      // 当前时间 - token中的登录时间 > 设置的过期时间,为过期;则清除token,并强制跳转至登录页
      // 反之为有效期,则放行
      if (date - tokenObj.startTime > expire) {
        window.localStorage.removeItem('isLogin');
        next('/login')
        ElMessage({
          message: h('p', null, [
            h('span', null, '登录状态过期'),
            h('i', { style: 'color: teal' }, '请重新登录!'),
          ]),
        })
      } else {
        next();
      }
    }
  }
});

export default router

封装axios api层

该部分转载于程序员青戈

参考文章链接


基础登录页面

<template>
    <div class="login-body">
        <div class="login-panel">
            <div class="login-title">用户登录</div>
            <el-form :model="formData" :rules="rules" ref="formDataRef">
                <el-form-item prop="username">
                    <el-input placeholder="请输入账号" v-model="formData.username" size="large" type="text">
                        <template #prefix>
                            <el-icon>
                                <User />
                            </el-icon>
                        </template>
                    </el-input>
                </el-form-item>
                <el-form-item prop="password">
                    <el-input placeholder="请输入密码" v-model="formData.password" size="large" type="password"
                        @keyup.enter.native="login()">
                        <template #prefix>
                            <el-icon>
                                <Lock />
                            </el-icon>
                        </template>
                    </el-input>
                </el-form-item>
                <el-form-item label="">
                    <el-button type="primary" style="width: 100%;" @click="login()" size="large">登录</el-button>
                </el-form-item>
            </el-form>
        </div>
    </div>
</template>

<script setup>
import { ref, reactive, } from 'vue'
import { ElMessage } from 'element-plus';
import request from '@/utils/request';
import { useRouter } from 'vue-router';

// const checkCodeUrl = "api/checkCode?" + new Date().getTime();
//表单
const formDataRef = ref();
let formData = reactive({
    username: "",
    password: ""
});
const rules = {
    username: [{
        required: true,
        message: "请输入用户名"
    }],
    password: [{
        required: true,
        message: "请输入密码"
    }],
}

const router = useRouter();

const login = () => {
    var form_obj = JSON.parse(JSON.stringify(formData));
    // console.log(form_obj);

    request.get("/login/"+form_obj.username + "/" + form_obj.password).then(res => {
        if (res) {
            ElMessage({
                message: '登录成功',
                type: 'success',
            })

            let tokenObj = { token: " isLogin", startTime: new Date().getTime() };
            window.localStorage.setItem("isLogin", JSON.stringify(tokenObj));
            localStorage.setItem("username", JSON.parse(JSON.stringify(formData.username)));

            router.push("/home");

        } else {
            ElMessage.error('账号或密码错误!!!登录失败!!!')
        }
    });
};
</script>

<style lang="scss" scoped >
.login-body {
    background: url("../assets/images/三门峡.png") no-repeat center center;
    // background: url("../assets/zqn01.jpg") no-repeat center center;
    height: 100%;
    width: 100%;
    background-size: cover;
    position: absolute;
    left: 0;
    top: 0;

    .login-panel {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        margin: auto;

        padding: 25px;
        width: 26%;
        min-width: 460px;
        height: 30%;
        min-height: 300px;
        background: rgba(255, 255, 255, 0.6);
        border-radius: 5%;
        box-shadow: 2px 2px 10px #ddd;

        .login-title {
            font-size: 22px;
            text-align: center;
            margin-bottom: 22px;
        }
    }
}
</style>

框架页模板

<script setup >
import { h, ref } from 'vue';
import { useRouter, RouterView, useRoute } from 'vue-router';
import { ArrowRight } from '@element-plus/icons-vue';
import { ElNotification, ElMessageBox, ElMessage } from 'element-plus';
import screenfull from 'screenfull'

const SetFullScreen = () => {
    if (!screenfull.isEnabled) {
        return false;
    }
    screenfull.toggle()
}

const router = useRouter();
const route = useRoute();
let local_username = localStorage.getItem("username");

const outLogin = () => {
    ElMessageBox.confirm(
        '确定退出当前登录状态吗?', 'Warning',
        {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
        }
        ).then(() => {
            router.push("/login");
            ElNotification.success({
                title: 'Success',
                message: h('i', { style: 'color: teal' }, '成功退出当前用户登录状态'),
                offset: 100,
            })
            window.localStorage.removeItem('isLogin');
            window.localStorage.removeItem('username');
        }).catch(() => {
            ElMessage({
                type: 'info',
                message: '已取消退出操作',
            })
        })
}

</script>

<template>
    <el-container class="layout-container-demo" style="min-height: 100vh;">
        <el-aside style="width: 14%;">
            <el-menu :default-openeds="['1', '2']"
                style="min-height: 100%; overflow: hidden; box-shadow:2px 0 6px rgb(0 21 41 / 35%);"
                background-color="rgb(48,65,86)" :collapse-transition="false" text-color="white" active-text-color="#ffd04b"
                :router="true" :default-active="route.path">

                <el-menu-item index="/home">
                    <el-icon>
                        <Location />
                    </el-icon>&nbsp;&nbsp;&nbsp;&nbsp;
                    <span>首页</span>
                </el-menu-item>

                <el-menu-item index="/ais">
                    <el-icon>
                        <Ship />
                    </el-icon>&nbsp;&nbsp;&nbsp;&nbsp;
                    <span>Ais</span>
                </el-menu-item>

                <el-menu-item index="/echarts">
                    <el-icon>
                        <Histogram />
                    </el-icon>&nbsp;&nbsp;&nbsp;&nbsp;
                    <span>Echarts</span>
                </el-menu-item>

            </el-menu>
        </el-aside>

        <el-container>
            <el-header style="font-size: 12px;border-bottom: 1px solid #ccc; text-align: right;display: flex;">
                <el-breadcrumb :separator-icon="ArrowRight" style="flex: 1; padding-top:25px;">
                    <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
                    <el-breadcrumb-item :to="{ path: '/ais' }">AIS船舶信息</el-breadcrumb-item>
                    <el-breadcrumb-item :to="{ path: '/echarts' }">Echarts</el-breadcrumb-item>
                </el-breadcrumb>

                <el-icon @click="SetFullScreen()" size="25" style="margin-top: 18px;cursor: pointer;">
                    <FullScreen />
                </el-icon>

                <div class="toolbar" style="width: 80px;">
                    <el-dropdown>
                        <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" :size="40"
                            style="margin-top: 5px; "></el-avatar>
                        <template #dropdown>
                            <el-dropdown-menu>
                                <div style="text-align: center; padding: 10px 10px;"><b><i>{{ local_username }}</i></b>
                                </div>
                                <el-dropdown-item @click="outLogin()">退出登录</el-dropdown-item>
                            </el-dropdown-menu>
                        </template>
                    </el-dropdown>

                </div>
            </el-header>

            <el-main>
                <RouterView></RouterView>
            </el-main>
        </el-container>

    </el-container>
</template>

<style lang='scss' scoped>
.layout-container-demo .el-header {
    position: relative;
    color: var(--el-text-color-primary);
}

.layout-container-demo .el-aside {
    color: var(--el-text-color-primary);
    background: var(--el-color-primary-light-8);
}

.layout-container-demo .el-menu {
    border-right: none;
}

.layout-container-demo .el-main {
    padding: 0;
}

.layout-container-demo .toolbar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    right: 20px;
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值