图片压缩 图片转base64

图片压缩 图片转base64

<html>

<head>
    <title>Socket.IO chat</title>
    <link rel="stylesheet" href="element.css" >
    <link rel="stylesheet" href="index.css?v=1.0.2">
    <script src="vue.js"></script>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>
<body>
<div id="app" >
    <!--登录和退出登录 二维码展示-->
    <div class="login-btn" v-cloak v-show="!showChatBox">
        <el-button type="primary" size="small"  @click="loginFun">登录</el-button>
    </div>
    <!--聊天界面-->
    <div class="content-box" v-cloak v-show="showChatBox" >
        <div class="con-left">
            <div class="flex space-between search-box">
                <el-input v-model="searchValue" placeholder="请输入" size="small" clearable @clear="clearSearch"></el-input>
                <el-button size="small" class="btn-search" @click="searchFun">搜索</el-button>
            </div>

            <div class="left-bottom" v-loading="loading">
                <div  :class=[item.payload.id==currentTopInfo.payload.id?'checkedLeft':'','small-con'] @click="topicNameFun(item,index)" v-for="(item,index) in topicData" :key="item.id">
                    <div class="real-con">
                        <div class="left-avatar">
                            <img :src="item.payload.avatar" alt="">
                        </div>
                        <div class="left-name">
                            <div >{{item.payload.topic||`群聊(${item.payload.memberIdList.length})`}}</div>
                            <div class="con-msg">{{item.msg}}</div>
                        </div>
                        <div class="red-dot" v-show="item.payload.id!=currentTopInfo.payload.id&&item.isRead==0"></div>
                    </div>
                </div>
            </div>
        </div>
        <div class="con-right">
            <div class="right-top">
                <span class="name" v-if="topicData.length>0">{{currentTopInfo.payload.topic||`群聊(${currentTopInfo.payload.memberIdList.length})`}}</span>
<!--                <el-button type="danger" size="small" class="logout" @click="logoutFun">退出登录</el-button>-->
            </div>
           <div v-loading="messLoading">
               <div class="right-center-content" v-cloak id="data-list-content" ref="dataListBox" @scroll="handleScroll" >
                   <p v-if="showAllBtn" class="check-all-message"><span >{{msgData}}</span></p>
                   <template v-for="(item,index) in messageData">
                       <!--左边消息  非个人 -->
                       <div class="no-self-box" v-if="!item.isSelf">
                           <div class="right-avatar">
                               <img :src="item.avatar" v-if="item.avatar" alt="">
                               <el-avatar shape="square" icon="el-icon-user-solid" v-else></el-avatar>
                           </div>
                           <div class="ml-9">
                               <div class="nickname">
                                   <span class="name-sty">{{item.nickName}}</span>
                                   <span>{{item.receivTime}}</span>
                               </div>
                               <div class="no-self-con" v-if="item.contentType==1">
                                   <span>{{item.content}}</span>
                               </div>
                               <div class="content-img" v-else>
                                   <el-image
                                           :src="item.content"
                                           :preview-src-list="[item.bigImg]">
                                   </el-image>
                               </div>
                           </div>
                       </div>
                       <!--右边消息  个人 -->
                       <div class="flex flex-end-justify pad-bot" v-if="item.isSelf">
                           <div class="self-box">
                               <div class="mr-9">
                                   <div class="nickname text-right">
                                       <span>{{item.receivTime}}</span>
                                       <span class="name-sty" style="margin-left: 8px">{{item.nickName}}</span>

                                   </div>
                                   <div class="no-self-con" style="text-align: right" v-if="item.contentType==1">
                                       <span style="text-align: left">{{item.content}}</span>
                                   </div>
                                   <div class="content-img" style="text-align: right" v-else>
                                       <el-image
                                               :src="item.content"
                                               :preview-src-list="[item.bigImg]">
                                       </el-image>
                                   </div>
                               </div>
                               <div class="right-avatar">
                                   <img :src="item.avatar" v-if="item.avatar" alt="">
                                   <el-avatar shape="square" icon="el-icon-user-solid" v-else></el-avatar>
                               </div>
                           </div>
                       </div>
                   </template>
               </div>
           </div>
            <div class="right-center-content empty-box" v-show="showEmpty"></div>
            <!--  底部-->
            <div class="right-bottom">
                <div class="send-content">
                    <div class="top-header">
                        <el-tabs v-model="activeName" @tab-click="handleClick">
                            <el-tab-pane label="文字" name="first">

                            </el-tab-pane>
                            <el-tab-pane label="图片" name="second"></el-tab-pane>
                        </el-tabs>
                    </div>
                    <!-- 文字内容框-->
                    <div style="padding-top: 10px" v-if="activeName=='first'">
                        <el-input
                                ref="refInput"
                                type="textarea"
                                :rows="4"
                                placeholder="请输入消息"
                                @keydown.native="handleTextareaKeydown"
                                v-model="realCon">
                        </el-input>
                    </div>
                    <!-- 图片内容框-->
                    <div v-if="activeName=='second'" class="bottom-img">
                        <el-upload ref="elupload" class="upload-drag"  drag multiple action="" :auto-upload="false" :on-change.enter.stop="changeFile" list-type="picture-card">
                           <div class="img-content">
                               <div class="img-box" v-for="(item,index) in fileList" :key="index" >
                                   <img :src="item.url" class="selectImg"  alt="">
                                   <div class="shadow-btn">
                                       <i class="el-icon-delete shadow-hover-con" @click.stop="deleteImg(index)"></i>
                                   </div>
                               </div>
                           </div>
                            <div slot="tip" class="drag-tip">将图片拖拽到此处</div>
                        </el-upload>
                    </div>
                </div>
                <div class="flex flex-end-justify send-btn-box">
                    <div v-if="activeName=='second'">
                        <el-upload ref="eluploadCheck"   multiple action="" :auto-upload="false" :on-change.enter.stop="changeFile" list-type="picture-card">
                            <el-button type="primary" size="small" style="width: 100px;position: fixed;bottom: 8px;right:146px" ref="btn">选择图片</el-button>
                        </el-upload>
                    </div>
                    <el-tooltip class="item" :manual="true" effect="light" v-model="showTip" offset="15" content="不能发送空白信息" placement="top-end">
                        <el-button type="primary" size="small" style="width: 100px;position: fixed;bottom: 8px;right:30px" @click.enter.stop="sendMessage" :loading="sendLoading">发送</el-button>
                    </el-tooltip>
                </div>
            </div>
        </div>
    </div>

    <!--搜索弹框-->
    <div class="search-pos-box" v-cloak v-if="searchDataList.length>0">
        <div class="real-con" v-for="(item,index) in searchDataList" :key="index" @click="searchItem(item)">
            <div class="left-avatar">
                <img :src="item.payload.avatar" alt="">
            </div>
            <div class="left-name">{{item.payload.topic}}</div>
        </div>
    </div>
    <!--二维码弹框-->
    <el-dialog
            title="扫描二维码"
            :visible.sync="showQrcode"
            width="334px"
    >
        <div class="qrcode">
            <img id="qrcode" :src="showQrcodeUrl">
        </div>
    </el-dialog>
    <!--音频-->
    <audio
            src="audio.mp3"
            type="audio/mp3"
            preload="auto"
            controls
            hidden="true"
    ></audio>
</div>
</body>
<script src="elementUI.js" rel="external nofollow"></script>
<script src="socket.io.js" rel="external nofollow"></script>
<script src="axios.js" rel="external nofollow"></script>
<script>

    new Vue({
        el: '#app',
        data(){
            return {
                //搜索字段
                searchValue:'',
                //搜索列表
                searchDataList:[],
                //群列表
                topicData:[],
                //当前群详细信息
                currentTopInfo:{},
                //默认展示文字tab
                activeName:'first',
                //发送的文字
                realCon:"",
                //所选择的文件
                fileList:[],
                //消息列表
                messageData:[],
                //是否显示聊天界面
                showChatBox:false,
                //是否显示二维码弹框
                showQrcode:false,
                //二维码Url地址
                showQrcodeUrl:'',
                //查看全部消息按钮
                showAllBtn:false,
                loading:false,
                sendLoading:false,
                messLoading:false,
                scrollHeight:0,
                //空白提示
                showTip:false,
                //最新id
                finalId:'',
                //文字提示
                msgData:'',
                showEmpty:false,
            }
        },
        async created(){
            await this.getUserInfo();
            await this.getRooms()
        },
        mounted(){
            let that=this
            let socket = io();
            socket.on('scanned', function () {
                console.log('扫码进入')
                that.loading=true
                setTimeout(()=>{
                    //聊天框出现
                    that.showChatBox=true
                    //二维码弹框隐藏
                    that.showQrcode=false
                    that.showQrcodeUrl=''
                    that.getUserInfo();
                    that.getRooms()
                },5000)
            });
            socket.on('qrcode', function (qrcode) {
                that.showChatBox=false //登录按钮出现
                that.showQrcode=true //二维码出现
                that.showQrcodeUrl=qrcode
            });
            socket.on('msg', function (msg) {
                console.log(msg)
                let roomId = msg.room.id
                //排序 当前群和推送消息的群不一样时
                if(roomId!=that.currentTopInfo.id){
                    if(!msg.self){ //不是自己
                        if(that.currentTopInfo.id==that.topicData[0].id){  //排第二位
                            that.sortTopic(1,0,roomId)
                        }else if(that.currentTopInfo.id!=that.topicData[0].id){ //排第一位
                            that.sortTopic(0,0,roomId)
                        }
                        //判断群消息 加红点
                        let findCon=that.topicData.find(e=>{
                            return e.id==roomId
                        })
                        if(findCon){
                            findCon.isRead=0  //加红点
                            msg.type=msg.type?msg.type:1
                            findCon.msg=msg.type==1?msg.text:msg.type==2?'[图片]':msg.text
                            //播放音频
                            that.$nextTick(() => {
                                let audio = document.querySelector("audio");
                                audio.play();
                            });
                        }
                    }else{ //是自己
                        that.topicData.forEach((e,index)=>{
                            if(e.id==roomId){
                                e.isRead=1
                                msg.type=msg.type?msg.type:1
                                e.msg=msg.type==1?msg.text:msg.type==2?'[图片]':msg.text
                                Vue.set(that.topicData,index,e)
                            }
                        })
                    }
                }else{
                  //选中的群和当前消息群一致时
                  //不是自己,排序到第一位
                  if(!msg.self){
                      that.sortTopic(0,0,roomId)
                  }
                    that.topicData.forEach((e,index)=>{
                        if(e.id==roomId){
                            msg.type=msg.type?msg.type:1
                            e.msg=msg.type==1?msg.text:msg.type==2?'[图片]':msg.text
                            Vue.set(that.topicData,index,e)
                        }
                    })
                    let obj= {
                        avatar:msg.talker.payload.avatar,
                        nickName:msg.talker.payload.name,
                        content:msg.text,
                        bigImg:msg.type==2?msg.text.replace('compressor_',''):'',
                        receivTime:msg.receivTime,
                        contentType:msg.type, //1 文字 2 图片
                        isSelf:msg.self  //false 不是自己 true:是自己
                    }
                    that.messageData.push(obj)
                    that.updateMsgType()
                    that.scrollToBottom()
                }
            });
            socket.on('isRead', function (msg) {
                that.topicData.forEach(e=>{
                    if(e.id==msg.roomId){
                        e.isRead=1
                    }
                })
            })

        },
        methods:{
            //清空搜索选择
            clearSearch(){
                this.searchValue=''
                this.searchDataList=[]
            },
            //文字输入框回车发送消息
            handleTextareaKeydown(e) {
                if (!e.shiftKey && e.keyCode == 13) {
                    e.cancelBubble = true; //ie阻止冒泡行为
                    e.stopPropagation();//Firefox阻止冒泡行为
                    e.preventDefault(); //取消事件的默认动作*换行
                    //以下处理发送消息代码
                    this.sendMessage()
                }
            },
            //点击左侧群名称
            topicNameFun(item,index){
                this.showEmpty=true
                item.isRead=1
                this.currentTopInfo={...item}
                this.messageData=[]
                this.finalId=''
                this.getChatRecord()
            },
            //点击搜索项
            searchItem(item){
                // 点击之后 拍完序,清空搜索的内容
                this.searchDataList=[]
                this.searchValue=''
                this.sortTopic(0,0,item.id)
                this.showEmpty=true
                item.isRead=1
                this.currentTopInfo={...item}
                this.finalId=''
                this.messageData=[]
                this.getChatRecord()
            },
            //切换文字和图片
            handleClick(){
                this.fileList=[]
                this.realCon=''
                if(this.activeName=='second'){
                    this.$nextTick(()=>{
                        this.$refs.elupload.$children[1].$refs.input.disabled=true
                        this.$refs.btn.$el.onkeydown= (e) =>{
                            let _key=window.event.keyCode;
                            if(_key===13){
                                return false;
                            }
                        }
                    })
                    //监听回车事件发送消息
                    let that = this;
                    document.onkeydown = function(e) {
                        // that.disabled=true
                        var key = window.event.keyCode;
                        if (key == 13) {
                            if(!that.sendLoading){
                                that.sendMessage();
                            }
                        }
                    }
                }else{
                    this.$nextTick(()=>{
                        if(this.activeNode=='first'){
                            this.$refs.refInput.focus() // 设置焦点
                        }
                    })
                }
            },
            //发消息  调后台接口并渲染页面
            async sendMessage() {
                if(this.activeName=='first'){
                    let contentMsg=JSON.parse(JSON.stringify(this.realCon))
                    //避免重复发送
                    if(this.realCon.split(" ").join("").length == 0||!this.realCon){
                        this.showTip=true
                        setTimeout(()=>{
                            this.showTip=false
                        },1000)
                        return
                    }
                    this.realCon=''
                    this.sendLoading=true
                    await axios.post("/send",{"topic":this.currentTopInfo.payload.topic,"msg":contentMsg}).then(res=>{
                        if(res.data.code==200){
                            contentMsg=''
                        }
                    });
                    this.sendLoading=false
                    this.scrollToBottom()
                }else if(this.activeName=='second'){
                    if(this.fileList.length<=0){
                        this.showTip=true
                        setTimeout(()=>{
                            this.showTip=false
                        },1000)
                        return
                    }
                    this.sendLoading=true
                    for (const item of this.fileList) {
                        //图片文件流转换成base64
                        await this.transFun(item.raw).then(res=>{
                            item.fileName=res.fileName
                            item.path=res.path
                        })
                        //发送图片
                        await axios.post("/sendImg", {
                            topic:this.currentTopInfo.payload.topic,
                            base64:item.path,
                            fileName:item.fileName,
                            slFileName:item.slFileName,
                            base64Compressor:item.slPath,
                            roomId:this.currentTopInfo.id
                        }).then(res=>{
                            if(res.data.code==200){
                                this.fileList=[]
                            }
                        });
                    }
                    this.sendLoading=false
                    this.scrollToBottom()
                }
            },
            //群列表排序
            sortTopic(start,index,roomId){
                let that=this
                if(roomId){
                    let objCon = {}
                    for (let i = 0; i<that.topicData.length; i++) {
                        if (that.topicData[i].id == roomId) {
                            objCon = that.topicData[i]
                            that.topicData.splice(i, 1)
                            break
                        }
                    }
                    that.topicData.splice(start, index, objCon)
                }

            },
            //滚动加载更多消息
            handleScroll() {
                const e = this.$refs['dataListBox']
                // 距离顶部
                const scrollTop = e.scrollTop
                if (scrollTop == 0) {
                    this.showAllBtn = true
                    if(this.finalId){
                        this.getChatRecord() //加载更多聊天记录
                    }
                } else {
                    this.showAllBtn = false
                }
            },
            //退出登录
            logoutFun(){
                this.showChatBox=false
                axios.get("/logout", function (data) {
                });
            },
            //登录
            loginFun(){
                axios.get("/start", function (data) {
                });
            },
            //获取当前用户信息
            async getUserInfo(){
                try {
                    await axios.get("/userInfo").then((result)=>{
                        if(result.data.code==200){
                            this.showChatBox=true
                        }else{
                            this.showChatBox=false
                        }
                    })
                }catch {
                    //
                }finally {
                    //
                }
            },
            //获取群列表
            async getRooms(){
                try {
                    await axios.post("/getAllRooms",{},function (){}).then(res=>{
                        if(res.data.code==200){
                            this.topicData=[]
                            let data = res.data.data
                            if(data.length>0){
                                data.forEach(item=>{
                                    if(item.payload.memberIdList.length>0){
                                        this.topicData.push({
                                            ...item
                                        })
                                    }
                                })
                                this.topicData[0].isRead=1
                                this.currentTopInfo=this.topicData.length>0?this.topicData[0]:{}
                                this.finalId=''
                                this.getChatRecord()
                            }else{
                                this.topicData=[]
                            }

                        }else{
                            this.topicData=[]
                        }
                    })
                }catch {
                    //
                }finally {
                    this.loading=false
                }

            },
            //修改状态
            async updateMsgType(){
                await axios.post('/updateMsgType', {
                    roomId: this.currentTopInfo.payload.id,
                })
            },
            //查询聊天记录
            async getChatRecord(){
                this.messLoading=true
                let data=[]
                try {
                    await axios.post('/getRoomsHistory',{
                        roomName:this.currentTopInfo.payload.topic,
                        pageSize:25,
                        lastId:this.finalId,
                        roomId:this.currentTopInfo.id
                    }).then(res=>{
                        if(res.data.code==200){
                            this.msgData=''
                            data=res.data.data
                            if(data.length>0){
                                data.forEach(item=>{
                                    this.messageData.unshift({
                                        receivTime:item.receivTime,
                                        avatar:item.avatar,
                                        nickName:item.userName,
                                        content:item.msgContent,
                                        bigImg:item.msgType==2?item.msgContent.replace('compressor_',''):'',
                                        contentType:item.msgType, //1 文字 2 图片
                                        isSelf:item.isSelf==1?true:false //false 不是自己 true:是自己
                                    })
                                })
                                //首次加载滚动条滚动到最底部
                                if (!this.finalId) {
                                    // 首次渲染后获取scrollHeight并滑动到底部。
                                    setTimeout(() => {
                                        this.scrollToBottom('auto')
                                    }, 0)
                                }
                                //查看更多
                                const el = this.$refs['dataListBox']
                                this.scrollHeight = el ? el.scrollHeight : 0
                                if (this.finalId) {
                                    // 滚动到加载前的位置
                                    setTimeout(() => {
                                        const currScrollHeight = el.scrollHeight
                                        el.scrollTo(0, currScrollHeight - this.scrollHeight)
                                    }, 0)
                                }

                            }else{
                                this.msgData='暂无更多消息'
                            }
                        }else {
                            this.msgData=''
                        }

                    })
                }catch {
                    //
                }finally {
                    setTimeout(()=>{
                        this.showEmpty=false
                        //最新id
                        this.finalId=data.length>0?data[data.length-1].id:''
                    },200)
                    this.$nextTick(()=>{
                        if(this.activeNode=='first'){
                            this.$refs.refInput.focus() // 设置焦点
                        }
                    })
                    this.messLoading=false
                }
            },
            //搜索群
            searchFun() {
                if(!this.searchValue){
                    this.$message.warning('请输入群名称')
                    return
                }
                let  restaurants = this.topicData;
                let resultList = [];
                restaurants.forEach((item) => {
                    if (item.payload.topic.indexOf(this.searchValue) > -1) {
                        resultList.push(item);
                    }
                });
                this.searchDataList=resultList||[]
                if(resultList.length<=0){
                    this.searchValue=''
                    this.$message.warning('暂无数据')
                }
            },
            //删除图片
            deleteImg(index){
                this.fileList.splice(index,1)
            },
            //消息默认展示最新(div 永远滑到最底部)
            scrollToBottom(type) {
                setTimeout(()=>{
                    this.$nextTick(() => {
                        let div = document.getElementById('data-list-content')
                        div.scrollTo({
                            top: div.scrollHeight,
                            behavior: type?type:"smooth"
                        });
                    })
                },100)
            },
            //判断上传的文件是否是图片格式
            isAssetTypeAnImage(ext) {
                return [
                    'png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff'].
                indexOf(ext.toLowerCase()) !== -1;
            },
            //文件转base64
            transFun(raw){
                return new Promise((resolve, reject) => {
                    let reader = new FileReader();
                    reader.readAsDataURL(raw);
                    let realType=raw.type
                    let lastIndex=realType.lastIndexOf('/')+1
                    let fileType=realType.substring(lastIndex)
                    reader.onload =  function (e) {
                        resolve({
                            fileName:new Date().getTime()+'_image_normal'+'.'+fileType,
                            path:e.target.result,
                        })
                    }
                    reader.onerror = err => reject(err);
                })
            },
            //选择图片
            changeFile(param){
                let filePath = param.name;
                //获取最后一个.的位置
                let index= filePath.lastIndexOf(".");
                //获取后缀
                let ext = filePath.substr(index+1);
                //判断是否是图片
                if(this.isAssetTypeAnImage(ext)){
                    let quality=0.7
                    if(param.raw.size<1000*1000){ //小于1M
                        quality=0.5
                    }else if(param.raw.size<5000*1000){ //小于5M
                        quality=0.4
                    }else if(param.raw.size<10000*1000){ //小于10M
                        quality=0.3
                    }else { //大于10M
                        quality = 0.1
                    }
                    this.compressUpload(param.raw,{
                        width:150,
                        quality:quality
                    }).then(res=>{
                        this.fileList.push({
                            ...param,
                            slPath:res
                        })
                    })
                }
            },
            /* 图片压缩方法-canvas压缩  压缩图片--根据 宽 高 画质压缩图片*/
            compressUpload(file, config) {
                let read = new FileReader();
                read.readAsDataURL(file);
                return new Promise((resolve, reject) => {
                    // 生成canvas
                    let canvas = document.createElement("canvas");
                    let ctx = canvas.getContext("2d");
                    read.onload = function (e) {
                        let img = new Image();
                        img.src = e.target.result;
                        img.onload = function () {
                            let w = this.width;
                            let h = this.height;
                            let scale = w / h;
                            w = config.width || config.height * scale || w;
                            h = config.height || config.width / scale || h;
                            // 最大宽高如有限制时的处理
                            w = config.maxWidth && w > config.maxWidth ? config.maxWidth : w;
                            h = config.maxHeight && h > config.maxHeight ? config.maxHeight : h;
                            w = Math.min(w, h * scale) || w;
                            h = Math.min(h, w / scale) || h;

                            let quality = 0.7; // 默认图片质量
                            // 创建属性节点
                            let anw = document.createAttribute("width");
                            anw.nodeValue = w;
                            let anh = document.createAttribute("height");
                            anh.nodeValue = h;
                            canvas.setAttributeNode(anw);
                            canvas.setAttributeNode(anh);
                            ctx.drawImage(this, 0, 0, w, h);
                            if (config.quality && config.quality <= 1 && config.quality > 0) {
                                quality = config.quality;
                            }
                            let realType=file.type
                            let lastIndex=realType.lastIndexOf('/')
                            let fileType=realType.substring(lastIndex)
                            let base64 = canvas.toDataURL("image"+fileType, quality);
                            // 回调函数返回base64的值,也可根据自己的需求转换
                            resolve(base64);
                            canvas = null;
                        };
                    };
                });
            },

        }
    })
</script>

</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值