官网项目完成总结(一)

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,内容安全 1000次 1年
对象存储 OSS,恶意文件检测 1000次 1年
简介: 官网项目完成总结

前言:


开发完成的这个项目是基于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. 登录注册页


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

image.png

image.png

image.png

封装成一个组件(使用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>


相关文章
|
6月前
|
小程序 容器
企业官网小程序搭建教程-首页的搭建05
企业官网小程序搭建教程-首页的搭建05
|
6月前
|
JavaScript 算法 数据可视化
antv/g6使用教程及图配置
antv/g6使用教程及图配置
1502 0
|
11月前
|
小程序 JavaScript 前端开发
小程序之如何学习一个新的知识,首先就是通过官网进行讲解!!(2)
小程序之如何学习一个新的知识,首先就是通过官网进行讲解!!(2)
SketchUp2020免费中文完整版官网2021教程模型库下载
SketchUp2022 WIN10 64位安装步骤: 1.先使用“百度网盘客户端”下载SU22_CN_x64安装包到电脑磁盘里,并鼠标右击进行解压缩,然后找到SketchUpProFull-2022.exe,鼠标右击选择【以管理员身份运行】 2.选择软件安装路径,默认安装在C盘,点击【更改】可修改软件安装路径,注意:安装路径文件夹名称不能含有中文字符!小编这里将软件安装在D盘SU2022文件夹下,然后点击【安装】 温馨提示:请记住软件安装路径,后续操作需要用到。 3.正在安装中,这个过程中大概需要10分钟左右的时间,请耐心等待… 4.安装结束,点击【完成】 5.返回软件初始安装包
SketchUp2020免费中文完整版官网2021教程模型库下载
|
JavaScript 网络安全 开发工具
Github+Hexo搭建个人网站详细教程
随着互联网浪潮的翻腾,国内外涌现出越来越多优秀的社交网站让用户分享信息更加便捷。然后,如果你是一个不甘寂寞的程序猿,是否也想要搭建一个属于自己的个人网站,如果你曾经或者现在正有这样的想法,请跟随这篇文章发挥你的Geek精神,让你快速拥有自己的博客网站,写文章记录生活,享受这种从0到1的过程。
|
JavaScript 前端开发 程序员
从零开发和发布自己的wordpress插件到官方插件库完全指南
wordpress是一款很流行的开源博客程序,全世界有很多网站都在使用wordpress,程序员们也喜欢拿来做自己的技术博客,对于自己不满意的地方,那肯定也需要自己动手来修改了,下面就介绍从开发到发布一个wordpress插件的完整流程
149 0
|
数据挖掘 图形学
bookdown官网最新开源书籍汇总
bookdown官网最新开源书籍汇总
541 0
|
开发者 容器
《梦幻西游》官网小动画
偶然间在《梦幻西游》的官网发现了这么一个动画,又一不小心打开了开发者工具,又一不下心发现这个动画是通过一张图片使用帧动画来实现的
164 0
|
前端开发 JavaScript API