先看效果图:
 

消息格式参照下方:

- <template>
- <view class="chat-index">
- <scroll-view
- id="scrollview"
- class="scroll-style"
- :style="{height: `${windowHeight - inputHeight}rpx`}"
- scroll-y="true"
- :scroll-top="conf.scrollTop"
- @scrolltoupper="topRefresh"
- @click="touchClose"
- >
- <view id="msglistview" class="chat-body">
- <view v-for="item,index in data.msgInfoList" :key="index">
-
- <!-- 消息发送时间 -->
- <view class="time-box" v-if="item.showTime">
- <view class="time-style">
- <view>
- {{ timeFormat(item.sendTime) }}
- </view>
- </view>
- </view>
-
- <!-- 自己 -->
- <view class="item self" v-if="item.scid == userInfo.scid">
-
- <!-- 文本消息 -->
- <view class="content-text right" v-if="item.type=='text'">
- {{item.content}}
- </view>
-
- <!-- 语音消息 -->
- <view class="content-text right" v-else-if="item.type=='voice'">
- <view style="display: flex;" @click="playSound(item.content)">
- <text>{{ item.voiceLength }}''</text>
- <image v-if="conf.playVoice" style="width: 42rpx;height: 42rpx;" src="../../static/icon/voice_play_on.png"/>
- <image v-else style="width: 42rpx;height: 42rpx;" src="../../static/icon/voice_play.png"/>
- </view>
- </view>
-
- <!-- 图片消息 -->
- <view class="content-img" v-else-if="item.type=='img'">
- <image class="img-style" :src="item.content" mode="widthFix" :lazy-load="true"/>
- </view>
-
- <!-- 视频消息 -->
- <view class="content-video" v-else>
- <video class="video-style" :src="item.content" />
- </view>
-
- <!-- 头像 -->
- <image class="avatar" :src="userInfo.s_avatar" />
- </view>
-
- <!-- 好友 -->
- <view class="item Ai" v-else>
-
- <!-- 头像 -->
- <image class="avatar" :src="userInfo.r_avatar" />
-
- <!-- 文本消息 -->
- <view class="content-text left" v-if="item.type=='text'">
- {{item.content}}
- </view>
-
- <!-- 语音消息 -->
- <view class="content-text left" v-else-if="item.type=='voice'">
- <view style="display: flex;" @click="playSound(item.content)">
- <text>{{ item.voiceLength }}''</text>
- <image v-if="conf.playVoice" style="width: 42rpx;height: 42rpx;" src="../../static/icon/voice_play_on.png"/>
- <image v-else style="width: 42rpx;height: 42rpx;" src="../../static/icon/voice_play.png"/>
- </view>
- </view>
-
- <!-- 图片消息 -->
- <view class="content-img" v-else-if="item.type=='img'">
- <image class="img-style" :src="item.content" mode="widthFix" :lazy-load="true"/>
- </view>
-
- <!-- 视频消息 -->
- <view class="content-video" v-else>
- <video class="video-style" :src="item.content" />
- </view>
- </view>
- </view>
- </view>
- </scroll-view>
-
- <!-- 消息发送框 -->
- <view class="chat-bottom" :style="{height:`${inputHeight}rpx`}">
- <view class="input-msg-box" :style="{bottom:`${conf.keyboardHeight}rpx`}">
-
- <!-- 输入框区域 -->
- <view class="textarea-style">
- <!-- 语音/文字输入 -->
- <view class="voice-btn" @click="isVoice">
- <image class="icon-style" v-if="conf.isVoice" src="../../static/icon/keyboard.png" />
- <image class="icon-style" v-else src="../../static/icon/voice.png" />
- </view>
-
- <!-- textarea输入框 -->
- <view class="out_textarea_box" @click="() => conf.showMoreMenu=false">
- <textarea
- placeholder-class="textarea_placeholder"
- :style="{textAlign:(conf.textAreaDisabled?'center':'')}"
- v-model="sendMsg.text"
- maxlength="250"
- confirm-type="send"
- auto-height
- :placeholder="conf.textAreaText"
- :show-confirm-bar="false"
- :adjust-position="false"
- :disabled="conf.textAreaDisabled"
- @confirm="handleSend"
- @linechange="listenTextAreaHeight"
- @focus="scrollToBottom"
- @blur="scrollToBottom"
- @touchstart="handleTouchStart"
- @touchmove="handleTouchMove"
- @touchend="handleTouchEnd"
- />
- </view>
-
- <!-- 输入菜单 -->
- <view class="more-btn">
- <image class="icon-style" src="../../static/icon/emoji.png" @click="handleSend"/>
- <image class="icon-style" style="margin-left: 20rpx;" src="../../static/icon/more.png" @click="showMoreMenuFunc"/>
- </view>
-
- </view>
-
- <!-- 更多菜单 -->
- <view :class="{'more-menu-box-max': conf.showMoreMenu,'more-menu-box-min': !conf.showMoreMenu}">
- <view class="inner-menu-box">
- <view class="menu-box" @click="sendFile('choose','')">
- <view class="out-icon-area">
- <image class="i-style" src="../../static/icon/photo.png" />
- </view>
- <view class="t-style">照片</view>
- </view>
- <view class="menu-box" @click="sendFile('shoot','')">
- <view class="out-icon-area">
- <image class="i-style" src="../../static/icon/takePhoto.png" />
- </view>
- <view class="t-style">拍摄</view>
- </view>
- </view>
- </view>
-
- </view>
- </view>
-
- <!-- 语音输入 -->
- <view class="voice-mask" v-show="voice.mask">
- <view class="inner-mask">
- <view class="voice-progress-box" :style="{width:`${progressNum}`+'rpx'}">
- <view class="third-icon"/>
- <view class="progress-num">
- {{ voice.length }}s
- </view>
- </view>
- <view class="cancel-btn" :class="{cancelBtn : voice.cancel}">
- <image style="width: 60rpx;height: 60rpx;" src="../../static/icon/cancel-voice.png"></image>
- </view>
- <view class="show-tips">
- 上滑取消发送
- </view>
- <view class="bottom-area">
- <image class="img-style" src="../../static/icon/icon-voice.png" />
- </view>
- </view>
- </view>
- </view>
- </template>
- <script setup>
- import { computed, getCurrentInstance, reactive, ref, onUpdated } from 'vue';
- import { onLoad } from '@dcloudio/uni-app';
- import properties from '@/properties/index.js';
- import timeMethod from '@/utils/timeMethod.js';
- const { proxy } = getCurrentInstance();
- const _this = proxy;
- const sendMsg = reactive({
- text: ''
- })
- /* 接口数据 */
- const data = reactive({
- msgInfoList: [],
- pageNum: 1,
- pageSize: 20,
- pageNumCount: 0
- })
- /* 用户信息 */
- const userInfo = reactive({
- scid: null,
- rcid: null,
- s_avatar: '',
- r_avatar: ''
- })
- /* 配置项 */
- const conf = reactive({
- keyboardHeight: 0,
- bottomHeight: 150,
- scrollTop: 0,
- moreMenuHeight: 0,
- judgeScrollToBottom: true,
- showMoreMenu: false,
- loading: false,
- showMsgMenuBoxId: null,
- showMoreMenu: false,
- textAreaDisabled: false,
- textAreaText: '',
- isVoice: false,
- showMoreMenu: false,
- playVoice: false
- })
- /* 语音输入配置项 */
- const voice = reactive({
- mask: false,
- length: 0,
- cancel: false,
- startX: "",
- startY: "",
- timer: "",
- recordInstance: "",
- finished: false,
- })
- /* msg配置项 */
- const msgConf = reactive({
- timeSpace: 120,
- initMsgTime: '',
- msgId: 0,
- latestTime: ''
- })
- /**
- * 页面加载时调用
- */
- onLoad((e) => {
- userInfo.scid =parseInt(uni.getStorageSync('cid'));
- userInfo.rcid = parseInt(e.rcid);
- voice.recordInstance = uni.getRecorderManager();
- keyboardHeightChange();
- listenMsg();
- getAiUserInfo(parseInt(e.rcid));
- getSelfUserInfo(uni.getStorageSync('cid'));
- getAllMsg(parseInt(e.rcid));
- readMsg(parseInt(e.rcid))
- })
- /**
- * 数据更新时调用
- */
- onUpdated(() => {
- /* 页面更新时调用聊天消息定位到最底部 */
- if (conf.judgeScrollToBottom) scrollToBottom();
- })
- /**
- * 计算属性
- */
- const windowHeight = computed(() => rpxTopx(uni.getSystemInfoSync().windowHeight))
- const inputHeight = computed(() => conf.bottomHeight + conf.keyboardHeight + conf.moreMenuHeight)
- const progressNum = computed(() => voice.length * 2 + 250)
- /**
- * px 转换 rpx
- */
- const rpxTopx = (px) => {
- const deviceWidth = uni.getSystemInfoSync().windowWidth;
- let rpx = ( 750 / deviceWidth ) * Number(px);
- return Math.floor(rpx);
- }
- /**
- * 监听聊天发送栏高度
- */
- const listenTextAreaHeight = () => {
- setTimeout(()=>{
- let query = uni.createSelectorQuery();
- query.select('.input-msg-box').boundingClientRect();
- query.exec(res =>{
- conf.bottomHeight = rpxTopx(res[0].height);
- })
- },200)
- }
- /**
- * 监听键盘高度
- */
- const keyboardHeightChange = () => {
- uni.onKeyboardHeightChange(res => {
- conf.keyboardHeight = rpxTopx(res.height);
- if(conf.keyboardHeight <= 0) {
- conf.keyboardHeight = 0;
- conf.showMoreMenu = false;
- }
- })
- }
- /**
- * 滑动到底部
- */
- const scrollToBottom = (e) => {
- setTimeout(()=>{
- let query = uni.createSelectorQuery().in(_this);
- query.select('#scrollview').boundingClientRect();
- query.select('#msglistview').boundingClientRect();
- query.exec((res) =>{
- if(res[1].height > res[0].height){
- conf.scrollTop = rpxTopx(res[1].height - res[0].height);
- }
- })
- },200);
- }
- /**
- * 弹出更多菜单弹窗
- */
- const showMoreMenuFunc = () => {
- conf.showMoreMenu = true;
- conf.isVoice = false;
- conf.textAreaText = '';
- conf.moreMenuHeight = 350;
- }
- /**
- * websocket监听
- */
- const listenMsg = () => {
- uni.onSocketMessage((res)=>{
- let resData = JSON.parse(res.data);
- data.msgInfoList.push(resData);
- })
- }
- /**
- * 语音与输入切换
- */
- const isVoice = () => {
- if (conf.isVoice) {
- conf.isVoice = false;
- conf.textAreaDisabled = false;
- conf.textAreaText = '';
- } else {
- conf.isVoice = true;
- conf.textAreaDisabled = true;
- conf.textAreaText = '按住 说话';
- conf.showMoreMenu = false;
- conf.moreMenuHeight = 0;
- }
-
- }
- /**
- * 获取用户信息(自己)
- */
- const getSelfUserInfo = (cid) => _this.$http('/user/getUserInfo','GET',{'cid':cid}).then(res => {
- userInfo.scid = cid;
- userInfo.s_avatar = res.data.avatarUrl;
- })
- /**
- * 获取用户信息(好友)
- */
- const getAiUserInfo = (cid) => _this.$http('/user/getUserInfo','GET',{'cid':cid}).then(res => {
- userInfo.rcid = cid;
- userInfo.r_avatar = res.data.avatarUrl;
- uni.setNavigationBarTitle({title:res.data.name});
- })
- /**
- * 上拉加载消息
- */
- const topRefresh = () => {
- if (data.pageNum < data.pageNumCount) {
- data.pageNum++;
- conf.judgeScrollToBottom = false;
- conf.loading = true;
- getAllMsg(userInfo.rcid);
- }
- }
- /**
- * 获取消息
- */
- const getAllMsg = (rcid) => {
- _this.$http('/msg/getChatMsg','POST',{'scid':uni.getStorageSync('cid'),'rcid':rcid,'pageNum':data.pageNum,'pageSize':data.pageSize}).then(res => {
- data.pageNumCount = res.data.pagesNum;
- showMsgTime(res.data.list);
- msgConf.latestTime = data.msgInfoList.slice(-1)[0].sendTime;
- })
- }
- /**
- * 已读消息
- */
- const readMsg = (rcid) => {
- _this.$http('/msg/readMsg','POST',{'scid':rcid,'rcid':uni.getStorageSync('cid')})
- }
- /**
- * 控制消息时间是否展示
- */
- const showMsgTime = (msgData) => {
- msgData.forEach(e => {
- e.showTime = false;
- data.msgInfoList.unshift(e);
- if (msgConf.msgId !== 0) {
- if (timeMethod.calculateTime(msgConf.initMsgTime,e.sendTime)/1000 > msgConf.timeSpace) {
- data.msgInfoList.slice(0 - msgConf.msgId)[0].showTime = true;
- }
- }
- msgConf.initMsgTime = e.sendTime;
- msgConf.msgId++;
- });
- data.msgInfoList.slice(0 - (msgConf.msgId + 1))[0].showTime = true;
- }
- /**
- * 日期转换
- */
- const timeFormat = (time) => {
- //时间格式化
- const Time = timeMethod.getTime(time).split("T");
- //当前消息日期属于周
- const week = timeMethod.getDateToWeek(time);
- //当前日期0时
- const nti = timeMethod.setTimeZero(timeMethod.getNowTime());
- //消息日期当天0时
- const mnti = timeMethod.setTimeZero(timeMethod.getTime(time));
- //计算日期差值
- const diffDate = timeMethod.calculateTime(nti,mnti);
- //本周一日期0时 (后面+1是去除当天时间)
- const fwnti = timeMethod.setTimeZero(timeMethod.countDateStr(-timeMethod.getDateToWeek(timeMethod.getNowTime()).weekID + 1));
- //计算周日期差值
- const diffWeek = timeMethod.calculateTime(mnti,fwnti);
-
- if (diffDate === 0) { //消息发送日期减去当天日期如果等于0则是当天时间
- return Time[1].slice(0,5);
- } else if (diffDate < 172800000) { //当前日期减去消息发送日期小于2天(172800000ms)则是昨天- 一天最大差值前天凌晨00:00:00到今天晚上23:59:59
- return "昨天 " + Time[1].slice(0,5);
- } else if (diffWeek >= 0) { //消息日期减去本周一日期大于0则是本周
- return week.weekName;
- } else { //其他时间则是日期
- return Time[0].slice(5,10);
- }
- }
- /**
- * 关闭消息操作菜单
- */
- const touchClose = () => {
- conf.showBoxId = null;
- conf.showMoreMenu = false;
- conf.keyboardHeight = 0;
- conf.moreMenuHeight = 0;
- }
- /**
- * 发送消息
- */
- const handleSend = () => {
- conf.judgeScrollToBottom = true;
- data.pageNum = 1;
- /* 如果消息不为空 */
- if(sendMsg.text.length !== 0){
- _this.$http("/msg/sendMsg","POST",{
- "scid":userInfo.scid,
- "rcid":userInfo.rcid,
- "type": "text",
- "content":sendMsg.text}).then(res => {
- if (res.status) {
- if (timeMethod.calculateTime(res.data.sendTime,msgConf.latestTime)/1000 > msgConf.timeSpace) {
- res.data.showTime = true;
- } else {
- res.data.showTime = false;
- }
- data.msgInfoList.push(res.data);
- sendMsg.text = '';
- }
- })
- }
- }
- /**
- * 长按开始录制语音
- */
- const handleTouchStart = (e) => {
- if (conf.textAreaDisabled) {
- voice.finished = false;
- uni.getSetting({
- success(res) {
- if (res.authSetting['scope.record'] === undefined) {
- console.log("第一次授权")
- } else if (!res.authSetting['scope.record']) {
- uni.showToast({
- icon: "none",
- title: "点击右上角···进入设置开启麦克风授权!",
- duration: 2000
- })
- } else {
- voice.recordInstance.start();
- voice.mask = true;
- voice.isRecord = true;
- voice.length = 1;
- voice.startX = e.touches[0].pageX;
- voice.startY = e.touches[0].pageY;
- voice.timer = setInterval(() => {
- voice.length += 1;
- if(voice.length >= 60) {
- clearInterval(voice.timer);
- handleTouchEnd();
- }
- },1000)
- //判断先结束按钮但是录制才开始时不会结束录制的条件;因为获取授权这儿存在延时;所以结束录制时可能还没开始录制
- if (voice.finished && voice.mask) {
- handleTouchEnd();
- }
- }
- }
- })
- }
- }
- /**
- * 长按滑动
- */
- const handleTouchMove = (e) => {
- if (conf.textAreaDisabled) {
- if (voice.startY - e.touches[0].pageY > 80) {
- voice.cancel = true;
- }else {
- voice.cancel = false;
- }
- }
- }
- /**
- * 语音录制结束
- */
- const handleTouchEnd = () => {
- if (conf.textAreaDisabled) {
- voice.finished = true;
- voice.mask = false;
- clearInterval(voice.timer);
- voice.recordInstance.stop();
- voice.recordInstance.onStop((res) => {
- const message = {
- voice:res.tempFilePath,
- length:voice.length
- }
- if (!voice.cancel) {
- if (voice.length>1) {
- sendFile("voice",message);
- } else {
- uni.showToast({
- icon: 'none',
- title: "语音时间太短",
- duration: 1000
- })
- }
- }else {
- voice.cancel = false;
- }
- })
- }
- }
- /**
- * 语音播放
- */
- const playSound = (url) => {
- conf.playVoice = true;
- let music = null;
- music = uni.createInnerAudioContext();
- music.src = url;
- music.play();
- music.onEnded(()=>{
- music = null;
- conf.playVoice = false;
- })
- }
- /**
- * 发送文件
- */
- const sendFile = (type,data) => {
- if (type === "choose") {
- uni.chooseMedia({
- count: 1,
- mediaType: ['image', 'video'],
- sourceType: ['album'],
- maxDuration: 30,
- success(res) {
- let type = 'img';
- if (res.tempFiles[0].fileType === 'image') {
- type = 'img'
- } else {
- type = 'video'
- }
- uploadFile(res.tempFiles[0].tempFilePath,type)
- }
- })
- } else if (type === "shoot") {
- uni.chooseMedia({
- count: 1,
- mediaType: ['image', 'video'],
- sourceType: ['camera'],
- maxDuration: 30,
- success(res) {
- let type = 'img';
- if (res.tempFiles[0].fileType === 'image') {
- type = 'img'
- } else {
- type = 'video'
- }
- uploadFile(res.tempFiles[0].tempFilePath,type)
- }
- })
- } else {
- uploadFile(data.voice,'voice')
- }
- }
- /**
- * 上传文件
- */
- const uploadFile = (path,type) => {
- let param = {"scid":userInfo.scid,"rcid":userInfo.rcid,"type":type};
- if (type=='voice') {
- param = {"scid":userInfo.scid,"rcid":userInfo.rcid,"type":type,"voiceLength":voice.length};
- }
- uni.uploadFile({
- url: properties.appConf.url + "/msg/sendFileMsg",
- filePath: path,
- name: 'file',
- formData: param,
- header: {"Authorization": uni.getStorageSync('Authorization')},
- success(res) {
- let newMsg = JSON.parse(res.data)
- if (newMsg.status) {
- if (timeMethod.calculateTime(newMsg.data.sendTime,msgConf.latestTime)/1000 > msgConf.timeSpace) {
- newMsg.data.showTime = true;
- } else {
- newMsg.data.showTime = false;
- }
- data.msgInfoList.push(newMsg.data)
- }
- }
- })
- }
- </script>
- <style lang="scss">
-
- $chatContentbgc: #00ff7f;
- $chatBackground: #f0f0f0;
- center {
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .chat-index {
- height: 100vh;
- background-color: $chatBackground;
-
- .scroll-style {
-
- .chat-body {
- display: flex;
- flex-direction: column;
- padding-top: 23rpx;
-
- .time-box {
- width: 100%;
- height: 100rpx;
- display: flex;
- justify-content: center;
- align-items: center;
-
- .time-style {
- font-size: 22rpx;
- background-color: rgba(213, 213, 213, 0.3);;
- padding: 5rpx 10rpx;
- border-radius: 8rpx;
- color: black;
- }
- }
-
- .self {
- justify-content: flex-end;
- position: relative;
- }
-
- .Ai {
- position: relative;
- }
-
- .item {
- display: flex;
- padding: 23rpx 30rpx;
-
- .right {
- background-color: $chatContentbgc;
- }
-
- .left {
- background-color: #FFFFFF;
- }
-
- .right::after {
- position: absolute;
- display: inline-block;
- content: '';
- width: 0;
- height: 0;
- left: 100%;
- top: 10px;
- border: 12rpx solid transparent;
- border-left: 12rpx solid $chatContentbgc;
- }
-
- .left::after {
- position: absolute;
- display: inline-block;
- content: '';
- width: 0;
- height: 0;
- top: 10px;
- right: 100%;
- border: 12rpx solid transparent;
- border-right: 12rpx solid #FFFFFF;
- }
-
- .content-text {
- position: relative;
- max-width: 486rpx;
- border-radius: 8rpx;
- word-wrap: break-word;
- padding: 24rpx 24rpx;
- margin: 0 24rpx;
- border-radius: 5px;
- font-size: 32rpx;
- font-family: PingFang SC;
- font-weight: 500;
- color: #333333;
- line-height: 42rpx;
- }
-
- .content-img {
- margin: 0 24rpx;
- }
-
- .content-video {
- margin: 0 24rpx;
- }
-
- .img-style {
- width: 400rpx;
- height: auto;
- border-radius: 10rpx;
- }
-
- .video-style {
- width: 400rpx;
- height: 400rpx;
- }
-
- .avatar {
- display: flex;
- justify-content: center;
- width: 78rpx;
- height: 78rpx;
- background: #fff;
- border-radius: 50rpx;
- overflow: hidden;
-
- image {
- align-self: center;
- }
- }
- }
- }
- }
-
- .chat-bottom {
- width: 100%;
-
- .input-msg-box {
- width: 100% ;
- min-height: 150rpx;
- position: fixed;
- bottom: 0;
- background: #e6e6e6;
-
- .textarea-style {
- width: 100%;
- padding-top: 20rpx;
- display: flex;
-
- .out_textarea_box {
- width:65%;
- min-height: 70rpx;
- border-radius: 10rpx;
- margin-left: 10rpx;
- background: #f0f0f0;
- display: flex;
- align-items: center;
-
- textarea {
- width: 94%;
- padding: 0 3%;
- min-height: 42rpx;
- max-height: 200rpx;
- font-size: 32rpx;
- font-family: PingFang SC;
- color: #333333;
- }
- }
-
- .voice-btn {
- width: 10%;
- @extend center;
- }
-
- .more-btn {
- width: calc(25% - 25rpx);
- margin-left: 10rpx;
- @extend center;
- }
-
- .icon-style {
- width: 50rpx;
- height: 50rpx;
- }
- }
-
- .more-menu-box-min {
- width: 100%;
- height: 0rpx;
- display: none;
- }
-
- .more-menu-box-max {
- height: 400rpx;
- margin-top: 10rpx;
- border-top: 1rpx solid #d6d6d6;
- transition: height 1ms linear;
- display: block;
-
- .inner-menu-box {
- width: calc(100% - 20rpx);
- height: calc(360rpx - 10rpx);
- padding: 10rpx;
-
- .menu-box {
- width: 150rpx;
- height: 150rpx;
- margin: 12rpx calc((100% - 600rpx) / 8);
- float: left;
-
- .out-icon-area {
- width: 110rpx;
- height: 110rpx;
- background-color: #fff;
- border-radius: 20rpx;
- margin: 0 20rpx;
- @extend center;
-
- .i-style {
- width: 60rpx;
- height: 60rpx;
- }
- }
-
- .t-style {
- font-size: 24rpx;
- font-weight: 400;
- text-align: center;
- margin-top: 10rpx;
- color: #717171;
- }
- }
- }
- }
-
- }
- }
-
- .voice-mask{
- position:fixed;
- top:0;
- right:0;
- bottom:0;
- left:0;
- background-color: rgba(0,0,0,0.8);
-
- .inner-mask {
- display: flex;
- flex-direction: column;
- align-items: center;
-
- .voice-progress-box {
- min-width: 250rpx;
- height: 150rpx;
- margin-top: 60%;
- border-radius: 50rpx;
- background: #4df861;
- position: relative;
- @extend center;
-
- .third-icon {
- width: 0;
- height: 0;
- border: 15rpx solid transparent;
- border-top: 15rpx solid #4df861;
- position: absolute;
- top: 100%;
- left: 45%;
-
- .progress-num {
- font-size: 50rpx;
- font-weight: 600;
- }
- }
-
- }
-
- .cancel-btn {
- width: 120rpx;
- height: 120rpx;
- clip-path: circle();
- margin-top: 50%;
- background: #080808;
- @extend center;
- }
-
- .cancelBtn {
- width: 150rpx;
- height: 150rpx;
- background-color: #ff0004;
-
- }
-
- .show-tips {
- width: 100%;
- margin-top: 50rpx;
- text-align: center;
- color: white;
- animation: 4s opacity2 1s infinite;
- font-size: 30rpx;
- font-weight: 400;
- font-family: sans-serif;
- }
-
- @keyframes opacity2{
- 0%{opacity:0}
- 50%{opacity:.8;}
- 100%{opacity:0;}
- }
-
- .bottom-area {
- position: fixed;
- bottom: 0rpx;
- width: 100%;
- height:190rpx;
- border-top: #BABABB 8rpx solid;
- border-radius: 300rpx 300rpx 0 0;
- background-image: linear-gradient(#949794,#e1e3e1);
- @extend center;
-
- .img-style {
- width: 50rpx;
- height: 50rpx;
- }
- }
- }
- }
- }
- </style>
复制代码 导入的时间工具包 timeMethod.js
- class TimeMethod {
-
- constructor() {}
-
- //日期格式化
- addZero(data) {
- if (parseInt(data) < 10) {
- return "0" + String(data);
- }
- return data;
- }
-
- /**
- * 获取当前日期
- */
- getNowTime() {
- const myDate = new Date();
- const year = myDate.getFullYear();
- const mouth = this.addZero(myDate.getMonth() + 1);
- const day = this.addZero(myDate.getDate());
- const hour = this.addZero(myDate.getHours());
- const minute = this.addZero(myDate.getMinutes());
- const second = this.addZero(myDate.getSeconds());
- return year + '-' + mouth + '-' + day + 'T' + hour+ ':' + minute+ ':' + second
- }
-
- /**
- * 根据时间返回标准字符串时间
- * @param {Object} time
- */
- getTime(time) {
- const myDate = new Date(time);
- const year = myDate.getFullYear();
- const mouth = this.addZero(myDate.getMonth() + 1);
- const day = this.addZero(myDate.getDate());
- const hour = this.addZero(myDate.getHours());
- const minute = this.addZero(myDate.getMinutes());
- const second = this.addZero(myDate.getSeconds());
- return year + '-' + mouth + '-' + day + 'T' + hour+ ':' + minute+ ':' + second
- }
-
- /**
- * @param {Object} timestamp
- * @param {Object} type
- * 时间戳转时间
- */
- timestampToTime(timestamp,type) {
- if(String(timestamp).length===10) {
- //时间戳为10位需*1000
- var date = new Date(timestamp * 1000);
- }else {
- var date = new Date(timestamp);
- }
- const Y = date.getFullYear() + '-';
- const M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
- const D = date.getDate() + ' ';
- const h = date.getHours() + ':';
- const m = date.getMinutes() + ':';
- const s = date.getSeconds();
- if(type==="date") {
- return Y+M+D;
- }else {
- return Y+M+D+h+m+s;
- }
- }
-
-
- /**
- * @param {Object} time
- * 时间转时间戳
- */
- timeToTimestamp(time) {
- //精确到秒,毫秒用000代替 :Date.parse(date);
- return new Date(time).getTime();
- }
-
-
- /**
- * @param {Object} startTime
- * @param {Object} endTime
- * 日期计算
- */
- calculateTime(startTime,endTime) {
- return new Date(startTime) - new Date(endTime)
- }
-
- /**
- * @param {Object} time
- * 日期转星期
- */
- getDateToWeek(time) {
- let weekArrayList = [
- {"weekID":7,"weekName":"星期日"},
- {"weekID":1,"weekName":"星期一"},
- {"weekID":2,"weekName":"星期二"},
- {"weekID":3,"weekName":"星期三"},
- {"weekID":4,"weekName":"星期四"},
- {"weekID":5,"weekName":"星期五"},
- {"weekID":6,"weekName":"星期六"}];
- return weekArrayList[new Date(time).getDay()]
- }
-
- /**
- * @param {Object} date
- * yyyy-MM-dd HH:mm:ss转为 yyyy-MM-ddTHH:mm:ss
- */
- timeFormat(date,type) {
- if (type == "T")
- return date.replace(" ","T")
- else
- return date.replace("T"," ")
- }
-
- /**
- * @param {Object} time
- * 定时器
- */
- timeSleep(time) {
- return new Promise((resolve) => setTimeout(resolve,time))
- }
-
-
- /**
- * 根据日期加减计算日期
- * @param dayCount
- */
- countDateStr(dayCount) {
- let dd = new Date();
- dd.setDate(dd.getDate()+ dayCount);
- let ms = dd.getTime();
- return new Date(ms).toJSON();
- }
-
- /**
- * @param {Object} time
- * 日期中时间置0
- */
- setTimeZero(time) {
- return time.slice(0,10) + 'T00:00:00.000+00:00';
- }
- }
- export default new TimeMethod();
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |