官网项目完成总结

Posted 接着奏乐接着舞。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了官网项目完成总结相关的知识,希望对你有一定的参考价值。

目录

前言:

1.总结(个人感受)

2.rem适配[1920*1080设计图]

2.1 在static目录下新建js文件 page:flexble

2.2  在assets文件夹下新建css文件

2.3 在nuxt.config.js设置配置

2.4 页面中使用

3. 登录注册页

 封装成一个组件(使用cookie):

4.seo优化

需求:

 实现:

 在页面里面:

 nuxt官网地址:

5.nuxt 使用VueAwesomeSwiper插件,展示轮播及缩略图

6.IntersectionObserver API 使用教程

7.IE11的CSS兼容性问题

8.pc端网页屏幕自适应适配方案(rem)

9.后台返回图形验证码 前端如何处理

10.nuxt中文官网

11.好用的日期处理插件day.js


前言:

开发完成的这个项目是基于nuxt.js框架typescript语法的服务端渲染项目,具有良好的SEO体验。目前项目处于预发布阶段。开发用时约30天,测试约15天,共约26个页面,接口约50个,封装了一些公共组件,也用到一些三方组件,如seiper轮播图插件,加密插件、day.js插件。

兼容:项目兼容几乎所有浏览器,IE兼容到11

重点功能:SEO搜索引擎优化直播功能直播回顾功能、权限验证


 

1.总结(个人感受)

1.对于UI页面的精确度已经达到了惨绝人寰的程度,UI人员精确到1px就罢了,今天跑过来说调整一下这个地方,明天又跑来说这个地方再改下…(绝对是巨坑,最坑没有之一,浪费LZ大量的时间和精力,无力吐槽…)

2.nuxt.js框架的使用,是有坑的,比如说获取window对象,比如获取vue对象,还有个大坑就是,因为是服务端渲染。一般基地址就是两个,一个开发地址一个线上地址,但是在这里至少需要3个地址,一个开发的,一个客户端请求的,一个服务器请求的,要做判断区分。

3.项目中的首页大量使用seiper轮播图插件,高版本比如7兼容性不好,项目用的4,但是也存在问题,一个巨坑是缩略图轮播,thumbs老是报错(初始化正常,切换tab栏回去的时候报错,刷新页面就好),说找不到addclass,位置在init 7700多行,死活排查不出来,最后我是通过在错误页面强行使用this.$router.go(0)刷新页面。

4.关于三方插件,如时间格式转换的,推荐day.js插件,非常好用。再比如加密插件,使用的是crypto.js加密插件,使用也是非常简单,存的是时候加密一下,取出来的时候再解密一下

5.使用如elementUI组件库的时候,要修改它们样式,记得使用::v-deep 


2.rem适配[1920*1080设计图]


2.1 在static目录下新建js文件 page:flexble

(function flexible (window, document) 
  var docEl = document.documentElement
  var dpr = window.devicePixelRatio || 1

  // adjust body font size
  function setBodyFontSize () 
    if (document.body) 
      document.body.style.fontSize = (12 * dpr) + 'px'
    
    else 
      document.addEventListener('DOMContentLoaded', setBodyFontSize)
    
  
  setBodyFontSize();

  // set 1rem = viewWidth / 10
  function setRemUnit () 
    // var rem = docEl.clientWidth / 10
    // docEl.style.fontSize = rem + 'px'

    var width = docEl.getBoundingClientRect().width
    // 当屏幕超过1920px以后就不在随着屏幕的变大而变大了
    if (width / dpr > 1920) 
      width = 1920 * dpr
    
    // 当屏幕小于1300px以后就不再随着屏幕的变小而变小了
    // if (width / dpr < 1300) 
    //   width = 1300 * dpr
    // 
    var rem = width / 19.2
    docEl.style.fontSize = rem + 'px'
     window.rem = rem
  

  setRemUnit()

  // reset rem unit on page resize
  window.addEventListener('resize', setRemUnit)
  window.addEventListener('pageshow', function (e) 
    if (e.persisted) 
      setRemUnit()
    
  )

  // detect 0.5px supports
  if (dpr >= 2) 
    var fakeBody = document.createElement('body')
    var testElement = document.createElement('div')
    testElement.style.border = '.5px solid transparent'
    fakeBody.appendChild(testElement)
    docEl.appendChild(fakeBody)
    if (testElement.offsetHeight === 1) 
      docEl.classList.add('hairlines')
    
    docEl.removeChild(fakeBody)
  
(window, document))

2.2  在assets文件夹下新建css文件

@use "sass:math";

$base-width: 1920;
$base-font_size: math.div(1920 , 19.2);

@function rem($px)
  @return  math.div($px , $base-font_size) * 1rem;
  // @return $px * 1px


/**  字体 **/
$large-font_size: 16px ;
$medium-font_size: 14px;
$small-font_size: 12px;


$title-size: rem(44);

/** 颜色 **/
$primary-color: #C90000;
$bottom-color: #D10000;


$oss_url:'//oss-guanwang.yuceyingjia.com/';
$base-oss_url: '//oss-guanwang.yuceyingjia.com/newGWWeb/';


:export 
  ossUrl: $base-oss_url;

2.3 在nuxt.config.js设置配置

  // 引入全局scss 变量
  styleResources: 
    // your settings here
    scss: ['./assets/css/variables.scss'],
    hoistUseStatements: true  // Hoists the "@use" imports. Applies only to "sass", "scss" and "less". Default: false.
  ,
script: [
       src: '/js/page-flexible.js'
    ]

2.4 页面中使用

font-size:rem(15)


3. 登录注册页

登录、注册、忘记密码(重置)均在一个页面上,有密码校验、本地持久化,记住密码、短信验证码、加密、路由跳转等功能

 

 

 


 封装成一个组件(使用cookie):

<template>
  <div>
    <div class="container1">
     $route.query.zc
      <!-- 左侧注册区域 -->
      <div class="left">
       <div class="zhuce">
          <!-- logo title -->
        <div class="logo"><img src="~/assets/img/login/LOGO.png" alt="" /></div>
        <!-- 注册表单区域 -->
        <div class="formTable">
          <el-form :rules="rules" ref="formData" :model="formData">
            <el-form-item prop="mobile" v-show="wangji || !forGet">
              <el-input
                v-model="formData.mobile"
                placeholder="请输入您的手机号"
              >
              </el-input>
            </el-form-item>

             <el-form-item
            prop="email"
            class="article"
            v-if="cLogin || forGet "
            v-show="wangji|| !forGet"
          >
            <el-input

              v-model="formData.email"
              maxlength="40"
              placeholder="手机验证码"
              class="input"
            >
            </el-input>

            <span class="span" @click="getCMS" v-if="cLogin ">
              <span v-show="isC == false">获取验证码</span>
              <span v-show="isC == true">
                isActive ? "重新获取" : count + "s"
              </span></span
            >
          </el-form-item>



            <!-- <el-form-item prop="Yzm" v-if="cLogin || forGet" v-show="wangji|| !forGet"> -->
            <el-form-item prop="Yzm" v-if="imgUrl">
            <el-input
              v-model="formData.Yzm"
              maxlength="40"
              placeholder="图形验证码"
              class="input"
            >
            </el-input>
            <img :src="imgUrl" alt=""  class="img"/>
          </el-form-item>

         <el-form-item prop="miMa" v-if="!forGet">
              <el-input
                v-model="formData.miMa"
                placeholder="您的账号密码"
              ></el-input>
            </el-form-item>

          <!-- 修改密码区域 forGet控制 -->
           <el-form-item  prop="newPassword" v-if="!wangji && forGet">
                <el-input type="password" placeholder="请输入新密码" v-model="formData.newPassword"></el-input>
            </el-form-item>
            <el-form-item  prop="repPassword" v-if="!wangji&& forGet">
                <el-input type="password"  placeholder="请输入确认密码" v-model="formData.repPassword"></el-input>
            </el-form-item>
          <!-- 记住密码、忘记密码区域 -->
          <div class="middle" v-if="!cLogin">
            <div class="left">
              <el-checkbox v-model="checked">记住密码</el-checkbox>
            </div>
            <div class="right" v-if="!forGet"><span @click="missCode">忘记密码</span></div>
          </div>

            <!-- 提交表单按钮 -->
            <el-form-item align="center" class="div" v-if="!wangji">
              <el-button
                size="mini"
                type="primary"
                :loading="loading"
                @click="submitForm('formData')"
                >buttonText</el-button
              >
            </el-form-item>
            <el-form-item align="center" class="div" v-else>
              <el-button
                size="mini"
                type="primary"
                :loading="loading"
                @click="next"
                >下一步</el-button
              >
            </el-form-item>
            <!-- 底部 还没有账号? 立即注册区域 -->
            <div class="bottom" v-if="!wangji" >
              <span class="left">cLogin ? '已有账号?':'还没有账号?'</span>
              <span class="right" @click="clickLogin">cLogin ? '立即登录':'立即注册'</span>
            </div>
          </el-form>
        </div>
       </div>
      </div>
      <!-- 右侧图片区域 -->
      <div class="right">
        <img src="~/assets/img/login/bg.png" alt="" />
        <div class="img"><img src="~/assets/img/login/login_slogin.png" alt=""></div>
        <div class="zhezhao"></div>
        <!-- <div class="textIMG">
          <h3>让投资更简单更理性</h3>
          <p>Make investment simpler and</p>
          <p>more rational</p>
        </div> -->
      </div>
      </div>

  </div>
</template>

<script>
import CryptoJS from "crypto-js";//加密

import  isvalidUsername, isvalidMobile, isvalidEmail, code, password  from '@/utils/validate'
import axios from 'axios'
// import  Alert  from 'element-ui'

const TIME_COUNT = 60
export default 
  props: 
    loading:  // 是否点击确定按钮
      type: Boolean,
      default: false
    
  ,

  methods: 
    //提交表单
    submitForm (formName) 
      this.$refs[formName].validate((valid) => 
        if (valid) 
          // 校验通过,提交数据
          this.getIMGCode()//调图形验证码,默认为空
         if(this.forGet)
          //  重置密码
           this.getReset()
         else
           if(this.cLogin===false)
          //  做登录
          this.getLogin ()
         else
          //  做注册
          this.getZhuCe ()
         
         
         else 
          // 验证不通过
          return false
        
      )
    ,
    // 封装的倒计时效果
    getCMS () 
      this.isC = true

      if (!this.timer) 
        this.count = TIME_COUNT
        this.isActive = false
        this.getCMSCode() //获取验证码(ip)----60秒内不能重复发送--
        this.timer = setInterval(() => 
          if (this.count > 0 && this.count <= TIME_COUNT) 
            this.count--
           else 
            this.isActive = true
            clearInterval(this.timer)
            this.timer = null
          
        , 1000)
      
    ,
    // 做登录
    async getLogin () 
      let data1 = await axios.post("https://app-gw-test.365ycyj.com/UserApi/50000/UserLogin", 
        username: this.formData.mobile,
        password: this.formData.miMa,

      )
      console.log(data1, 'login--------------11111111111111111')
      if(data1.data.Msg == 'success')
        this.$message(
          message: '恭喜登录成功!',
          type: 'success'
        );
        console.log(data1.data,'wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww');
        // 如果记住密码的话
        if(this.checked)
          localStorage.setItem("rememberPsw",true)
          let cipherText = CryptoJS.AES.encrypt(this.formData.miMa, "secretkey123").toString();
           this.$store.commit('UPDATE_ALL_STATE',accessToken:data1.data.Data.Token,userInfo:this.formData.mobile,pwd:this.formData.miMa)
            this.$cookies.set("accessToken",data1.data.Data.Token,maxAge:60*60*24*3) //保存3天
            this.$cookies.set("userInfo",this.formData.mobile,maxAge:60*60*24*3) //保存3天
            this.$cookies.set("pwd",cipherText,maxAge:60*60*24*3) //保存3天
        else
          // 不记住密码,不保存密码
          localStorage.setItem("rememberPsw",false)
          let cipherText = CryptoJS.AES.encrypt(this.formData.miMa, "secretkey123").toString();
          this.$store.commit('UPDATE_ALL_STATE',accessToken:data1.data.Data.Token,userInfo:this.formData.mobile)
          // this.$cookies.set("pwd",'') //
          // this.$cookies.set("accessToken",'') //
          this.$cookies.set("accessToken",data1.data.Data.Token,maxAge:60*60*4) //保存4小时
          this.$cookies.set("userInfo",this.formData.mobile,maxAge:60*60*4) //保存4小时
          this.$cookies.set("pwd",cipherText,maxAge:60*60*4) //保存4小时
            // this.$cookies.set("accessToken",data1.data.Data.Token,maxAge:60*60*4) //保存4小时
            // this.$cookies.set("userInfo",this.formData.mobile,maxAge:60*60*4) //保存4小时
        
         this.$router.push(this.$route.query.return_url || '/') //登录后跳转到原位置或者首页
        // this.$store.commit('UPDATE_ALL_STATE',accessToken:data1.data.Data.Token2,userInfo:this.formData.mobile)
        // this.$cookies.set("accessToken",data1.data.Data.Token2,maxAge:60*60*24*3) //保存3天
        // this.$cookies.set("userInfo",this.formData.mobile,maxAge:60*60*24*3) //保存3天
        // this.$router.go(0); //刷新页面
      else 
        this.$message.error(data1.data.Msg);
        // this.$router.push(path: '/', query:id: 3);
      

    ,
    // 做注册
      async getZhuCe () 
      let data1 = await axios.post("https://app-gw-test.365ycyj.com/UserApi/50000/MReg", 
        tel: this.formData.mobile,
        pwd: this.formData.miMa,
        smscode:this.formData.email,
        app: '官网',
        issendmsg: '1',
        qudaotype: '2',
        clienttype: '0',
        mac: '',
        clientagent: 'pc_ycyj',
        qudaoma: '',

      )
      console.log(data1, 'login--------------11111111111111111')
      if(data1.data.Msg == 'success')
        this.$message(
          message: '恭喜您注册成功!请登录',
          type: 'success'
        );
        this.cLogin = false //去登陆
        // 如果是注册的话,那么登录后应该下载软件
        this.isDownPC = true
        // this.$store.commit('UPDATE_ALL_STATE',accessToken:data1.data.Data.Token2,userInfo:this.formData.mobile)
        // this.$cookies.set("accessToken",data1.data.Data.Token2,maxAge:60*60*24*3) //保存3天
        // this.$cookies.set("userInfo",this.formData.mobile,maxAge:60*60*24*3) //保存3天
        // this.formData.mobile = '' // 关闭弹框
        // this.$router.go(0); //刷新页面
      else 
        this.$message.error(data1.data.Msg);
      

    ,
    // 接口--获取短信验证码--ip限制--默认为空GetSMSCodeByWeb
    async getCMSCode()
    let data1 = await axios.post("https://app-gw-test.365ycyj.com/UserApi/50000/GetSMSCodeByWeb", 
       tel: this.formData.mobile || '15805494663',
       imgcode:this.formData.Yzm ||'',
       yingjiatype:'0',
       type:'0'
      )
      console.log(data1,'ceshi  短信验证码……………………………………………………');
        
    ,
    // 接口--获取图形验证码--ip限制
    async getIMGCode()
    let data1 = await axios.post("https://app-gw-test.365ycyj.com/UserApi/50000/GetImgCodeByWeb")
    if(data1.Data)
      this.imgUrl = data1.Data.ImgSrc
    
    ,
    // 做忘记密码--密码重置
    async getReset () 
      let data1 = await axios.post("https://app-gw-test.365ycyj.com/UserApi/50000/ResetPassword", 
        tel: this.formData.mobile,
        password: this.formData.newPassword,
        smscode:this.formData.email,
        clienttype: '0',
      )
      console.log(data1, 'getReset--------------11111111111111111')
      if(data1.data.Msg == 'success')
        this.$message( 
          message: '恭喜您重置成功!',
          type: 'success'
        );
        // 如果记住密码的话
        if(this.checked)
           this.$store.commit('UPDATE_ALL_STATE',accessToken:data1.data.Data.Token,userInfo:this.formData.mobile)
            this.$cookies.set("accessToken",data1.data.Data.Token,maxAge:60*60*24*3) //保存3天
            this.$cookies.set("userInfo",this.formData.mobile,maxAge:60*60*24*3) //保存3天
        else
          this.$store.commit('UPDATE_ALL_STATE',accessToken:data1.data.Data.Token,userInfo:this.formData.mobile)
            this.$cookies.set("accessToken",data1.data.Data.Token,maxAge:60*60*4) //保存4小时
            this.$cookies.set("userInfo",this.formData.mobile,maxAge:60*60*4) //保存4小时
        
         this.$router.push(this.$route.query.return_url || '/') //登录后跳转到原位置或者首页

        // this.cLogin = false //去登陆
        // this.$store.commit('UPDATE_ALL_STATE',accessToken:data1.data.Data.Token2,userInfo:this.formData.mobile)
        // this.$cookies.set("accessToken",data1.data.Data.Token2,maxAge:60*60*24*3) //保存3天
        // this.$cookies.set("userInfo",this.formData.mobile,maxAge:60*60*24*3) //保存3天
        // this.formData.mobile = '' // 关闭弹框
        // this.$router.go(0); //刷新页面
      else 
        this.$message.error(data1.data.Msg);
      

    ,
    // missCode+clickLogin做忘记密码、注册、登录切换效果
    missCode()
      this.wangji = true
      this.forGet=!this.forGet
      this.cLogin = true
    ,
    clickLogin()
      this.cLogin=!this.cLogin
      this.forGet = false

    ,
    // 点击下一步
    next()
      this.wangji = false
    


  ,
 
  data () 
    var checkNickName = (rule, value, callback) => 
      if (!value) 
        callback(new Error('姓名不能为空'))
       else if (value.length > 30) 
        callback(new Error('最多30个字符'))
       else 
        callback()
      
    
    var checkMobile = (rule, value, callback) => 
      if (!value) 
        callback(new Error('手机号不能为空'))
       else if (!isvalidMobile(value)) 
        callback(new Error('手机号不合法'))
       else 
        callback()
      
    
    var checkCode = (rule, value, callback) => 
      if (!value) 
        callback(new Error('验证码不能为空'))
       else if (!code(value)) 
        callback(new Error('验证码不合法'))
       else 
        callback()
      
    

    var checkPass = (rule, value, callback) => 
      if (value === '') 
        callback(new Error('密码不能为空'))
      
      else if (!password(value)) 
        callback(new Error('密码不合法'))
      
      else 
        callback()
      
    

    var checkYZM = (rule, value, callback) => 
      if (!value) 
        callback(new Error('图形验证码不能为空'))
       else if (!code(value)) 
        callback(new Error('图形验证码不合法'))
       else 
        callback()
      
    
    // 校验新密码
    const validatePassword = (rule, value, callback) => 
        // console.log('value', value)
        if(value.length < 6) 
          callback(new Error('新密码不能少于6位'))
        else 
          callback()
        
    ;

    // 校验确认密码是否一致
    const validateRepPassword = (rule, value, callback) => 
        if(value !== this.formData.newPassword) 
            callback(new Error('两次输入的密码不一致'))
        else 
            callback()
        
    ;
    return 
      rules: 
        mobile: [ required: true, validator: checkMobile, trigger: 'blur' ],
        email: [ required: true, validator: checkCode, trigger: 'blur' ],
        miMa: [ required: true, validator: checkPass, trigger: 'blur' ],
        Yzm: [ required: true, validator: checkYZM, trigger: 'blur' ],
        newPassword: [
           required: true, message: '新密码不能为空', trigger: 'blur' ,
           validator: validatePassword, trigger: 'blur' 
        ],
        repPassword: [
           required: true, message: '确认密码不能为空', trigger: 'blur' ,
           validator: validateRepPassword, trigger: ['change', 'blur'] 
        ]
      ,
      ip: '1.1.1.1',
      area: '北京市',
      brower: 'chrome',
      os: 'windows7',
      // mobile:this.formData.mobile,
      imgUrl: "",
      formData: 
        mobile:this.$cookies.get('userInfo')? CryptoJS.AES.decrypt(this.$cookies.get('userInfo'), "secretkey123").toString(CryptoJS.enc.Utf8):'',
        email: '',
        miMa:this.$cookies.get('pwd')? CryptoJS.AES.decrypt(this.$cookies.get('pwd'), "secretkey123").toString(CryptoJS.enc.Utf8):'',//解密
        code: "",
        Yzm: '',
        newPassword:'',
        repPassword:''
      ,
      isActive: false,
      count: 0,
      timer: null,
      isC: false,
      cLogin:false,//切换登录和注册
      checked:false,//是否记住密码
      forGet:false,//是否点击忘记密码
      wangji:false,//忘记密码密码
      isDownPC:false,//是不是下载pc软件
      borHeight:1000,//浏览器可视区域的高度
    
  ,
  

  async created() 
    // 如果是点击注册,那么页面显示注册
    if(this.$route.query.zc == 1)
      this.cLogin = true
    
    // 这里测试同一ip超过5次哪个 ,有数据就会显示图形验证码
    // const data1 = await this.$api.UserApi.GetImageVeriFicationCode();
    // this.imgUrl = data1.ImgSrc
      // this.getIMGCode()  //这个是获取图形验证码、ip限制的
    
  ,
   mounted () 
     if(localStorage.getItem("rememberPsw") == 'true')
      this.checked = true
    else if(localStorage.getItem("rememberPsw") == 'false')
      this.checked = false
    
    
  ,
  // 登录按钮的文字显示
  computed: 
    buttonText() 
      if(this.forGet === true)
        return "确定"
      else
        if(this.cLogin)
        return "快速注册领取3天VIP"
      else if(!this.cLogin)
        return "立即登录"
      
      


    
  


</script>

<style lang="scss" scoped>

.span 
  position: absolute;
  top: 16.2%;
  right: 8%;
  color: #c90000;
  font-family: PingFang SC;
  font-size: rem(18);

// 修改提交按钮的样式
.el-button
  outline: 0 none;
  border: 0 none;
  width: rem(600);
  height: rem(60);
  background: #C90000;
  margin-top: rem(50);
  font-size: rem(30);
  font-family: PingFang SC;
font-weight: 600;
color: #FFFFFF;

// 修改输入框的颜色
::v-deep .el-input__inner
  background-color: #f6f6f6;

// 修改输入框的边框样式
::v-deep .el-input__inner
  border: 1px solid rgba(255,255,255,0);
  border-bottom: 2px solid #f6f6f6;
  font-size: rem(20);
  color: #1E1E1E;
  margin: rem(20) 0;
  border-radius: 0;

// 修改校验错误时的样式
::v-deep .el-form-item.is-error .el-input__inner, .el-form-item.is-error .el-input__inner:focus, .el-form-item.is-error .el-textarea__inner, .el-form-item.is-error .el-textarea__inner:focus, .el-message-box__input input.invalid, .el-message-box__input input.invalid:focus 

    border-color: #f6f6f6;
    border-bottom: 2px solid #C90000;

// 修改校验错误时弹出字体
::v-deep .el-form-item__error 
    color: #C90000;
    font-size: rem(16);


// 修改选中记住密码样式
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner, .el-checkbox__input.is-indeterminate .el-checkbox__inner 
    background-color: #C90000;
    border-color: #C90000;

::v-deep .el-checkbox__input.is-checked+.el-checkbox__label 
    width: rem(94);
    height: rem(23);
    font-size: rem(16);
    font-family: PingFang SC;
    font-weight: 400;
    color: #1E1E1E;

::v-deep .el-checkbox
  width: rem(94);
    height: rem(23);
    font-size: rem(16);
    font-family: PingFang SC;
    font-weight: 400;
    color: #1E1E1E;

::v-deep .el-checkbox__label 

    font-size: rem(16);



.container1 
  

  height:100%;
  width:100%;
  display: flex;
  box-sizing: border-box;
  .left 
    flex: 3;
    overflow: hidden;
    width: 70%;
    background-color: #f6f6f6;
    .logo 
      width: rem(296);
      height: rem(70);
      margin: rem(90) rem(422) rem(60);
    
    .formTable
      width: rem(600);
      height: 100%;
      margin: 0 rem(270);
      .middle
        display: flex;
        justify-content: space-between;
        .right
          text-align: right;
          width: 93px;
          height: rem(23);
          font-size: rem(16);
          font-family: PingFang SC;
          font-weight: 400;
          color: #C90000;
        

        .left
          width: rem(94);
          height: rem(23);
          font-size: rem(16);
          font-family: PingFang SC;
          font-weight: 400;
          color: #1E1E1E;
        
      

      .bottom
        width: rem(238);
        height: rem(23);
        margin:rem(30) auto;
        line-height: rem(23);
        text-align: center;
        .left
          color: #1F1F1F;
          font-size: rem(14);
        
        .right:hover
          cursor: pointer;
        
        .right
          color: #C90000;
          font-size: rem(16);
          font-family: PingFang SC;
          font-weight: 700;
        
        
    
  
  .right 
    position: relative;
    width: 100%;
    flex: 2;
    overflow: hidden;
    height: 100%;
    .textIMG
      position: absolute;
      top: 20%;
      left: 0;
      h3
        margin-left: rem(30);
        font-size: rem(26);
        font-family: PingFang SC;
        font-weight: 600;
        color: #C90000;
      
      p
        margin-left: rem(30);
        margin-top: rem(10);
        font-size: rem(20);
        font-family: D-DIN;
        font-weight: bold;
        color: #3B3B3B;
      
    
      .img
        position: absolute;
        top: rem(200);
        left: rem(60);
        width: rem(448);
        height: rem(138);
        z-index: 2;
        img
          width: 100%;
          height: 100%;
        
      
      .zhezhao
        position: absolute;
        height: 100%;
        top: 0;
        left: 0;
        width: rem(140);
        background-color: #f2f2f2;
        opacity: 0.7;
        z-index: 1;
      
    img 
      width: 100%;
      height: 100%;
    
  
    .img 
    overflow: hidden;
    width: rem(200);
    height: rem(50);
    position: absolute;
    bottom: 23%;
    right: 0%;
  

</style>

4.seo优化

需求:

 实现:

其实就是设置nuxt.config.js里面的config中设置全局head对象,也可在每个页面的head中设置

 在页面里面:

<template>
  <h1> title </h1>
</template>
<script>
  export default 
    data() 
      return 
        title: 'Home page'
      
    ,
    head() 
      return 
        title: this.title,
        meta: [
          
            hid: 'description',
            name: 'description',
            content: 'Home page description'
          
        ]
      
    
  
</script>

 

 nuxt官网地址:

Nuxt - Meta Tags and SEOhttps://nuxtjs.org/docs/features/meta-tags-seo


5.nuxt 使用VueAwesomeSwiper插件,展示轮播及缩略图

nuxt 使用VueAwesomeSwiper插件,展示轮播及缩略图 - 小白&小菜 - 博客园参考地址:https://github.com/surmon-china/vue-awesome-swiper vue-cli 脚手架使用swiper的步骤:参考地址:https://www.cnblhttps://www.cnblogs.com/duanzhenzhen/p/12362129.html


6.IntersectionObserver API 使用教程

IntersectionObserver API 使用教程 - 阮一峰的网络日志https://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html


7.IE11的CSS兼容性问题

IE11的CSS兼容性问题 - 云+社区 - 腾讯云 最近测试给了我一大堆BUG,一瞅发现全是IE11的。吐槽一下这个浏览器真的比较特立独行。很多默认的样式跟别的浏览器不同,而且最明显的一点应该是padding左...https://cloud.tencent.com/developer/article/1843613


 

8.pc端网页屏幕自适应适配方案(rem)

pc端网页屏幕自适应适配方案(rem) - 简书1 、安装flexible和postcss-px2rem 2、 在main.js 引入lib-flexible *3、删除public/index.html 中的meta标记...https://www.jianshu.com/p/96b4ae1dc5cf?from=message


 

9.后台返回图形验证码 前端如何处理

后台返回图形验证码 前端如何处理_IT_iosers的博客-CSDN博客_验证码返回前端测试后端返回图形验证码console 打印的结果此时前端用axios请求如果直接去拿返回值,就会发现…额…乱码了啊(数据流)前端处理用原生 转化 getImg() var that = this; var windowUrl = window.URL || window.webkitURL; //处理浏览器兼容性 var xhr = new XMLHttpRequest(); var url = `$window.API_BASE_URIhttps://blog.csdn.net/IT_iosers/article/details/120668037?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163548460316780269877007%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163548460316780269877007&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-3-120668037.first_rank_v2_pc_rank_v29&utm_term=%E5%9B%BE%E5%BD%A2%E9%AA%8C%E8%AF%81%E7%A0%81+%E5%89%8D%E7%AB%AF&spm=1018.2226.3001.4187


 

10.nuxt中文官网

安装设置 - Nuxt TypeScript


 

11.好用的日期处理插件day.js

下载安装全局安装后

在页面中就可随意使用

         $dayjs(item.StartTime).format("YYYY/MM/DD")

以上是关于官网项目完成总结的主要内容,如果未能解决你的问题,请参考以下文章

回归 | js实用代码片段的封装与总结(持续更新中...)

VsCode 代码片段-提升研发效率

线程学习知识点总结

十个html5代码片段,超实用,一定要收藏

Vue3官网-高级指南(十七)响应式计算`computed`和侦听`watchEffect`(onTrackonTriggeronInvalidate副作用的刷新时机`watch` pre)(代码片段

python常用代码片段总结