创新实训周报四(第十周)用户聊天前端(静态界面部分)

本周我分到的任务是两个组件,显示好友列表和聊天界面,我选择仿微信做一个界面,然后分别在其中镶嵌两个组件

这是做好的成品展示

具体的如下

总体界面

<template>
  <div id="building">
    <div id="app">
      <div class="sidebar">
        <mycard></mycard>
      </div>
      <div class="main">
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script>
import mycard from '@/components/mycard/mycard'
import { mapActions } from 'vuex'
export default {
  components: {
    mycard
  },
  created() {
    this.$store.dispatch('fetchUserInfo');
    this.$store.dispatch('initData')
  }
}
</script>

<style scoped>
#app {
  display: flex;
  border-radius: 50px;
  margin-bottom: 50px;
  /* margin: 0px auto; */
  /* width: 860px; */
  /* height: 600px; */
  width: 100%;
  height: 600px;
  background-color: rgb(255, 255, 255);
  /* background-color: #fff; */
}

.sidebar {
  width: 60px;
  height: 600px;
  /* background: #2b2c2f */
  background: #f8d080;
}

.main {
  flex: 1;
  height: 600px;
  background: rgb(243, 243, 243);
  /* background: #f2f2f2; */
}

building {
  background: url("../assets/chat1.png");
  width: 100%;
  height: 100%;
  position: fixed;
 
  background-size: 100% 100%;
}
</style>

选择框

<!-- 最左边的选择框 -->
<template>
	<div class="mycard">
	    <header>
	    	<img :src="user.img" class="avatar">
	    </header>
	    <div class="navbar" @click="clearSearch">
	         <router-link to="/friends" class="icon iconfont icon-msg" ></router-link>
	         <router-link to="/friend" class="icon iconfont icon-friend"></router-link>
	         <router-link to="/chatWithDoctor" class="icon iconfont icon-collection"></router-link>
			 <router-link v-show="health" to="/addFriends" class="icon iconfont icon-search"></router-link>
	   
		</div>
	    <footer>
	        <i class="icon iconfont icon-more"></i>
	    </footer>
	</div>
</template>

<script>
import { mapState } from 'vuex'
export default {
	data: () => ({
    modal:true,
    dialogVisible: false,
    friend:Array(6).fill({}),
    wish:'',
    loading:false,
	health:false
  
  }),

    computed: {
       ...mapState([
       	  'user',
       ])
    },
    methods: {
    	clearSearch() {
    		this.$store.dispatch('search', '')
    	},
    },
	created(){
       
        this.request.get("/test/isHealth",{
            params:{
              uid:JSON.parse(localStorage.getItem("user")).id,
             
            },
          }).then((res) => {
          
            if (res.data.code === "0" && res.data.data===true) {
              this.health=true;
            }
        });
	}
}
</script>

<style lang="stylus" scoped>
@import '../../assets/fonts/iconfont.css'
.mycard
    position: relative
    width: 100%
    height: 100%
    .avatar
	    width: 36px
	    height: 36px
	    margin: 20px 12px 0 12px
	    border-radius: 2px
    .navbar
        width: 100%
        text-align: center
	    .icon
	        display: inline-block
	        font-size: 26px
	        margin-top: 28px
	        padding: 0 16px
	        box-sizing: border-box
	        color: rgb(173,174,175)
	        opacity: 0.8
	        cursor: pointer
	        &.active
	            color: rgb(0,220,65)
	        &:hover
	            opacity: 1;
	    .icon-msg,.icon-more
	        font-size: 22px
	    .icon-msg
	        padding: 0 19px
	footer
	    position: absolute
	    bottom: 20px
	    width: 100%
	    text-align: center
</style>

朋友列表

朋友界面分为两个部分,一个是朋友信息列表,一个是选中后显示选中朋友信息

<template>
  <div class="content">
    <div class="msglist">
      <search></search>
      <chatlist></chatlist>
    </div>
    <div class="chatbox">
      <message></message>
      <vText></vText>
    </div>
  </div>
</template>

<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
import search from '../components/search/search'
import chatlist from '../components/chatlist/chatlist'
import message from '../components/message/message'
import vText from '../components/text/text'


export default {

  //import引入的组件需要注入到对象中才能使用
  components: {
    search,
    chatlist,
    message,
    vText
  }
}


</script>

<style lang="stylus" scoped>
.content
  display: flex
  width: 100%
  .msglist
    width: 250px
    background: rgb(230,230,230)
  .chatbox
    flex: 1
    width:100%
</style>

朋友信息列表

<!-- 好友列表 -->
<template>
 <div class="friendlist">
 	<ul>
        <li v-for="item in searchedFriendlist" class="frienditem"  :class="{ noborder: !item.initial}">
            <div class="list_title" v-if="item.initial">{{item.initial}}</div>
            <div class="friend-info" :class="{ active: item.id === selectFriendId }" @click="selectFriend(item.id)">
                <img class="avatar"  width="36" height="36" :src="item.img">
                <div class="remark">{{item.remark}}</div>
            </div>
        </li>
    </ul>
 </div>
</template>

<script>
import { mapState, mapActions ,mapGetters } from 'vuex'
export default {
    data: () => ({
    img: require('../../assets/chat/images/1.jpg')
  }),
    computed: {
        ...mapState([
            'selectFriendId',
            'searchText'
        ]),
        ...mapGetters([
            'searchedFriendlist'
        ])
    },
    methods: {
        ...mapActions([
             'selectFriend',
        ])  
    }
}
</script>

<style lang="stylus" scoped>
.friendlist
    height: 540px
    width: 250px
    overflow-y: auto
    .frienditem
        border-top: 1px solid #dadada
        &:first-child,&.noborder
            border-top: none
        .list_title
            box-sizing: border-box
            width: 100%
            font-size: 12px
            padding: 15px 0 3px 12px
            color: #999
        .friend-info
            display: flex
            padding: 12px
            transition: background-color .1s
            font-size: 0
            &:hover 
                background-color: rgb(220,220,220)
            &.active 
                background-color: #c4c4c4
            .avatar
                border-radius: 2px
                margin-right: 12px
            .remark
                font-size: 14px
                line-height: 36px



</style>

搜索框

<!-- 搜索框 -->
<template>
<div class="wrapper">
	<div class="search-wrapper">
		<input type="text" class="searchInput" v-model="search" @keyup="change" placeholder="搜索">
		<i class="icon iconfont icon-search" v-show="noText"></i>
		<div class="searchInput-delete" v-show="haveText" @click="del"></div>
	</div>
</div>
</template>

<script>
export default {
	 methods: {
        change () {
        	this.$store.dispatch('search', this.search)
        },
        del () {
            this.search= ''
            this.change()
        }
     },
     data () {
     	return {
     		search: '',
     		active: false
     	}
     },
     computed: {
        noText () {
   	      if(this.search  === '') return true
   	      return false
        },
        haveText () {
   	      if(this.search  === '') return false
   	      return true
        }
     }
}
</script>

<style lang="stylus" scoped>
.wrapper
    padding: 22px 12px 12px 12px
	.search-wrapper
	  position: relative
	  display: flex
	  box-sizing: border-box
	  height: 26px
	  width: 100%
	  background-color: #e5e3e2
	  border: 1px solid #d9d7d6
	  border-radius: 2px
	  .searchInput
	    flex: 1
	    font-size: 12px
	    padding: 6px
	    background-color: #e5e3e2
	    outline: none
	    &:focus
	    	background-color: #f2efee
	  .icon-search
	    display: inline-block
	    width: 24px
	    height: 24px
	    font-size: 14px
	    line-height: 24px
	    text-align: center
	  .searchInput-delete
	    display: block
	    position: absolute
	    outline: none
	    top: 0;
	    right: 0;
	    width: 24px
	    height: 100%
	    background-image: url(delete.png)
	    background-size: 26px
	    background-position: center
	    background-repeat: no-repeat
	    cursor: pointer
</style>

朋友信息

<!-- 好友信息 -->
<template>
   <div  style="overflow-y: scroll;"class="Info-wrapper">
        <div class="newfriend" v-show="selectedFriend.id === 0">
			<div class="box p-5 px-6" style="width: 1500px;height: 500px;">
				<h3 style="font-weight: bold;text-align: left;">好友申请</h3>
    <div class="side-list">
      <div v-for="(request, index) in friendRequests" :key="index" class="side-list-item">
        <img :src="request.avatar" alt="Avatar" class="side-list-image rounded-full">
        <div class="flex-1">
          <h4 style="text-align: left;" class="side-list-title">{{ request.name }}</h4>
          <div class="side-list-info">{{ request.traits.join(", ") }}</div>
          <div class="side-list-info">{{ request.qualities.join(", ") }}</div>
        </div>
        <div style="margin-top: 50px;margin-left: 100px;">
			<el-button type="info"  >拒绝</el-button>
			<el-button type="primary"  >同意</el-button>
         
        </div>
      </div>
    </div>
  </div>

	</div>
	
        <div class="friendInfo" v-show="selectedFriend.id > 0">
	   	    <div class="esInfo" >
	   	    	<div class="left">
	   	    		<div class="people">
	   	    			<div class="nickname">{{selectedFriend.nickname}}</div>
	   	    			<div :class="[selectedFriend.sex===1?'gender-male':'gender-female']"></div>
	   	    		</div>
	   	    		<div class="signature">{{selectedFriend.signature}}</div>
	   	    	</div>
	   	    	<div class="right">
	   	    	    <img class="avatar"  width="60" height="60" :src="selectedFriend.img">
	   	    	</div>
	   	    </div>
	   	    <div class="detInfo">
	   	    	<div class="remark"><span>备&nbsp&nbsp&nbsp注</span>{{selectedFriend.remark}}</div>
	   	    	<div class="area"><span>地&nbsp&nbsp&nbsp区</span>{{selectedFriend.area}}</div>
	   	    	<div class="wxid"><span>微信号</span>{{selectedFriend.wxid}}</div>
	   	    </div>
	   	    <div class="send" @click="send">
    	        <span>发消息</span>
            </div>
	   	</div>
   </div>
</template>

<script>
import router from '../../router'
import { mapGetters } from 'vuex'

export default {
	data: () => ({
    img: '../../assets/chat/images/1.jpg',
	friendRequests: [
        {
          avatar: "../../public/images/avatars/avatar-2.jpg",
          name: "John Michael",
          traits: ["好奇", "探索", "谨慎尝试", "有选择性", "焦虑", "敏感", "紧张", "易尴尬", "内向", "沉默"],
          qualities: ["害羞", "拘谨", "温和", "谦逊", "谨慎", "有同情心", "细致", "认真", "有序", "考虑周全"],
          status:0
		},
		{
          avatar: "../../public/images/avatars/avatar-2.jpg",
          name: "John Michael",
          traits: ["好奇", "探索", "谨慎尝试", "有选择性", "焦虑", "敏感", "紧张", "易尴尬", "内向", "沉默"],
          qualities: ["害羞", "拘谨", "温和", "谦逊", "谨慎", "有同情心", "细致", "认真", "有序", "考虑周全"],
		  status:1
        },
		{
          avatar:"../../public/images/avatars/avatar-2.jpg",
          name: "John Michael",
          traits: ["好奇", "探索", "谨慎尝试", "有选择性", "焦虑", "敏感", "紧张", "易尴尬", "内向", "沉默"],
          qualities: ["害羞", "拘谨", "温和", "谦逊", "谨慎", "有同情心", "细致", "认真", "有序", "考虑周全"],
		  status:2
        },
		{
          avatar: "../../public/images/avatars/avatar-2.jpg",
          name: "John Michael",
          traits: ["好奇", "探索", "谨慎尝试", "有选择性", "焦虑", "敏感", "紧张", "易尴尬", "内向", "沉默"],
          qualities: ["害羞", "拘谨", "温和", "谦逊", "谨慎", "有同情心", "细致", "认真", "有序", "考虑周全"]
        },
		{
          avatar:"../../public/images/avatars/avatar-2.jpg",
          name: "John Michael",
          traits: ["好奇", "探索", "谨慎尝试", "有选择性", "焦虑", "敏感", "紧张", "易尴尬", "内向", "沉默"],
          qualities: ["害羞", "拘谨", "温和", "谦逊", "谨慎", "有同情心", "细致", "认真", "有序", "考虑周全"]
        },
		{
          avatar: "../../public/images/avatars/avatar-2.jpg",
          name: "John Michael",
          traits: ["好奇", "探索", "谨慎尝试", "有选择性", "焦虑", "敏感", "紧张", "易尴尬", "内向", "沉默"],
          qualities: ["害羞", "拘谨", "温和", "谦逊", "谨慎", "有同情心", "细致", "认真", "有序", "考虑周全"]
        },
		{
          avatar:"../../public/images/avatars/avatar-2.jpg",
          name: "John Michael",
          traits: ["好奇", "探索", "谨慎尝试", "有选择性", "焦虑", "敏感", "紧张", "易尴尬", "内向", "沉默"],
          qualities: ["害羞", "拘谨", "温和", "谦逊", "谨慎", "有同情心", "细致", "认真", "有序", "考虑周全"]
        },
		{
          avatar: "../../public/images/avatars/avatar-2.jpg",
          name: "John Michael",
          traits: ["好奇", "探索", "谨慎尝试", "有选择性", "焦虑", "敏感", "紧张", "易尴尬", "内向", "沉默"],
          qualities: ["害羞", "拘谨", "温和", "谦逊", "谨慎", "有同情心", "细致", "认真", "有序", "考虑周全"]
        },
        // 添加更多好友申请数据...
      ]
  }),
    computed: {
        ...mapGetters([
            'selectedFriend'
        ])
    },
    methods: {
    	send () {
    		this.$store.dispatch('send')
    		this.$store.dispatch('search', '')
    	}
    }
}
</script>
<style scoped>


.side-list {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.side-list-item {
    display: flex;
    align-items: center;
    gap: 20px;
	
}

.side-list-image {
    width: 50px;
    height: 50px;
    border-radius: 50%;
}

.side-list-title {
    font-weight: bold;
}

.side-list-info {
    color: #666;
}

.button {
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
}

.bg-primary {
    background-color: #007bff;
    color: #fff;
}

.bg-secondery {
    background-color: #6c757d;
    color: #fff;
}

.button:hover {
    opacity: 0.8;
}
</style>
<style lang="stylus" scoped>
.newfriend
    height: 100%
    padding: 28px 0 0 30px
    box-sizing: border-box
    border-bottom: 1px solid #e7e7e7
    .nickname
        font-size: 18px
.friendInfo
    padding: 0 90px
	.esInfo
	    display: flex
	    align-items: center
	    padding: 100px 0 45px 0
	    .left
	        flex: 1
	        .people
	            .nickname
	                display: inline-block
	                font-size: 20px
	                margin-bottom: 16px
	            .gender-male,.gender-female
	                display: inline-block
	                width: 18px
	                height: 18px
	                vertical-align: top
	                margin-top: 2px
	            .gender-male
	                background-image: url(man.png)
	                background-size: cover
	            .gender-female
	                background-image: url(woman.png)
	                background-size: cover
	        .signature
	            font-size: 14px
	            color: rgba(153,153,153,.8)
	    .right
	        .avatar
	            border-radius: 3px
	.detInfo
	    padding: 40px 0
	    border-top: 1px solid #e7e7e7
	    border-bottom: 1px solid #e7e7e7
	    .remark,.area,.wxid
	        font-size: 14px
	        margin-top: 20px
	        span
	            font-size: 14px
	            color: rgba(153,153,153,.8)
	            margin-right: 40px
	    .remark
	        margin-top: 0
	.send
        position: relative
        text-align: center
        width: 140px
        height: 36px
        left: 115px
        top: 50px
        line-height: 36px
        font-size: 14px
        color: #fff
        background-color: #1aad19
        cursor: pointer
        border-radius: 2px
        &:hover
            background: rgb(18,150,17)
</style>

聊天界面

分为四个部分,除了搜索框(代码已经贴过)外,还有聊天列表页面、显示信息界面、发送信息界面

聊天列表

<!-- 聊天列表 -->
<template>
    <div class="msglist">
        <ul>
            <li v-for="item in searchedChatlist" class="sessionlist" :class="{ active: item.id === selectId }"
                @click="selectSession(item.id)">
                <div class="list-left">
                    <img class="avatar" width="42" height="42" :src="item.user.img" :alt="item.user.name" >
                </div>
                <div class="list-right">
                    <p class="name">{{ item.user.name }}</p>
                    <span class="time">{{ item.messages[item.messages.length - 1].date | time }}</span>
                   <!-- <p class="lastmsg">{{ item.messages[item.messages.length - 1].content }}</p>-->
                </div>
            </li>
        </ul>
    </div>
</template>

<script>
import { mapState, mapActions, mapGetters } from 'vuex'
import axios from 'axios'
export default {
    
    created() {
        this.fetchMessage();  
    },
    computed: {
        ...mapState([
            'selectId',
            'searchText'
        ]),
        ...mapGetters([
            'searchedChatlist'
        ])
    },
    methods: {
        fetchMessage() {
            const user = JSON.parse(localStorage.getItem('user'));
            //var params = new URLSearchParams();
        //params.append('username', '123456');
        // 发送POST请求  
            axios.post('http://localhost:9966/message/getMessage', {
                username: user.uname,
        }, {
                headers: {
                    'Content-Type':'application/json'
                }
            })  
  .then(response => {  
    // 假设后端返回的是一个List<GetMessageVO>的JSON数组  
    const messagesFromBackend = response.data; // 提取后端返回的数据  
  
    // 将后端返回的数据添加到chatlist中  
    // 你可能需要使用Vuex的mutation来确保状态更新的正确性  
    this.$store.commit('addMessagesToList', messagesFromBackend);  
  })  
  .catch(error => {  
    console.error('Error fetching messages:', error);  
  });
        },
        ...mapActions([
            'selectSession',
        ])
    },
    filters: {
        // 将日期过滤为 hour:minutes
        time(date) {
            //month =data.getMonth() < 9 ? "0" + (data.getMonth() + 1) : data.getMonth() + 1;
            if (typeof date === 'string') {
                date = new Date(date);
            }
            if (date.getMinutes() < 10) {
                return date.getHours() + ':0' + date.getMinutes();
            } else {
                return date.getHours() + ':' + date.getMinutes();
            }
        }
    },
}
</script>

<style lang="stylus" scoped>
.msglist
  height: 540px
  overflow-y: auto
  .sessionlist
    display: flex
    padding: 12px
    transition: background-color .1s
    font-size: 0
    &:hover 
        background-color: rgb(220,220,220)
    &.active 
        background-color: #c4c4c4
    .avatar
        border-radius: 2px
        margin-right: 12px
    .list-right
        position: relative
        flex: 1
        margin-top: 4px
	    .name
	        display: inline-block
	        vertical-align: top
	        font-size: 14px
	    .time
	        float: right
	        color: #999
	        font-size: 10px
	        vertical-align: top
        .lastmsg
            position: absolute
            font-size: 12px
            width: 130px
            height: 15px
            line-height: 15px
            color: #999
            bottom: 4px
            overflow: hidden
            white-space:nowrap
            text-overflow:ellipsis
</style>

信息显示

<!-- 消息框 -->
<template>
  <div class="message">
      <header class="header">
          <div class="friendname">{{ selectedChat.user.name }}</div>
      </header>
      <div class="message-wrapper" ref="list">
          <ul v-if="selectedChat">
              <li v-for="(item, i) in selectedChat.messages" class="message-item" :key="i">
                  <div class="time"><span>{{ selectedChat.messages[i].date | time }}</span></div>
                  <div class="main" :class="{ self: item.self }">
                      <img class="avatar" width="36" height="36"
                          :src="item.self ? user.img : selectedChat.user.img" />
                      <div class="content">
                          <div class="text" v-html="replaceFace(item.content)"></div>
                      </div>
                  </div>
              </li>
          </ul>
      </div>
  </div>
</template>

<script>
import { mapGetters, mapState } from 'vuex'
export default {
    /*data() {
     return {
       selectedChat: {
         user: {
           name: "John Doe",
           img: "public/images/avatars/avatar-4.jpg"
         },
         messages: [
           {
             date: "2024-05-05T12:00:00",
             self: false,
             content: "Hey there! How are you?"
           },
           {
             date: "2024-05-05T12:05:00",
             self: true,
             content: "Hi! I'm doing well, thanks. How about you?"
          },
           {
             date: "2024-05-05T12:10:00",
             self: false,
             content: "I'm good too. Just busy with work."
           }
         ]
       },
       user: {
         name: "You",
         img: "public/images/avatars/avatar-5.jpg"
       }
     };
   },*/
  computed: {
      ...mapGetters([
          'selectedChat',
          'messages'
      ]),
      ...mapState([
          'user',
          'emojis'
      ])
  },
  mounted() {
      //  在页面加载时让信息滚动到最下面
      setTimeout(() => this.$refs.list.scrollTop = this.$refs.list.scrollHeight, 0)
  },
  watch: {
      // 发送信息后,让信息滚动到最下面
      messages() {
          setTimeout(() => this.$refs.list.scrollTop = this.$refs.list.scrollHeight, 0)
      }
  },
  methods: {
      //  在发送信息之后,将输入的内容中属于表情的部分替换成emoji图片标签
      //  再经过v-html 渲染成真正的图片
    replaceFace(con) {
      
          if (con.includes('/:')) {
              var emojis = this.emojis;
              for (var i = 0; i < emojis.length; i++) {
                  con = con.replace(emojis[i].reg, '<img src="static/emoji/' + emojis[i].file + '"  alt="" style="vertical-align: middle; width: 24px; height: 24px" />');
              }
              return con;
          }
          return con;
      }
  },
  filters: {
      // 将日期过滤为 hour:minutes
      time(date) {
          
          console.log('time的++', date);
          if (typeof date === 'string') {
              date = new Date(date);
          }
          if (date.getMinutes() < 10) {
              return date.getHours() + ':0' + date.getMinutes();
          } else {
              return date.getHours() + ':' + date.getMinutes();
          }
      }
  }
}
</script>

<style lang="stylus" scoped>
.message
  width: 100%
  height: 450px
  .header
    height: 60px
    padding: 28px 0 0 30px
    box-sizing: border-box
    border-bottom: 1px solid #e7e7e7
    .friendname
      font-size: 18px
  .message-wrapper
    min-height: 390px
    max-height: 390px
    padding: 10px 15px
    box-sizing: border-box
    overflow-y: auto
    border-bottom: 1px solid #e7e7e7
    .message
      margin-bottom: 15px
    .time
      width: 100%
      font-size: 12px
      margin: 7px auto
      text-align: center
      span
        display: inline-block
        padding: 4px 6px
        color: #fff
        border-radius: 3px
        background-color: #dcdcdc
    .main
      display: flex
      align-items: flex-start
      &.self
        justify-content: flex-end
      .avatar 
        border-radius: 3px
        width: 36px
        height: 36px
        margin-left: 10px
      .content
        margin-left: 10px
        padding: 6px 10px
        max-width: 330px
        line-height: 24px
        box-sizing: border-box
        font-size: 14px
        word-break: break-all
        background-color: #fafafa
        border-radius: 4px
        text-align: left
        &.self
          margin-right: 10px
          margin-left: 0
          background-color: #b2e281
        &:before
          content: " "
          position: absolute
          top: 50%
          transform: translateY(-50%)
          border-width: 6px
          border-style: solid
          border-color: transparent
          &.self
            right: -12px
            border-left-color: #b2e281
          &:not(.self)
            left: -12px
            border-right-color: #fafafa

</style>

发送

这个vue页面主要是将发送信息的那个输入框和显示信息的message.vue分开了

<!-- 文本输入框 -->
<template>
    <div class="text">
        <div class="emoji">
            <i class="icon iconfont icon-look" @click="showEmoji = !showEmoji"></i>
            <transition name="showbox">
                <div class="emojiBox" v-show="showEmoji">
                    <li v-for="(item, index) in icon" @click="content += item">
                        {{ item }}
                    </li>
                </div>
            </transition>
        </div>
        <textarea ref="text" v-model="content" @keyup="onKeyup" @click="showEmoji = false">
   </textarea>
        <div class="send" @click="send">
            <span>发送(ent)</span>
        </div>
        <transition name="appear">
            <div class="warn" v-show="warn">
                <div class="description">不能发送空白信息</div>
            </div>
        </transition>
    </div>
</template>

<script>
import { mapGetters, mapState } from 'vuex'
let socket;
export default {
    data() {
        return {
            content: '',
            reply: '未找到',
            frequency: 0,
            warn: false,
            showEmoji: false,

        };
    },
    computed: {
        ...mapState([
            'selectId',
            'emojis',
            'icon'
        ]),
        ...mapGetters([
            'selectedChat',
        ])
    },
    methods: {
        getImageUrl(file) {
            return require(`../../assets/chat/emoji/${file}`);

        },

        // 按回车发送信息
        onKeyup(e) {
            if (e.keyCode === 13) {
                this.send()
            }
        },
        // 点击发送按钮发送信息
        send() {
            if (this.content.length <= 1) {
                this.warn = true
                this.content = ''
                setTimeout(() => {
                    this.warn = false;
                }, 1000)
            } else {
                if (typeof (WebSocket) == "undefined") {
                    console.log("您的浏览器不支持WebSocket");
                } else {
                    console.log("开始连接服务器");
                    //const user = JSON.parse(localStorage.getItem('user'))
                    //let message = {from: user.uname,to:}
                }
                    
                 
                    var msg = {
                        content: this.content,
                    }
                    this.content = ''
                    this.$store.dispatch('sendMessage', msg)

                
            }
        }
    },
    // 在进入的时候 聚焦输入框
    mounted() {
        this.$refs.text.focus()
    },
    watch: {
        // 在选择其它对话的时候 聚焦输入框
        selectId() {
            setTimeout(() => {
                this.$refs.text.focus()
            }, 0)
        },
        // 当输入框中的值为空时 弹出提示  并在一秒后消失
        content() {
            if (this.content === '') {
                if (this.frequency === 0) {
                    this.warn = true;
                    this.frequency++
                    setTimeout(() => {
                        this.warn = false;
                    }, 1000)
                }
            }
        }
    }
}
</script>

<style lang="stylus" scoped>
.text
    position: relative
    height: 150px
    background: rgb(243, 243, 243)
    .emoji
        position: relative
        width: 100%
        height: 40px
        line-height: 40px
        font-size: 12px
        padding: 0 30px
        box-sizing: border-box
        color: #7c7c7c
        .icon-look
            cursor: pointer
            &:hover
                color: #1aad19
        .emojiBox
            position: absolute
            display: flex
            flex-wrap: wrap
            top: -210px
            left: -100px
            width: 300px
            overflow-y: auto
            max-height: 200px
            padding: 5px
            background-color: #fff
            border: 1px solid #d1d1d1
            border-radius: 2px
            box-shadow:0 1px 2px 1px #d1d1d1
            &.showbox-enter-active, &.showbox-leave-active
                transition: all .5s
            &.showbox-enter,&.showbox-leave-active
                opacity: 0
    textarea
        box-sizing: border-box
        padding: 0 30px
        height: 110px
        width: 100%
        border: none
        outline: none
        font-family: "Micrsofot Yahei"
        resize: none
        background-color: rgb(243, 243, 243)
    .send
        position: absolute
        bottom: 10px
        right: 30px
        width: 75px
        height: 28px
        line-height: 28px
        box-sizing: border-box
        text-align: center
        border: 1px solid #e5e5e5
        border-radius: 3px
        background: #f5f5f5
        font-size: 14px
        color: #7c7c7c
        &:hover
            background: rgb(18,150,17)
            color: #fff
    .warn
         position: absolute
         bottom: 50px
         right: 10px
         width: 110px
         height: 30px
         line-height: 30px
         font-size: 12px
         text-align: center
         border: 1px solid #bdbdbd
         border-radius: 4px
         box-shadow:0 1px 5px 1px #bdbdbd
         &.appear-enter-active, &.appear-leave-active
            transition: all 1s
         &.appear-enter,&.appear-leave-active
            opacity: 0
         &:before
            content: " "
            position: absolute
            top: 100%
            right: 20px
            border: 7px solid transparent
            border-top-color: #fff
            filter:drop-shadow(1px 3px 2px #bdbdbd)
</style>

总结

本周没有什么特别的难点,但是好久没有用到vue,好多知识已经遗忘,而且组件还这么多,因此写的时候很痛苦,当时遇到了好多问题。不过因为当时没有写博客,所以这里直接将代码帖了上来,实际上,这些是改动后的代码,还有js部分也是我后来才写的,这里也直接贴了上去,懒得分了,然后就是医生端和用户端大同小异,因此博客中就没有写。

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值