官网项目完成总结(一)

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,内容安全 1000次 1年
密钥管理服务KMS,1000个密钥,100个凭据,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>


相关文章
|
7月前
|
小程序 容器
企业官网小程序搭建教程-首页的搭建05
企业官网小程序搭建教程-首页的搭建05
|
5月前
|
存储 Java 关系型数据库
Maven下载以及配置 一条龙全教程
Maven下载以及配置 一条龙全教程
236 0
SketchUp2020免费中文完整版官网2021教程模型库下载
SketchUp2022 WIN10 64位安装步骤: 1.先使用“百度网盘客户端”下载SU22_CN_x64安装包到电脑磁盘里,并鼠标右击进行解压缩,然后找到SketchUpProFull-2022.exe,鼠标右击选择【以管理员身份运行】 2.选择软件安装路径,默认安装在C盘,点击【更改】可修改软件安装路径,注意:安装路径文件夹名称不能含有中文字符!小编这里将软件安装在D盘SU2022文件夹下,然后点击【安装】 温馨提示:请记住软件安装路径,后续操作需要用到。 3.正在安装中,这个过程中大概需要10分钟左右的时间,请耐心等待… 4.安装结束,点击【完成】 5.返回软件初始安装包
SketchUp2020免费中文完整版官网2021教程模型库下载
|
小程序 JavaScript 前端开发
小程序之如何学习一个新的知识,首先就是通过官网进行讲解!!(2)
小程序之如何学习一个新的知识,首先就是通过官网进行讲解!!(2)
|
前端开发
手把手带你一起写迅雷官网(一)
手把手带你一起写迅雷官网
|
前端开发 JavaScript
手把手带你一起写迅雷官网(二)
手把手带你一起写迅雷官网
|
数据挖掘 图形学
bookdown官网最新开源书籍汇总
bookdown官网最新开源书籍汇总
587 0
|
开发者 容器
《梦幻西游》官网小动画
偶然间在《梦幻西游》的官网发现了这么一个动画,又一不小心打开了开发者工具,又一不下心发现这个动画是通过一张图片使用帧动画来实现的
172 0
|
前端开发 JavaScript API
|
搜索推荐 小程序 Android开发
【做一个官网】企业如何从零做一个官网
【做一个官网】企业如何从零做一个官网。做一个官网教程,今天珍奶bb给大家简单唠唠企业公司官网开发流程及步骤是什么?企业做一个官网早已不是一件很难的事情,虽然建设网站涉及到代码、服务器、域名申请等等,但是这么专业的事情早就有公司规范化、流程化、简单化来完成了。因此大家只需要找到一家靠谱的第三方企业网站建设公司即可。 下面就给大家讲讲和第三方企业网站建设公司合作做一个官网的流程及步骤是什么?
400 0