17 changed files with 301 additions and 681 deletions
Unified View
Diff Options
-
4mock/sys/user.ts
-
0src/api/clue/index.ts
-
30src/api/message/model.ts
-
6src/locales/lang/zh-CN/routes/clue.ts
-
38src/router/menu.ts
-
24src/router/menus/modules/clue.ts
-
20src/router/menus/modules/message.ts
-
49src/router/routes/modules/clue.ts
-
40src/router/routes/modules/message.ts
-
2src/settings/projectSetting.ts
-
0src/views/clue/clueList/data.ts
-
71src/views/clue/clueList/index.vue
-
26src/views/clue/cluePool/data.ts
-
72src/views/clue/cluePool/index.vue
-
26src/views/clue/customer/data.ts
-
2src/views/clue/customer/index.vue
-
572src/views/message/chatInfo/index.vue
@ -1,30 +0,0 @@ |
|||||
|
|
||||
export interface MessageItemModel { |
|
||||
nickName: string |
|
||||
contentTime: string |
|
||||
miId: string |
|
||||
userMarriageInformationType: number |
|
||||
} |
|
||||
|
|
||||
export interface MessageRoomModel { |
|
||||
cityName: string |
|
||||
finalActivityTime: string |
|
||||
miId: string |
|
||||
finalContent: string |
|
||||
genderCode: number |
|
||||
roomId: string |
|
||||
roomName: string |
|
||||
roomPic: string |
|
||||
unreadContentCount: number |
|
||||
} |
|
||||
|
|
||||
export interface MessageModel { |
|
||||
content: string |
|
||||
contentTime: string |
|
||||
readStatus: boolean |
|
||||
finalContent: string |
|
||||
roomContentRecordId: number |
|
||||
roomId: string |
|
||||
sendMiId: string |
|
||||
type: number |
|
||||
} |
|
||||
@ -0,0 +1,6 @@ |
|||||
|
export default { |
||||
|
clue: '线索管理', |
||||
|
cluePool: '线索池', |
||||
|
clueList: '我的线索', |
||||
|
customer: '客户信息' |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
import type { MenuModule } from '/@/router/types' |
||||
|
import { t } from '/@/hooks/web/useI18n' |
||||
|
const clueMenu: MenuModule = { |
||||
|
orderNo: 90003, |
||||
|
menu: { |
||||
|
path: '/clue', |
||||
|
name: t('routes.clue.clue'), |
||||
|
children: [ |
||||
|
{ |
||||
|
path: 'cluePool', |
||||
|
name: t('routes.clue.cluePool'), |
||||
|
}, |
||||
|
{ |
||||
|
path: 'clueList', |
||||
|
name: t('routes.clue.clueList'), |
||||
|
}, |
||||
|
{ |
||||
|
path: 'customer', |
||||
|
name: t('routes.clue.customer'), |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
} |
||||
|
export default clueMenu |
||||
@ -1,20 +0,0 @@ |
|||||
import type { MenuModule } from '/@/router/types' |
|
||||
import { t } from '/@/hooks/web/useI18n' |
|
||||
const messageMenu: MenuModule = { |
|
||||
orderNo: 90003, |
|
||||
menu: { |
|
||||
path: '/message', |
|
||||
name: t('routes.message.message'), |
|
||||
children: [ |
|
||||
{ |
|
||||
path: 'messageList', |
|
||||
name: t('routes.message.messageList'), |
|
||||
}, |
|
||||
{ |
|
||||
path: 'chatInfo', |
|
||||
name: t('routes.message.chatInfo'), |
|
||||
}, |
|
||||
], |
|
||||
}, |
|
||||
} |
|
||||
export default messageMenu |
|
||||
@ -0,0 +1,49 @@ |
|||||
|
import type { AppRouteModule } from '/@/router/types' |
||||
|
|
||||
|
import { LAYOUT } from '/@/router/constant' |
||||
|
import { t } from '/@/hooks/web/useI18n' |
||||
|
|
||||
|
const messageRoute: AppRouteModule = { |
||||
|
path: '/clue', |
||||
|
name: 'Clue', |
||||
|
component: LAYOUT, |
||||
|
redirect: '/clue/cluePool', |
||||
|
meta: { |
||||
|
orderNo: 90013, |
||||
|
hideChildrenInMenu: false, |
||||
|
icon: 'ant-design:dribbble-circle-filled', |
||||
|
title: t('routes.clue.clue'), |
||||
|
}, |
||||
|
children: [ |
||||
|
{ |
||||
|
path: 'cluePool', |
||||
|
name: 'CluePool', |
||||
|
component: () => import('/src/views/clue/cluePool/index.vue'), |
||||
|
meta: { |
||||
|
// roles: ['/staff/staff'],
|
||||
|
title: t('routes.clue.cluePool'), |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
path: 'clueList', |
||||
|
name: 'ClueList', |
||||
|
component: () => import('/src/views/clue/clueList/index.vue'), |
||||
|
meta: { |
||||
|
// roles: ['/staff/staff'],
|
||||
|
title: t('routes.clue.clueList'), |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
path: 'customer', |
||||
|
name: 'Customer', |
||||
|
component: () => import('/src/views/clue/customer/index.vue'), |
||||
|
meta: { |
||||
|
// roles: ['/staff/staff'],
|
||||
|
title: t('routes.clue.customer'), |
||||
|
hideMenu: true, |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
} |
||||
|
|
||||
|
export default messageRoute |
||||
@ -1,40 +0,0 @@ |
|||||
import type { AppRouteModule } from '/@/router/types' |
|
||||
|
|
||||
import { LAYOUT } from '/@/router/constant' |
|
||||
import { t } from '/@/hooks/web/useI18n' |
|
||||
|
|
||||
const messageRoute: AppRouteModule = { |
|
||||
path: '/message', |
|
||||
name: 'Message', |
|
||||
component: LAYOUT, |
|
||||
redirect: '/message/messageList', |
|
||||
meta: { |
|
||||
orderNo: 90013, |
|
||||
hideChildrenInMenu: false, |
|
||||
icon: 'ant-design:send-outlined', |
|
||||
title: t('routes.message.message'), |
|
||||
}, |
|
||||
children: [ |
|
||||
{ |
|
||||
path: 'messageList', |
|
||||
name: 'MessageList', |
|
||||
component: () => import('/src/views/message/messageList/index.vue'), |
|
||||
meta: { |
|
||||
// roles: ['/staff/staff'],
|
|
||||
title: t('routes.message.message'), |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
path: 'chatInfo', |
|
||||
name: 'ChatInfo', |
|
||||
component: () => import('/src/views/message/chatInfo/index.vue'), |
|
||||
meta: { |
|
||||
// roles: ['/staff/staff'],
|
|
||||
title: t('routes.message.chatInfo'), |
|
||||
hideMenu: true, |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
} |
|
||||
|
|
||||
export default messageRoute |
|
||||
@ -0,0 +1,71 @@ |
|||||
|
<template> |
||||
|
<div class="order-list"> |
||||
|
<BasicTable @register="registerTable"> |
||||
|
<template #action="{ record }"> |
||||
|
<TableAction |
||||
|
:actions="[ |
||||
|
{ |
||||
|
label: '详情', |
||||
|
onClick: toDetail.bind(null, record), |
||||
|
}, |
||||
|
]" |
||||
|
/> |
||||
|
</template> |
||||
|
</BasicTable> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
export default { |
||||
|
name: 'OrderList', |
||||
|
} |
||||
|
</script> |
||||
|
<script setup lang="ts"> |
||||
|
import moment from 'moment/moment' |
||||
|
import { computed, ref } from 'vue' |
||||
|
import { Card } from 'ant-design-vue' |
||||
|
import { useRouter } from 'vue-router' |
||||
|
import { tableColumns, tableFormSchema } from './data' |
||||
|
import { BasicTable, useTable, TableAction } from '/@/components/Table' |
||||
|
import { getChatMessagePage } from '/@/api/clue' |
||||
|
|
||||
|
const [registerTable] = useTable({ |
||||
|
bordered: true, |
||||
|
useSearchForm: true, |
||||
|
columns: tableColumns, |
||||
|
showIndexColumn: true, |
||||
|
showTableSetting: false, |
||||
|
api: getChatMessagePage, |
||||
|
formConfig: { |
||||
|
labelWidth: 120, |
||||
|
schemas: tableFormSchema, |
||||
|
}, |
||||
|
// beforeFetch: (arg) => { |
||||
|
// const { orderTime } = arg |
||||
|
// if (orderTime) { |
||||
|
// arg.orderTimeFrom = moment(orderTime[0]).format('YYYY-MM-DD 00:00:00') |
||||
|
// arg.orderTimeTo = moment(orderTime[1]).format('YYYY-MM-DD 23:59:59') |
||||
|
// delete arg.orderTime |
||||
|
// } |
||||
|
// }, |
||||
|
actionColumn: { |
||||
|
width: 160, |
||||
|
title: '操作', |
||||
|
fixed: 'right', |
||||
|
dataIndex: 'action', |
||||
|
slots: { customRender: 'action' }, |
||||
|
}, |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
const router = useRouter() |
||||
|
function toDetail(record: any) { |
||||
|
const { miId, userMarriageInformationType } = record |
||||
|
router.push({ |
||||
|
query: { miId, type: userMarriageInformationType }, |
||||
|
path: '/message/chatInfo', |
||||
|
}) |
||||
|
} |
||||
|
</script> |
||||
|
<style scoped lang="less"> |
||||
|
</style> |
||||
@ -0,0 +1,26 @@ |
|||||
|
import { BasicColumn, FormSchema } from '/@/components/Table' |
||||
|
const userTypeList = [ |
||||
|
{ label: '正常用户', value: 1 }, |
||||
|
{ label: '录入用户', value: 2}, |
||||
|
{ label: '红娘', value: 3 }, |
||||
|
] |
||||
|
|
||||
|
export const tableColumns: BasicColumn[] = [ |
||||
|
{ title: '用户昵称', dataIndex: 'nickName' }, |
||||
|
{ title: '用户身份', dataIndex: 'userMarriageInformationType', |
||||
|
customRender: ({ text }) => { |
||||
|
return userTypeList.find((find) => find.value === text)?.label |
||||
|
}, |
||||
|
}, |
||||
|
// { title: '客户手机号', dataIndex: 'userPhone' },
|
||||
|
{ title: '最新消息时间', dataIndex: 'contentTime' }, |
||||
|
] |
||||
|
|
||||
|
export const tableFormSchema: FormSchema[] = [ |
||||
|
{ |
||||
|
field: 'nickName', |
||||
|
label: '用户昵称', |
||||
|
component: 'Input', |
||||
|
colProps: { span: 8}, |
||||
|
}, |
||||
|
] |
||||
@ -0,0 +1,72 @@ |
|||||
|
<template> |
||||
|
<div class="order-list"> |
||||
|
<BasicTable @register="registerTable"> |
||||
|
<template #action="{ record }"> |
||||
|
<TableAction |
||||
|
:actions="[ |
||||
|
{ |
||||
|
label: '详情', |
||||
|
onClick: toDetail.bind(null, record), |
||||
|
}, |
||||
|
]" |
||||
|
/> |
||||
|
</template> |
||||
|
</BasicTable> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
export default { |
||||
|
name: 'OrderList', |
||||
|
} |
||||
|
</script> |
||||
|
<script setup lang="ts"> |
||||
|
import moment from 'moment/moment' |
||||
|
import { computed, ref } from 'vue' |
||||
|
import { Card } from 'ant-design-vue' |
||||
|
import { useRouter } from 'vue-router' |
||||
|
import { tableColumns, tableFormSchema } from './data' |
||||
|
import { BasicTable, useTable, TableAction } from '/@/components/Table' |
||||
|
import { getChatMessagePage } from '/@/api/clue' |
||||
|
|
||||
|
const [registerTable] = useTable({ |
||||
|
bordered: true, |
||||
|
useSearchForm: true, |
||||
|
columns: tableColumns, |
||||
|
showIndexColumn: true, |
||||
|
showTableSetting: false, |
||||
|
api: getChatMessagePage, |
||||
|
formConfig: { |
||||
|
labelWidth: 120, |
||||
|
schemas: tableFormSchema, |
||||
|
}, |
||||
|
// beforeFetch: (arg) => { |
||||
|
// const { orderTime } = arg |
||||
|
// if (orderTime) { |
||||
|
// arg.orderTimeFrom = moment(orderTime[0]).format('YYYY-MM-DD 00:00:00') |
||||
|
// arg.orderTimeTo = moment(orderTime[1]).format('YYYY-MM-DD 23:59:59') |
||||
|
// delete arg.orderTime |
||||
|
// } |
||||
|
// }, |
||||
|
actionColumn: { |
||||
|
width: 160, |
||||
|
title: '操作', |
||||
|
fixed: 'right', |
||||
|
dataIndex: 'action', |
||||
|
slots: { customRender: 'action' }, |
||||
|
}, |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
const router = useRouter() |
||||
|
function toDetail(record: any) { |
||||
|
const { miId, userMarriageInformationType } = record |
||||
|
router.push({ |
||||
|
query: { miId, type: userMarriageInformationType }, |
||||
|
path: '/message/chatInfo', |
||||
|
}) |
||||
|
} |
||||
|
</script> |
||||
|
<style scoped lang="less"> |
||||
|
|
||||
|
</style> |
||||
@ -0,0 +1,26 @@ |
|||||
|
import { BasicColumn, FormSchema } from '/@/components/Table' |
||||
|
const userTypeList = [ |
||||
|
{ label: '正常用户', value: 1 }, |
||||
|
{ label: '录入用户', value: 2}, |
||||
|
{ label: '红娘', value: 3 }, |
||||
|
] |
||||
|
|
||||
|
export const tableColumns: BasicColumn[] = [ |
||||
|
{ title: '用户昵称', dataIndex: 'nickName' }, |
||||
|
{ title: '用户身份', dataIndex: 'userMarriageInformationType', |
||||
|
customRender: ({ text }) => { |
||||
|
return userTypeList.find((find) => find.value === text)?.label |
||||
|
}, |
||||
|
}, |
||||
|
// { title: '客户手机号', dataIndex: 'userPhone' },
|
||||
|
{ title: '最新消息时间', dataIndex: 'contentTime' }, |
||||
|
] |
||||
|
|
||||
|
export const tableFormSchema: FormSchema[] = [ |
||||
|
{ |
||||
|
field: 'nickName', |
||||
|
label: '用户昵称', |
||||
|
component: 'Input', |
||||
|
colProps: { span: 8}, |
||||
|
}, |
||||
|
] |
||||
@ -1,572 +0,0 @@ |
|||||
<template> |
|
||||
<div class="flex-row" style="width: 100%;height: 100%;"> |
|
||||
<div class="flex-col" style="width: 320px;height: 100%;border-right: 1px solid #ccc;"> |
|
||||
<div style="width: 100%;padding: 10px 24px;"> |
|
||||
<span style="font-size: 30px;font-weight: bold;color: #333;">用户资料</span> |
|
||||
</div> |
|
||||
<div class="flex-col" style="padding: 0px 20px;" v-if="details && details.code"> |
|
||||
<img :src="avatar" style="height: 120px;width: 120px;border-radius: 50%;margin-top: 90px;"/> |
|
||||
<span style="font-size: 18px;font-weight: bold;color: #333;margin-top: 8px;">{{details.name}}</span> |
|
||||
<div class="flex-row" style="margin-top: 8px;" v-if="details.phone"> |
|
||||
<span style="font-size: 14px;color: #333;">手机号:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.phone}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row" style="margin-top: 8px;"> |
|
||||
<span style="font-size: 14px;color: #333;">身份:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{matchmakerTypeList.find((find) => find.value === details.type)?.label}}</span> |
|
||||
<span style="font-size: 14px;color: #333;" v-if="details.matchmakerLevel > 2"> / {{details.matchmakerLevel == 3 ? '站点服务商' : '区域服务商'}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row" style="margin-top: 8px;" v-if="details.storeName"> |
|
||||
<span style="font-size: 14px;color: #333;">所属门店:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.storeName}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row" style="margin-top: 8px;"> |
|
||||
<span style="font-size: 14px;color: #333;">入驻时间:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.validityPeriodFrom}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row" style="margin-top: 8px;"> |
|
||||
<span style="font-size: 14px;color: #333;">到期时间:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.validityPeriodTo}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row" style="margin-top: 8px;"> |
|
||||
<span style="font-size: 14px;color: #333;">评分:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.score || '5.0'}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="flex-col" style="padding: 0px 20px;" v-else-if="details"> |
|
||||
<img :src="avatar" style="height: 120px;width: 120px;border-radius: 50%;margin-top: 90px;"/> |
|
||||
<span style="font-size: 18px;font-weight: bold;color: #333;margin-top: 8px;">{{details.nickName}}</span> |
|
||||
<div class="flex-row" style="margin-top: 8px;" v-if="details.name"> |
|
||||
<span style="font-size: 14px;color: #333;">姓名:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.name}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row" style="margin-top: 8px;" v-if="details.phone"> |
|
||||
<span style="font-size: 14px;color: #333;">手机号:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.phone}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row" style="margin-top: 8px;"> |
|
||||
<span style="font-size: 14px;color: #333;">性别:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.genderCode == 0 ? '男' : '女'}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row" style="margin-top: 8px;"> |
|
||||
<span style="font-size: 14px;color: #333;">嘉宾来源:</span> |
|
||||
<span style="font-size: 14px;color: #333;">{{details.identityTypeName || '红娘录入'}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="flex-col" style="width: 375px;height: 100%;border-right: 1px solid #ccc;"> |
|
||||
<div style="width: 100%;padding: 10px 24px;border-bottom: 1px solid #ccc;background:white;"> |
|
||||
<span style="font-size: 30px;font-weight: bold;color: #333;">消息列表</span> |
|
||||
</div> |
|
||||
<div style="width: 100%;height: 80vh;overflow: auto;"> |
|
||||
<div class="flex-row room-card" v-for="(item, index) in roomList" :key="item.roomId" :style="{background: roomIndex == index ? '#ddd' : 'white'}" @click="changeRoom(item, index)"> |
|
||||
<Badge :count="item.unreadContentCount"> |
|
||||
<img :src="item.roomPic || bAvatar" style="height: 64px;width: 64px;border-radius: 8px;"/> |
|
||||
</Badge> |
|
||||
<div class="flex-col" style="flex: 1;padding-left: 8px;"> |
|
||||
<div class="flex-row-center-space" style="flex: 1;"> |
|
||||
<span style="font-size: 16px;font-weight: bold;color: #333;">{{item.roomName}}</span> |
|
||||
<div class="flex-row" v-if="item.cityName"> |
|
||||
<Icon size="18" icon="ant-design:environment-outlined" style="padding-top: 2px;"/> |
|
||||
<span style="font-size: 14px;color: #666;">{{item.cityName}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="flex-col" style="flex: 1;"> |
|
||||
<span style="font-size: 14px;color: #333;">{{item.finalContent}}</span> |
|
||||
<span style="font-size: 12px;color: #999;">{{item.finalActivityTime}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="flex-col" style="flex: 1;height: 100%;"> |
|
||||
<Spin :spinning="loading" style="flex: 1;height: 100%;"> |
|
||||
<div class="flex-col" style="flex: 1;height: 100%;"> |
|
||||
<div class="flex-row-center-space" style="width: 100%;padding: 10px 24px;border-bottom: 1px solid #ccc;"> |
|
||||
<span style="font-size: 30px;font-weight: bold;color: #333;">对话框</span> |
|
||||
<span style="font-size: 18px;color: #333;" v-if="nowItem">{{nowItem.roomName}}</span> |
|
||||
</div> |
|
||||
<Result subTitle="暂无消息记录" v-if="!loading && messageList.length == 0"></Result> |
|
||||
<div class="scroll_wrap" ref="scrollWrap"> |
|
||||
<div class="chat-item" v-for="item in messageList" :key="item.roomContentRecordId"> |
|
||||
<span class="chat-time" v-if="item.contentTime && item.contentTime.length">{{item.contentTime}}</span> |
|
||||
<!--图片消息 --> |
|
||||
<template v-if="item.type == 6"> |
|
||||
<div class="chat-container chat-location-me" v-if="isMe(item)"> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="avatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-content-container"> |
|
||||
<div class="chat-text-container-super" style="justify-content: flex-end;"> |
|
||||
<div class="chat-text-container chat-text-container-me"> |
|
||||
<span class="chat-text chat-text-me">{{item.info.content || ''}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="chat-container" v-else> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="nowItem.roomPic || bAvatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container" style="justify-content: flex-start;margin: 4px 8px 0px 8px;"> |
|
||||
<div style="border-top: 1px solid #f3f3f3;padding: 12px;width: 300px;"> |
|
||||
<span style="font-size: 15px;color: #333;">申请查看Ta的照片,是否同意?</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<!--图片消息 --> |
|
||||
<template v-else-if="item.type == 5"> |
|
||||
<div class="chat-container chat-location-me" v-if="isMe(item)"> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="avatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container chat-text-container-me" style="justify-content: flex-end;margin: 4px 8px 0px 8px;"> |
|
||||
<Image :src="avatarImage(item)" style="height: 300px;width: 300px;border-radius: 8px 0 8px 8px;"/> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="chat-container" v-else> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="nowItem.roomPic || bAvatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container" style="justify-content: flex-start;margin: 4px 8px 0px 8px;"> |
|
||||
<Image :src="avatarImage(item)" style="height: 300px;width: 300px;border-radius: 0px 8px 8px 8px;"/> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<!--邀请发榜消息 --> |
|
||||
<template v-else-if="item.type == 4"> |
|
||||
<div class="chat-container chat-location-me" v-if="isMe(item)"> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="avatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container chat-text-container-me" style="justify-content: flex-end;margin: 4px 8px 0px 8px;"> |
|
||||
<Image :src="avatarImage(item)" style="width: 300px;height: 240px;border-radius: 8px 0px 0px 0px;"/> |
|
||||
<div style="padding: 12px;background: white;border-radius: 0 0 8px 8px;"> |
|
||||
<span style="font-size: 15px;color: #333;">{{item.info.content}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="chat-container" v-else> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="nowItem.roomPic || bAvatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container" style="justify-content: flex-start;margin: 4px 8px 0px 8px;"> |
|
||||
<Image :src="avatarImage(item)" style="height: 240px;width: 300px;border-radius: 0px 8px 0px 0px;"/> |
|
||||
<div style="border-top: 1px solid #f3f3f3;padding: 12px;width: 300px;"> |
|
||||
<span style="font-size: 15px;color: #EE811B;">Hi!我是你的红娘,邀请你发布悬赏,现在去发布?</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<!--悬赏匹配资料消息 --> |
|
||||
<template v-else-if="item.type == 3"> |
|
||||
<div class="chat-container chat-location-me" v-if="isMe(item)"> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="avatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container chat-text-container-me" style="justify-content: flex-end;margin: 4px 8px 0px 8px;"> |
|
||||
<img :src="avatarImage(item)" style="height: 225px;width: 300px;border-radius: 8px 0px 0px 0px;"/> |
|
||||
<div class="flex-row-center-space" style="padding: 8px 12px 4px 12px;color: #fff;"> |
|
||||
<div class="flex-row-center-start"> |
|
||||
<span style="font-size: 16px;font-weight: bold;margin-right: 6px;">{{item.info.nickName}}</span> |
|
||||
</div> |
|
||||
<span style="font-size: 12px;">{{item.info.age}}岁 / {{item.info.height}}cm</span> |
|
||||
</div> |
|
||||
<div class="flex-row-center-start" style="padding: 0px 12px 4px 12px;color: #fff;max-width: 300px;"> |
|
||||
<span style="font-size: 12px;">{{item.info.nowtown}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;">|</span> |
|
||||
<span style="font-size: 12px;">{{item.info.hometown}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row-center-start" style="padding: 0px 12px 12px 12px;color: #fff;max-width: 300px;"> |
|
||||
<span style="font-size: 12px;">{{item.info.education}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;" v-if="item.info.occupation">|</span> |
|
||||
<span style="font-size: 12px;" v-if="item.info.occupation">{{item.info.occupation}}</span> |
|
||||
<span style="margin: 0px 12px;font-size: 12px;">|</span> |
|
||||
<span style="font-size: 12px;">{{item.info.income}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="chat-container" v-else> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="nowItem.roomPic || bAvatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container" style="justify-content: flex-start;margin: 4px 8px 0px 8px;"> |
|
||||
<img :src="avatarImage(item)" style="height: 225px;width: 300px;border-radius: 0px 8px 0px 0px;"/> |
|
||||
<div class="flex-row-center-space" style="padding: 8px 12px 4px 12px;color: #333;"> |
|
||||
<div class="flex-row-center-start"> |
|
||||
<span style="font-size: 16px;font-weight: bold;margin-right: 6px;">{{item.info.nickName}}</span> |
|
||||
</div> |
|
||||
<span style="font-size: 12px;">{{item.info.age}}岁 / {{item.info.height}}cm</span> |
|
||||
</div> |
|
||||
<div class="flex-row-center-start" style="padding: 0px 12px 4px 12px;color: #333;max-width: 300px;"> |
|
||||
<span style="font-size: 12px;">{{item.info.nowtown}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;">|</span> |
|
||||
<span style="font-size: 12px;">{{item.info.hometown}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row-center-start" style="padding: 0px 12px 12px 12px;color: #333;max-width: 300px;"> |
|
||||
<span style="font-size: 12px;">{{item.info.education}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;" v-if="item.info.occupation">|</span> |
|
||||
<span style="font-size: 12px;" v-if="item.info.occupation">{{item.info.occupation}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;">|</span> |
|
||||
<span style="font-size: 12px;">{{item.info.income}}</span> |
|
||||
</div> |
|
||||
<div style="border-top: 1px solid #f3f3f3;padding: 12px;"> |
|
||||
<span style="font-size: 15px;color: #333;">嘉宾申请与你见面,请确认!</span> |
|
||||
</div> |
|
||||
<div style="padding: 0px 12px 12px 12px;width: 300px;" v-if="[2, 3].includes(item.info.miIdAttitude)"> |
|
||||
<span style="font-size: 13px;color: #EE811B;" v-if="item.info.miIdAttitude == 2">你已接受见面,待对方同意后红娘安排见面,你也可主动联系对方红娘了解进程。</span> |
|
||||
<span style="font-size: 13px;color: #ff0000;" v-if="item.info.miIdAttitude == 3">你已经拒绝见面</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<!--用户资料消息 --> |
|
||||
<template v-else-if="item.type == 2"> |
|
||||
<div class="chat-container chat-location-me" v-if="isMe(item)"> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="avatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container chat-text-container-me" style="justify-content: flex-end;margin: 4px 8px 0px 8px;"> |
|
||||
<img :src="avatarImage(item)" style="height: 225px;width: 300px;border-radius: 8px 0px 0px 0px;"/> |
|
||||
<div class="flex-row-center-space" style="padding: 8px 12px 4px 12px;color: #fff;"> |
|
||||
<div class="flex-row-center-start"> |
|
||||
<span style="font-size: 16px;font-weight: bold;margin-right: 6px;">{{item.info.nickName}}</span> |
|
||||
</div> |
|
||||
<span style="font-size: 12px;">{{item.info.age}}岁 / {{item.info.height}}cm</span> |
|
||||
</div> |
|
||||
<div class="flex-row-center-start" style="padding: 0px 12px 4px 12px;color: #fff;max-width: 300px;"> |
|
||||
<span style="font-size: 12px;">{{item.info.nowtown}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;">|</span> |
|
||||
<span style="font-size: 12px;">{{item.info.hometown}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row-center-start" style="padding: 0px 12px 12px 12px;color: #fff;max-width: 300px;"> |
|
||||
<span style="font-size: 12px;">{{item.info.education}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;" v-if="item.info.occupation">|</span> |
|
||||
<span style="font-size: 12px;" v-if="item.info.occupation">{{item.info.occupation}}</span> |
|
||||
<span style="margin: 0px 12px;font-size: 12px;">|</span> |
|
||||
<span style="font-size: 12px;">{{item.info.income}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="chat-container" v-else> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="nowItem.roomPic || bAvatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-profile-container" style="justify-content: flex-start;margin: 4px 8px 0px 8px;"> |
|
||||
<img :src="avatarImage(item)" style="height: 225px;width: 300px;border-radius: 0px 8px 0px 0px;"/> |
|
||||
<div class="flex-row-center-space" style="padding: 8px 12px 4px 12px;color: #333;"> |
|
||||
<div class="flex-row-center-start"> |
|
||||
<span style="font-size: 16px;font-weight: bold;margin-right: 6px;">{{item.info.nickName}}</span> |
|
||||
</div> |
|
||||
<span style="font-size: 12px;">{{item.info.age}}岁 / {{item.info.height}}cm</span> |
|
||||
</div> |
|
||||
<div class="flex-row-center-start" style="padding: 0px 12px 4px 12px;color: #333;max-width: 300px;"> |
|
||||
<span style="font-size: 12px;">{{item.info.nowtown}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;">|</span> |
|
||||
<span style="font-size: 12px;">{{item.info.hometown}}</span> |
|
||||
</div> |
|
||||
<div class="flex-row-center-start" style="padding: 0px 12px 12px 12px;color: #333;max-width: 300px;"> |
|
||||
<span style="font-size: 12px;">{{item.info.education}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;" v-if="item.info.occupation">|</span> |
|
||||
<span style="font-size: 12px;" v-if="item.info.occupation">{{item.info.occupation}}</span> |
|
||||
<span style="margin: 0px 8px;font-size: 12px;">|</span> |
|
||||
<span style="font-size: 12px;">{{item.info.income}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<!--聊天消息 --> |
|
||||
<template v-else> |
|
||||
<div class="chat-container chat-location-me" v-if="isMe(item)"> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="avatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-content-container"> |
|
||||
<div class="chat-text-container-super" style="justify-content: flex-end;"> |
|
||||
<div class="chat-text-container chat-text-container-me"> |
|
||||
<span class="chat-text chat-text-me">{{item.content || ''}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="chat-container" v-else> |
|
||||
<div class="chat-icon-container"> |
|
||||
<img :src="nowItem.roomPic || bAvatar" style="height: 40px;width: 40px;border-radius: 6px;"/> |
|
||||
</div> |
|
||||
<div class="chat-content-container"> |
|
||||
<div class="chat-text-container-super" style="justify-content: flex-start;"> |
|
||||
<div class="chat-text-container flex-col"> |
|
||||
<span class="chat-text">{{item.content || ''}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</Spin> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { Button, Badge, Result, Spin, Image } from 'ant-design-vue' |
|
||||
import { matchmakerTypeList } from '/@/enums/partnerEnum' |
|
||||
import Icon from '/@/components/Icon/src/Icon.vue' |
|
||||
import { getMarriageInformationDetailsById } from '/@/api/marriageInfo' |
|
||||
import { getMatchmakerInfo } from '/@/api/reward' |
|
||||
import { getChatMessageRoomList, getChatRoomMessageList } from '/@/api/message' |
|
||||
|
|
||||
export default { |
|
||||
components: { Button, Badge, Icon, Result, Spin, Image }, |
|
||||
data() { |
|
||||
return { |
|
||||
miId: null, |
|
||||
details: null, |
|
||||
avatar: null, |
|
||||
nowItem: null, |
|
||||
roomList: [], |
|
||||
roomIndex: 0, |
|
||||
pageIndex: 1, |
|
||||
messageList: [], |
|
||||
loading: true, |
|
||||
roomId: null, |
|
||||
noMore: false, //暂无更多数据 |
|
||||
matchmakerTypeList, |
|
||||
bAvatar: 'https://dating-agency-prod.oss-cn-shenzhen.aliyuncs.com/B5B307276426.png' |
|
||||
}; |
|
||||
}, |
|
||||
mounted() { |
|
||||
this.miId = this.$route.query.miId |
|
||||
if(this.miId){ |
|
||||
let type = Number(this.$route.query.type) |
|
||||
if(type == 3){ |
|
||||
getMatchmakerInfo(this.miId).then(res => { |
|
||||
this.details = res |
|
||||
this.avatar = res.profilePhoto || this.bAvatar |
|
||||
}) |
|
||||
} else { |
|
||||
getMarriageInformationDetailsById(this.miId).then(res => { |
|
||||
this.details = res |
|
||||
this.avatar = res.profilePhoto || this.bAvatar |
|
||||
}) |
|
||||
} |
|
||||
getChatMessageRoomList({selfMiId: this.miId, pageSize: 100}).then(result => { |
|
||||
this.roomList = result.items || [] |
|
||||
this.nowItem = this.roomList[0] |
|
||||
this.roomId = this.roomList[0].roomId |
|
||||
this.fetchMessageList() |
|
||||
}) |
|
||||
} |
|
||||
this.$refs.scrollWrap.addEventListener("scroll", this.onScrollListener); |
|
||||
}, |
|
||||
methods: { |
|
||||
//滚动监听 |
|
||||
onScrollListener() { |
|
||||
if (this.$refs.scrollWrap.scrollTop == 0) { |
|
||||
console.log("滚动到顶部了"); |
|
||||
|
|
||||
if (this.noMore) { |
|
||||
console.log("暂无更多数据"); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
//模拟耗时任务从接口获取数据 |
|
||||
setTimeout(() => { |
|
||||
const scrollWrap = this.$refs.scrollWrap; |
|
||||
|
|
||||
let h1 = scrollWrap.scrollHeight; |
|
||||
console.log("h1======" + h1); |
|
||||
|
|
||||
this.fetchMessageList(); |
|
||||
|
|
||||
//list更新后,等待页面渲染完毕再去拿scrollHeight,否则拿到的是之前的 |
|
||||
this.$nextTick(() => { |
|
||||
let h2 = scrollWrap.scrollHeight; |
|
||||
console.log("h======" + h2); |
|
||||
|
|
||||
//顶部在原先基础上往下滚动50px,露出新加载数据的一点 |
|
||||
scrollWrap.scrollTo({ |
|
||||
top: h2 - h1 - 50, |
|
||||
behavior: "instant", //auto-自动滚动 instant-瞬间滚动 smooth-平滑滚动 |
|
||||
}); |
|
||||
}); |
|
||||
}, 1000); |
|
||||
} |
|
||||
}, |
|
||||
//滚动到顶部 |
|
||||
scrollTop() { |
|
||||
this.$nextTick(() => { |
|
||||
const scrollWrap = this.$refs.scrollWrap; |
|
||||
scrollWrap.scrollTo({ |
|
||||
top: 0, |
|
||||
behavior: "smooth", //auto-自动滚动 instant-瞬间滚动 smooth-平滑滚动 |
|
||||
}); |
|
||||
}); |
|
||||
}, |
|
||||
//滚动到底部 |
|
||||
scrollBottom() { |
|
||||
this.$nextTick(() => { |
|
||||
let scrollWrap = this.$refs.scrollWrap; |
|
||||
scrollWrap.scrollTo({ |
|
||||
top: scrollWrap.scrollHeight, |
|
||||
behavior: "smooth", //auto-自动滚动 instant-瞬间滚动 smooth-平滑滚动 |
|
||||
}); |
|
||||
}); |
|
||||
}, |
|
||||
//初始化数据 |
|
||||
async fetchMessageList() { |
|
||||
this.loading = true |
|
||||
const result = await getChatRoomMessageList({pageNum: this.pageNum, selfMiId: this.miId, roomId: this.roomId}) |
|
||||
var respList = result.items || [] |
|
||||
for (var index = respList.length - 1; index >= 0; index--) { |
|
||||
if(respList[index].type == 2 || respList[index].type == 3){ |
|
||||
respList[index].info = JSON.parse(respList[index].content) |
|
||||
if(respList[index].info.type && Number(respList[index].info.type) > 3){ |
|
||||
respList[index].type = Number(respList[index].info.type) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
if(this.pageNum == result.pages){ |
|
||||
this.noMore = true; //数据全部加载完毕 |
|
||||
console.log('数据全部加载完毕') |
|
||||
if(this.pageNum == 1){ |
|
||||
this.messageList = respList |
|
||||
this.scrollBottom(); |
|
||||
} else { |
|
||||
this.messageList = [...respList, ...this.messageList] |
|
||||
} |
|
||||
} else if(this.pageNum == 1){ |
|
||||
this.messageList = respList |
|
||||
this.pageNum = result.current + 1 |
|
||||
this.scrollBottom(); |
|
||||
} else { |
|
||||
this.pageNum = result.current + 1 |
|
||||
this.messageList = [...respList, ...this.messageList] |
|
||||
} |
|
||||
this.loading = false |
|
||||
}, |
|
||||
changeRoom(item, index){ |
|
||||
if(this.loading || this.roomId === item.roomId){ |
|
||||
return |
|
||||
} |
|
||||
this.nowItem = item |
|
||||
this.pageNum = 1 |
|
||||
this.roomIndex = index |
|
||||
this.noMore = false; |
|
||||
this.roomId = item.roomId |
|
||||
this.messageList = [] |
|
||||
this.fetchMessageList() |
|
||||
}, |
|
||||
isMe(item){ |
|
||||
return item.sendMiId === this.miId |
|
||||
}, |
|
||||
avatarImage(item){ |
|
||||
if(item.info && item.info.url){ |
|
||||
return item.info.url |
|
||||
} |
|
||||
if(item.info && item.info.profilePhoto){ |
|
||||
return item.info.profilePhoto |
|
||||
} |
|
||||
return 'https://dating-agency-prod.oss-cn-shenzhen.aliyuncs.com/64949726764B.jpg' |
|
||||
}, |
|
||||
}, |
|
||||
beforeDestroy() { |
|
||||
this.$refs.scrollWrap.removeEventListener("scroll", this.onScrollListener); |
|
||||
}, |
|
||||
}; |
|
||||
</script> |
|
||||
|
|
||||
<style lang="less" scoped> |
|
||||
.scroll_wrap { |
|
||||
width: 100%; |
|
||||
height: 80vh; |
|
||||
// position: absolute; |
|
||||
// top: 30px; |
|
||||
// left: 50%; |
|
||||
// transform: translateX(-50%); |
|
||||
// border: 1px solid #333; |
|
||||
overflow: auto; |
|
||||
|
|
||||
.item { |
|
||||
height: 50px; |
|
||||
line-height: 50px; |
|
||||
padding-left: 15px; |
|
||||
border-bottom: 1px solid #e4e4e4; |
|
||||
} |
|
||||
} |
|
||||
.room-card{ |
|
||||
width: 100%; |
|
||||
padding: 12px; |
|
||||
border-bottom: 1px solid #ccc; |
|
||||
background: white; |
|
||||
} |
|
||||
|
|
||||
.chat-item { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
padding: 10px; |
|
||||
} |
|
||||
.chat-time { |
|
||||
padding: 2px 0px; |
|
||||
text-align: center; |
|
||||
font-size: 12px; |
|
||||
color: #aaaaaa; |
|
||||
} |
|
||||
.chat-container { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
} |
|
||||
.chat-location-me { |
|
||||
flex-direction: row-reverse; |
|
||||
text-align: right; |
|
||||
} |
|
||||
.chat-icon-container { |
|
||||
margin-top: 4px; |
|
||||
} |
|
||||
.chat-icon{ |
|
||||
width: 40px; |
|
||||
height: 40px; |
|
||||
border-radius: 50%; |
|
||||
background-color: #eeeeee; |
|
||||
} |
|
||||
.chat-content-container { |
|
||||
margin: 0px 8px; |
|
||||
} |
|
||||
.chat-user-name{ |
|
||||
font-size: 13px; |
|
||||
color: #888888; |
|
||||
} |
|
||||
.chat-profile-container{ |
|
||||
text-align: left; |
|
||||
background-color: #fff; |
|
||||
border-radius: 0 8px 8px 8px; |
|
||||
} |
|
||||
.chat-text-container { |
|
||||
text-align: left; |
|
||||
background-color: #fff; |
|
||||
border-radius: 0 8px 8px 8px; |
|
||||
padding: 10px 12px 13px 12px; |
|
||||
margin-top: 1px; |
|
||||
max-width: 300px; |
|
||||
} |
|
||||
.chat-text-container-me { |
|
||||
background-color: #EE811B; |
|
||||
border-radius: 8px 0 8px 8px; |
|
||||
} |
|
||||
.chat-text-container-super { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
margin-top: 4px; |
|
||||
} |
|
||||
.chat-text { |
|
||||
font-size: 14px; |
|
||||
word-break: break-all; |
|
||||
max-width: 286px; |
|
||||
} |
|
||||
.chat-text-me { |
|
||||
color: white; |
|
||||
} |
|
||||
</style> |
|
||||
Write
Preview
Loading…
Cancel
Save