feat: 消息列表

feature/task1.0.0__0514__ch
向文可 2 years ago
parent 53119f16e3
commit e3c281c73c

@ -4,8 +4,8 @@
<div class="body">
<div class="aside">
<div class="aside-header">近期会话</div>
<ul class="session-list">
<li v-for="(item, index) in sessionList" :key="index" class="session-item">
<el-scrollbar class="session-list">
<div v-for="(item, index) in sessionList" :key="index" class="session-item">
<el-badge class="session-count" :hidden="item.count === 0" :max="99" :value="item.count">
<el-avatar circle :src="item.avatar" />
</el-badge>
@ -18,8 +18,8 @@
<div class="session-content">{{ item.content }}</div>
</div>
</div>
</li>
</ul>
</div>
</el-scrollbar>
</div>
<div class="content">
<div class="content-header">
@ -29,10 +29,13 @@
</div>
</div>
<div class="content-header-right">
<el-button>个人订单</el-button>
<el-button>转移会话</el-button>
</div>
</div>
<div class="message-list"></div>
<el-scrollbar class="message-list">
<MessageItem v-for="(item, index) in sessionMessageList" :key="index" :message="item" />
</el-scrollbar>
<div class="operation-bar">
<el-button type="text">
<el-icon name="chat-smile-3-fill" size="24" />
@ -56,6 +59,7 @@
</template>
<script setup>
import MessageItem from './message.vue';
const sessionList = reactive([
{
name: '小可爱',
@ -86,18 +90,96 @@
const currentSession = computed(() => {
return sessionList[state.currentIndex];
});
const sessionMessageList = reactive([
{
type: 'text',
content: '你好,请问这个能有优惠吗?',
time: '2019-12-12',
from: 'customer',
avatar: 'https://placem.at/people',
name: '小可爱',
},
{
type: 'notify',
content: '小马 将该会话转移给 小艾,并留言:发货问题',
time: '2019-12-12',
from: 'system',
},
{
type: 'text',
content: '没有',
time: '2019-12-12',
from: 'employee',
avatar: 'https://placem.at/people',
name: '小爱',
},
{
type: 'product',
content: `{
"id": 18,
"name": "柏战K20青轴机械键盘 混光机械键盘青轴电竞网吧游戏键盘电脑键盘",
"categoryId": 51,
"startingPrice": 79.0,
"totalStock": 1200,
"mainPicture": "https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/mall-product/productO1CN011nFEoP1DrheUNhNgU_!!3435280270-0-cib.jpg",
"remoteAreaPostage": 10.0,
"singleBuyLimit": 0,
"isEnable": true,
"remark": "柏战K20青轴机械键盘 混光机械键盘青轴电竞网吧游戏键盘电脑键盘"
}`,
time: '2019-12-12',
from: 'customer',
avatar: 'https://placem.at/people',
name: '小可爱',
},
{
type: 'order',
content: `{
"orderId": 392016,
"orderNo": "6391f99d063e",
"userId": 513,
"userPhone": "17683712911",
"payAmount": 859.0,
"orderStatus": 2,
"orderStatusDesc": "已关闭",
"payType": 1,
"payTypeDesc": "未支付",
"orderSource": 2,
"orderSourceDesc": "安卓端APP",
"submitTime": "2022-05-10 20:36:59",
"product": {
"id": 18,
"name": "柏战K20青轴机械键盘 混光机械键盘青轴电竞网吧游戏键盘电脑键盘",
"categoryId": 51,
"startingPrice": 79.0,
"totalStock": 1200,
"mainPicture": "https://msb-edu-dev.oss-cn-beijing.aliyuncs.com/mall-product/productO1CN011nFEoP1DrheUNhNgU_!!3435280270-0-cib.jpg",
"remoteAreaPostage": 10.0,
"singleBuyLimit": 0,
"isEnable": true,
"remark": "柏战K20青轴机械键盘 混光机械键盘青轴电竞网吧游戏键盘电脑键盘"
}
}`,
time: '2019-12-12',
from: 'customer',
avatar: 'https://placem.at/people',
name: '小可爱',
},
]);
</script>
<style lang="less" scoped>
.chat-container {
display: flex;
flex-direction: column;
overflow: hidden;
.header {
padding: @layout-space 0;
}
.body {
width: 100%;
height: 100%;
flex: 1;
overflow: hidden;
display: flex;
border: 1px solid #eee;
.aside {
@ -190,6 +272,7 @@
}
.message-list {
flex: 1;
background-color: #f1f1f1;
}
.operation-bar {
display: flex;

@ -0,0 +1,185 @@
<template>
<div
class="message-item"
:class="{
[`--${props.message.type}`]: true,
'--self': props.message.from === 'employee',
}"
>
<div v-if="props.message.avatar" class="avatar">
<el-avatar :src="props.message.avatar" />
</div>
<div class="message-body">
<div class="name">
{{ props.message.name }}
</div>
<el-card v-if="props.message.type === 'product'" class="shadow">
<template #header>
<div class="flex">
<div class="left">商品编号{{ product.id }}</div>
<el-button type="text">复制</el-button>
</div>
</template>
<div class="flex">
<el-image :alt="product.name" height="64px" :src="product.mainPicture" width="64px" />
<div class="right">
<div class="name">{{ product.name }}</div>
<div class="price">{{ product.startingPrice }}</div>
</div>
</div>
<div class="footer">
<el-button>商品规格属性</el-button>
</div>
</el-card>
<el-card v-else-if="props.message.type === 'order'" class="shadow">
<template #header>
<div class="flex">
<div class="status">{{ order.orderStatusDesc }}</div>
<div class="service">售后中</div>
</div>
<div class="flex">
<div class="no">订单编号{{ order.orderNo }}</div>
<el-button type="text">复制</el-button>
</div>
</template>
<div class="flex">
<el-image :alt="order.product.name" height="64px" :src="order.product.mainPicture" width="64px" />
<div class="right">
<div class="flex">
<div class="name">{{ order.product.name }}</div>
<div class="price">{{ order.product.startingPrice }}</div>
</div>
<div class="flex">
<div class="sku">{{ order.product.sku || '默认规格' }}</div>
<div class="count">x{{ order.count || 1 }}</div>
</div>
</div>
</div>
<div class="footer">
<el-button>查看详情</el-button>
</div>
</el-card>
<div v-else class="content" :class="{ shadow: props.message.type === 'text' }">
{{ props.message.content }}
</div>
</div>
<div v-if="props.message.type !== 'notify'" class="time">
{{ props.message.time }}
</div>
</div>
</template>
<script setup>
const props = defineProps({
message: {
type: Object,
required: true,
},
});
const product = computed(() => {
return props.message.type === 'product' ? JSON.parse(props.message.content) : {};
});
const order = computed(() => {
return props.message.type === 'order' ? JSON.parse(props.message.content) : {};
});
</script>
<style lang="less" scoped>
.message-item {
display: flex;
& + .message-item {
margin-top: @layout-space;
}
&:first-child {
margin-top: @layout-space;
}
&:last-child {
margin-bottom: @layout-space;
}
.flex {
display: flex;
justify-content: space-between;
align-items: center;
}
.avatar {
margin: 0 @layout-space;
}
.name {
font-size: 14px;
margin-bottom: @layout-space-small;
}
.time {
font-size: 12px;
margin: auto @layout-space 0;
color: #ccc;
}
.content {
width: max-content;
height: max-content;
max-width: 300px;
padding: @layout-space-small @layout-space;
border-radius: @layout-border-radius;
color: #000;
background-color: #fff;
}
.el-card {
max-width: 360px;
:deep(.el-card__header) {
padding: @layout-space;
}
:deep(.el-card__body) {
padding: @layout-space;
}
.el-image {
margin-right: @layout-space;
flex-shrink: 0;
}
.service,
.no {
font-size: 14px;
}
.sku,
.count {
font-size: 12px;
margin-top: @layout-space;
}
.price {
flex-shrink: 0;
font-size: 12px;
color: var(--el-color-danger);
margin-top: @layout-space;
}
.footer {
margin-top: @layout-space;
padding-top: @layout-space;
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
}
}
.shadow {
box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.1);
}
&.--self {
flex-direction: row-reverse;
.message-body {
text-align: right;
.content {
color: #fff;
background-color: var(--el-color-primary);
}
}
}
&.--notify {
.message-body {
margin: auto;
.content {
max-width: unset;
background-color: rgba(0, 0, 0, 0.05);
color: rgba(0, 0, 0, 0.3);
font-size: 14px;
}
}
}
}
</style>
Loading…
Cancel
Save