Commit 23d14d85 authored by Zhang Xiaojie's avatar Zhang Xiaojie

Merge branch 'dev' of gitlab.33.cn:chenqikuai/fns_front_2 into dev

parents 248b821f cfdc6467
......@@ -49,7 +49,6 @@ export default defineComponent({
}
fmp
.authorize({
appId: "dtalk",
......@@ -103,9 +102,6 @@ export default defineComponent({
if (getUserMsg()) {
connect();
}
getVisitorId().then(id => {
console.log(id, "show id");
})
})
watch(() => connectionState.error, () => {
......
<template>
<div class="mx-5">
<div class="wrap22 flex items-center" @click="$router.push({path: 'NewsDetail', query: { uuid: info?.uuid, type: 'news' }})">
<div class="box1 flex-col flex-grow justify-between">
<div class="box1 flex-col flex-grow justify-between overflow-hidden">
<span class="info8">{{ info?.title }}</span>
<span class="info10">{{ info?.desc }}</span>
<div class="layer4 flex pr-20">
<span class="info9">{{ info?.writer }}</span>
<span class="word24">{{ $format(info?.created_at, 'YYYY-MM-DD') }}</span>
......@@ -62,6 +63,23 @@ export default defineComponent({
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap
}
.info10 {
z-index: 205;
display: block;
overflow-wrap: break-word;
color: rgba(141, 146, 175, 1);
margin-top: 5px;
font-size: 12px;
letter-spacing: 0.1679999977350235px;
font-family: PingFangSC-Medium;
line-height: 25px;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap
}
.layer4 {
......
<script lang="tsx">
import { goToChatWithOutletRoboot } from "@/router/navigate";
import AddressService from "@/service/AddressService";
import { defineComponent, ref } from "vue";
export default defineComponent({
props: ["setRef", "min_amount", "max_amount", "rate_lower", "rate_upper"],
setup(props) {
const handleClick = async () => {
console.log(1);
const ret = await AddressService.getInstance().getNearby({
bank_code: Number(process.env.VUE_APP_BANK_CODE),
number: 1,
})
if (ret.code === 200) {
goToChatWithOutletRoboot({
outletId: ret.data[0].outlet_id
})
}
}
return () => (
<div class="group2 flex-col">
<button
class="bd12 flex-col"
onClick={() => {}}
ref={(el) => {
props.setRef(el);
}}
>
<span class="txt9">立即申请</span>
</button>
<div class="bd13 flex-col w-full">
<div class="bd13 w-full">
<div class="layer12 flex-col w-full">
<span class="word18">借款额度(万元)</span>
<span class="txt10">
......@@ -26,6 +32,18 @@ export default defineComponent({
</span>
</div>
</div>
<button
class="bd12 flex-col"
onClick={() => {
console.log(1123123)
handleClick();
}}
ref={(el) => {
props.setRef(el);
}}
>
<span class="txt9" >立即申请</span>
</button>
</div>
);
},
......@@ -46,7 +64,7 @@ export default defineComponent({
left: 20px;
top: 222px;
.bd12 {
z-index: 12;
z-index: 15;
height: 40px;
border-radius: 20px;
background-color: rgba(62, 79, 175, 1);
......
......@@ -77,7 +77,10 @@
</div>
</div>
<!-- 底部操作 -->
<div class="flex text-center py-3 text-gray-800 bg-branch-tab-bg rounded-b-2xl" v-if="is_normal_work">
<div
class="flex text-center py-3 text-gray-800 bg-branch-tab-bg rounded-b-2xl"
v-if="is_normal_work"
>
<p class="w-1/2 border-r border-gray-200 mb-0" @click="handleClickChatWithClientManager">联系客服</p>
<p class="w-1/2 mb-0" :class="isOpen ? 'text-app-blue' : 'text-gray-800'" @click="toCall">电话咨询</p>
</div>
......@@ -97,6 +100,7 @@ import UserService from '@/service/UserService'
import { authCheck } from '@/utils/authCheck'
import router from '@/router'
import ShowCall from '@/components/showCall/index.vue'
import { goToChatWithOutletRoboot } from '@/router/navigate'
const addressService = new AddressService()
......@@ -182,6 +186,7 @@ const isOpen = computed(() => {
return false
}
})
const error = "由于施工原因,本营业厅暂时不营业搬迁中"
const errorReason = ref('')
const getErrorNote = () => {
if (props.is_normal_work) return
......@@ -219,19 +224,10 @@ const handleClickNagigate = () => {
const handleClickChatWithClientManager = async () => {
authCheck(async () => {
const ret = await UserService.getInstance().contact_custom_service({
outLetID: props.outlet_id as number
goToChatWithOutletRoboot({
outletId: props.outlet_id as number
})
if (ret.code === 200) {
router.push({
name: 'Chat',
query: {
targetId: ret.data.addr,
}
})
}
})
}
</script>
......
<template>
<div @click="$router.push({path: 'NewsDetail', query: { uuid: info.uuid, type: 'policy' }})">
<div class=" text-base text-gray-800 font-semibold pt-5">{{ info.title }}</div>
<div class=" text-base text-gray-800 font-semibold pt-5 news-title">{{ info.title }}</div>
<!-- <p class=" text-xs text-gray-400 pt-5">{{ info.desc }}</p> -->
<div class=" text-sm text-gray-800 text-justify pt-3">{{ info.desc }}</div>
<div class=" text-sm text-gray-800 text-justify pt-3 news-info">{{ info.desc }}</div>
<div class=" text-xs text-gray-400 py-5 border-b border-red border-solid">发布时间:{{ $format(info.created_at, 'YYYY-MM-DD') }} &nbsp;&nbsp;&nbsp;作者: {{ info.writer }}</div>
</div>
</template>
......@@ -26,4 +26,16 @@ export default defineComponent({
<style scoped>
.news-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap
}
.news-info {
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-break: break-all;
}
</style>
\ No newline at end of file
......@@ -37,9 +37,9 @@
import Vue, { getCurrentInstance } from 'vue'
import jsBridge from "@/utils/jsBridge2"
const { ctx } = getCurrentInstance() as any
// const { ctx } = getCurrentInstance() as any
console.log(ctx)
const emit = defineEmits(['hidden'])
const props = defineProps({
show: {
......@@ -52,14 +52,13 @@ const props = defineProps({
})
const hide = () => {
console.log(ctx, 'ctx')
ctx.$emit('hidden', false)
emit('hidden', false)
}
const handleClickCall = async () => {
console.log(props.phone)
new jsBridge().bridge_call(props.phone, () => {
ctx.$emit('hidden', false)
emit('hidden', false)
})
}
......
......@@ -11,4 +11,9 @@ export const CONST_END_CHAT = {
staff: { id: '4', value: '会话已结束' },
}
export const CHAT_CONST_LIST = [CONST_START_CHAT, CONST_END_CHAT]
export const CONST_WARNING = {
user: { id: '5', value: '您好,非常抱歉,该网点暂无营业人员。' },
staff: { id: '6', value: '' },
}
export const CHAT_CONST_LIST = [CONST_START_CHAT, CONST_END_CHAT, CONST_WARNING]
import { DisplayMessage } from '@/store/messagesStore'
import { getMasterIdFromDisplayMsg, getTargetIdFromDisplayMsg } from '@/utils/chatutils'
import {
getMasterIdFromDisplayMsg,
getTargetIdFromDisplayMsg,
} from '@/utils/chatutils'
import ChatListCardDB from './ChatListCardDB'
import ChatMessageDB from './ChatMessageDB'
interface iRecevedMsg {
msg: DisplayMessage
masterId: string
isChattingWithTargetId: boolean
isRoboot?: boolean
}
export default class ChatDBService {
static instance: ChatDBService
static getInstance() {
......@@ -14,30 +24,62 @@ export default class ChatDBService {
msg: DisplayMessage
masterId: string
isChattingWithTargetId: boolean
isRoboot?: boolean
}) {
let firstInsert = false
const isQueueEmpty = this.dataList.length === 0
if (isQueueEmpty) {
firstInsert = true
}
this.pushToList(data)
if (firstInsert === true) {
await this.exec(this.dataList[0])
this.dataList.shift()
this.startExecList()
}
}
private async startExecList(): Promise<any> {
if (this.dataList.length !== 0) {
const msg = this.dataList[0]
await this.exec(msg)
this.dataList.shift()
return this.startExecList()
}
}
private async exec(data: {
msg: DisplayMessage
masterId: string
isChattingWithTargetId: boolean
isRoboot?: boolean
}) {
/* 检查和对象之间的聊天记录,如果数量为0,则表示之前没有和他聊过,需要新增一个chatcard */
/* 如果数量为1,表示之前和他聊过 */
const { msg, masterId, isChattingWithTargetId } = data
console.log(data, "show in handleEveryRecive");
await ChatMessageDB.getInstance().saveMsg(msg, masterId)
const thePersonAlreadyInChatList = await ChatListCardDB.getInstance().thePersonAlreadyInChatList(
const thePersonAlreadyInChatList = await ChatMessageDB.getInstance().thePersonAlreadyInChatList(
getMasterIdFromDisplayMsg(msg),
getTargetIdFromDisplayMsg(msg),
)
console.log(thePersonAlreadyInChatList, 'show thePersonAlreadyInChatList');
await ChatMessageDB.getInstance().saveMsg(msg, masterId)
if (thePersonAlreadyInChatList) {
await ChatListCardDB.getInstance().updateNewestCard({
return await ChatListCardDB.getInstance().updateNewestCard({
msg,
isChattingWithTargetId,
})
} else {
await ChatListCardDB.getInstance().addNewCard({
return await ChatListCardDB.getInstance().addNewCard({
msg,
isChattingWithTargetId,
isRobootCard: data.isRoboot,
})
}
}
private dataList = [] as iRecevedMsg[]
private pushToList(msg: iRecevedMsg) {
this.dataList.push(msg)
}
}
......@@ -52,8 +52,7 @@ export default class ChatListCardDB extends MyAppDatabase {
return this.chatListCard
.filter((item) => {
return item.masterId === masterId
})
.toArray()
}).reverse().sortBy('datetime')
}
async thePersonAlreadyInChatList(masterId: string, personId: string) {
......@@ -105,7 +104,8 @@ export default class ChatListCardDB extends MyAppDatabase {
async addNewCard(data: {
msg: DisplayMessage
isChattingWithTargetId: boolean
isChattingWithTargetId: boolean,
isRobootCard?: boolean
}) {
const content = data.msg.content?.content || '[新消息]'
const masterId = getMasterIdFromDisplayMsg(data.msg)
......@@ -118,7 +118,8 @@ export default class ChatListCardDB extends MyAppDatabase {
unreadMsgCount: data.isChattingWithTargetId ? 0 : 1,
content,
inChat: false,
datetime: data.msg.datetime
datetime: data.msg.datetime,
isRobootCard: data.isRobootCard,
})
}
......
......@@ -30,7 +30,11 @@ export default class ChatMessageDB extends MyAppDatabase {
}
async deleteMsg({ uuid, logid }: { uuid?: string; logid?: string }) {
const updateChatList = async (masterId: string, target: string, deletedMsgDatetime: number) => {
const updateChatList = async (
masterId: string,
target: string,
deletedMsgDatetime: number,
) => {
const latestedMsg = await this.getLatestedMessage(masterId, target)
if (latestedMsg) {
......@@ -39,8 +43,8 @@ export default class ChatMessageDB extends MyAppDatabase {
this.chatListCard
.filter((i) => i.masterId === masterId && i.targetId === target)
.modify((i) => {
i.content = latestedMsg.content.content as string;
i.datetime = latestedMsg.datetime;
i.content = latestedMsg.content.content as string
i.datetime = latestedMsg.datetime
})
} else {
/* 如果和target没有聊天消息 */
......@@ -56,11 +60,21 @@ export default class ChatMessageDB extends MyAppDatabase {
if (uuid) {
const item = await this.chatMessage.where('uuid').equals(uuid).first()
await this.chatMessage.where('uuid').equals(uuid).delete()
item && updateChatList(item?.masterId, getTargetIdFromDisplayMsg(item), item?.datetime)
item &&
updateChatList(
item?.masterId,
getTargetIdFromDisplayMsg(item),
item?.datetime,
)
} else if (logid) {
const item = await this.chatMessage.where('logid').equals(logid).first()
await this.chatMessage.where('logid').equals(logid).delete()
item && updateChatList(item?.masterId, getTargetIdFromDisplayMsg(item), item?.datetime)
item &&
updateChatList(
item?.masterId,
getTargetIdFromDisplayMsg(item),
item?.datetime,
)
} else {
throw new Error('没有uuid或者logid')
}
......@@ -78,6 +92,18 @@ export default class ChatMessageDB extends MyAppDatabase {
}
}
async thePersonAlreadyInChatList(masterId: string, personId: string) {
return (
(await this.chatMessage
.filter(
(i) =>
(i.masterId === masterId &&
((i.state === null && i.from === personId) || (i.state !== null && i.target === personId)))
)
.count()) !== 0
)
}
/* from表示自己的address,target表示对话人的address */
getMessage(from: string, target: string) {
return this.chatMessage
......
......@@ -13,6 +13,7 @@ export interface iChatListCard {
content: string
datetime: number
inChat: boolean // 会话状态,会话中?
isRobootCard?: boolean
}
export class MyAppDatabase extends Dexie {
......@@ -24,10 +25,10 @@ export class MyAppDatabase extends Dexie {
constructor() {
super('MyAppDatabase')
this.version(1.3).stores({
this.version(1.4).stores({
chatMessage:
'++id, content, from, uuid, state, uploadProgress, type, datetime, hideDatetime, logid, masterId, readed',
chatListCard: '++id, masterId, targetId, unreadMsgCount, content, inChat',
chatListCard: '++id, masterId, targetId, unreadMsgCount, content, inChat, isRobootCard',
contactPerson: '++id, addr, bank, phone, user_name, out_let_name',
userInfo: '++id, created_at, phone, remark, user_name, uuid, addr',
})
......
import router from '.'
export function goToChatWithOutletRoboot(data: { outletId: number }) {
router.push({
name: 'Chat',
query: {
targetId: data.outletId,
outlet: 'true',
},
})
}
export function gotoChatWithStaff(data: { address: string; beginChat?: boolean }) {
router.push({
name: 'Chat',
query: {
targetId: data.address,
beginChat: data.beginChat ? 'true' : undefined,
},
})
}
import { Toast } from 'vant'
import baseAxios, { iRet } from '../index'
import { iNearbyOutLet } from './types'
import { iNearbyOutLet, iOutLetDetail } from './types'
import Bridge from '@/utils/jsBridge2'
class AddressService {
static instance: AddressService
......@@ -80,6 +80,22 @@ class AddressService {
data,
})
}
getOutlet(data: { outlet_name?: string; id?: number }) {
let theData = {
bank_code: Number(process.env.VUE_APP_BANK_CODE)
} as any
if (data.outlet_name) {
theData.outlet_name = data.outlet_name
} else if (data.id !== undefined) {
theData.id = data.id
}
return baseAxios<iOutLetDetail>({
url: '/address/getOutlet',
method: 'post',
data: theData,
})
}
}
export default AddressService
......@@ -13,3 +13,18 @@ export interface iNearbyOutLet {
export interface errorInfo {
note: string
}
export interface iOutLetDetail {
id: number
city_name: string
is_normal_work: boolean
latitude: string
location: string
longitude: string
opening_hours: string
outlet_name: string
region_name: string
weekend_status: number
province_name: string
}
\ No newline at end of file
......@@ -16,6 +16,8 @@ baseAxios.interceptors.response.use(
router.push({
name: 'Login',
})
} else if (ret.code === 1000) {
Toast('您好,非常抱歉,该网点暂无营业人员。')
} else if (ret.code !== 200) {
Toast.fail(ret.msg)
}
......
......@@ -104,7 +104,7 @@ class MessageStore {
* @param content 消息内容,需根据类型填写对应字段
* @param uuid 如果传入 uuid 则说明是重新发送之前失败的消息
*/
sendMessage({
async sendMessage({
type,
content,
target,
......@@ -151,7 +151,7 @@ class MessageStore {
type === ChatMessageTypes.Image &&
(<dtalk.proto.IAudioMsg>content).mediaUrl
)
this.send(type, content, _uuid, message, target)
await this.send(type, content, _uuid, message, target)
return
}
......@@ -187,7 +187,7 @@ class MessageStore {
}
// 文本类消息,不需要上传 OSS,直接发送
else {
ChatDBService.getInstance().handleEveryReceive({
await ChatDBService.getInstance().handleEveryReceive({
msg: message,
masterId: getMasterIdFromDisplayMsg(message),
isChattingWithTargetId: isChattingWith(
......@@ -293,6 +293,8 @@ class MessageStore {
uuid,
})
.then(() => {
console.log('send success');
message.state = 'success'
ChatMessageDB.getInstance().updateMsg(
......
import { iChatListCard } from '@/db'
import ContactPersonService from '@/db/ContactPersonService'
import UserInfoDBService from '@/db/UserInfoService'
import AddressService from '@/service/AddressService'
import UserService from '@/service/UserService'
import { iContact } from '@/service/UserService/types'
import { eRole } from '@/types/roleType'
import { getUserMsg } from './userMsg'
/* 拿到地址对应的用户昵称 */
export const getDisplayNamesFromAddress = async (
addressList: string[],
): Promise<string[]> => {
......@@ -51,13 +54,44 @@ export const getDisplayNamesFromAddress = async (
return addressList.map((item) => {
const msg = fullList.find((i: any) => i?.addr === item)
if (msg?.out_let_name) {
return msg?.out_let_name + msg.user_name
return msg?.out_let_name + msg.user_name
} else {
return msg?.phone
}
})
}
/* 获取网点名称 */
export const getDisplayNamesFromOutletId = async (outletids: number[]) => {
const promiseList = outletids.map((id) => {
return AddressService.getInstance()
.getOutlet({
id,
})
.then((ret) => {
if (ret.code === 200) {
return ret.data.outlet_name
}
})
})
const list = await Promise.all(promiseList)
return list
}
export const getDisplayNames = async (
list: { outletId?: number; address?: string }[],
) => {
const promiseList = list.map((i) => {
if (i.outletId !== undefined) {
return getDisplayNamesFromOutletId([i.outletId]).then((ret) => ret[0])
} else if (i.address !== undefined) {
return getDisplayNamesFromAddress([i.address]).then((ret) => ret[0])
} else return ''
})
return Promise.all(promiseList)
}
export const getMsgFromAddress = async (
addressList: string[],
): Promise<any[]> => {
......
<template>
<div class="px-5">
<pwd-setting
:phone="$route.query.phone"
:phone="Phone()"
:sendSmsFunc="sendSmsFunc"
:setPwdFunc="setPwdFunc"
/>
......@@ -11,9 +11,20 @@
<script lang="ts">
import PwdSetting from "./PwdSetting.vue";
import { defineComponent } from "vue";
import { getUserMsg } from '@/utils/userMsg'
export default defineComponent({
components: { PwdSetting },
inject: ["sendSmsFunc", "setPwdFunc"],
methods: {},
created(){
console.log(this.$route.query.phone,'router');
this.Phone()
},
methods: {
Phone(){
const phone =getUserMsg()?.userInfo.phone+''
console.log(phone,'phone');
return phone
}
},
});
</script>
......@@ -12,20 +12,20 @@
<ServiceRating :setSelectedRate="handleSelect" :selected="selected" v-if="showServiceRating" />
<ChatOption>
<ChatOptionItemVue
v-if="isUser"
v-if="isUser && isChatWithRoboot"
:selected="questionSelected"
@click="handleClickQuestionOption"
value="常用问题"
/>
<ChatOptionItemVue
v-if="isUser"
v-if="isUser && isChatWithRoboot"
:selected="serviceSelected"
:value="serviceShowValue"
@click="handleClickService"
/>
<ChatOptionItemVue :selected="false" value="电话联系" @click="handleClickCall" />
</ChatOption>
<ChatInputVue :serviceShowValue="serviceShowValue"/>
<ChatInputVue :serviceShowValue="serviceShowValue" />
<CommonUseSentence
class="transition-all h-0"
:class="{ 'h-40': showShortSentences }"
......@@ -52,13 +52,17 @@ import { v4 as uuidv4 } from 'uuid'
import { ChatMessageTypes } from "@/types/chatMessageTypes";
import { useRoute } from "vue-router";
import { queryFaqAnswer, queryFaqList } from "@/service/FaqService";
import { getDisplayNamesFromAddress, getMsgFromAddress } from "@/utils/displayName";
import { getDisplayNames, getDisplayNamesFromAddress, getMsgFromAddress } from "@/utils/displayName";
import { MessageContent } from "@/types/chat-message";
import { CONST_END_CHAT, CONST_START_CHAT } from "@/config/chat";
import { CONST_END_CHAT, CONST_START_CHAT, CONST_WARNING } from "@/config/chat";
import ChatOptionItemVue from "@/components/ChatOptions/ChatOptionItem.vue";
import ShowCall from "@/components/showCall/index.vue"
import { getUserMsg } from "@/utils/userMsg";
import { eRole } from "@/types/roleType";
import ChatDBService from "@/db/ChatDBService";
import UserService from "@/service/UserService";
import { gotoChatWithStaff } from "@/router/navigate";
import { Toast } from "vant";
export default defineComponent({
......@@ -78,6 +82,7 @@ export default defineComponent({
const handleClickQuestionOption = () => {
questionSelected.value = !questionSelected.value
}
watch(questionSelected, () => {
setShowSentences(questionSelected.value)
sentensesLoading.value = true;
......@@ -91,23 +96,42 @@ export default defineComponent({
const serviceSelected = ref(false);
const serviceShowValue = ref('人工服务')
const handleClickService = () => {
const sendChatMessage = (payload: {
type: ChatMessageTypes;
content: MessageContent;
}) => {
messageStore.sendMessage({ type: payload.type, content: payload.content, target: route.query.targetId as string });
};
const sendChatMessage = (payload: {
type: ChatMessageTypes;
content: MessageContent;
target?: string;
}) => {
return messageStore.sendMessage({ type: payload.type, content: payload.content, target: payload.target || route.query.targetId as string });
};
const handleClickService = async () => {
if (serviceShowValue.value === '人工服务') {
sendChatMessage({
type: ChatMessageTypes.Card,
content: {
bank: CONST_START_CHAT.user.id,
name: CONST_START_CHAT.staff.id,
account: '',
} as MessageContent
questionSelected.value = false;
const ret = await UserService.getInstance().contact_custom_service({
outLetID: Number(route.query.targetId) as number
})
serviceShowValue.value = '结束服务'
if (ret.code === 200) {
gotoChatWithStaff({
address: ret.data.addr,
beginChat: true
});
} else {
// await sendChatMessage({
// type: ChatMessageTypes.Card,
// content: {
// bank: CONST_WARNING.user.id,
// name: CONST_WARNING.staff.id,
// account: '',
// } as MessageContent,
// target: route.query.targetId as string
// })
return;
}
} else if (serviceShowValue.value === '结束服务') {
serviceShowValue.value = '人工服务'
sendChatMessage({
......@@ -118,15 +142,8 @@ export default defineComponent({
account: '',
} as MessageContent
})
// showServiceRating.value = true;
}
}
onMounted(async () => {
const inChat = await ChatListCardDB.getInstance().getChatStatus(getFromId() as string, target)
serviceShowValue.value = inChat ? '结束服务' : '人工服务'
})
const initError = ref(false);
const showServiceRating = ref(false);
......@@ -145,12 +162,25 @@ export default defineComponent({
const handleClickCall = () => {
const handleClickCall = async () => {
if (isChatWithRoboot.value) {
const ret = await UserService.getInstance().contact_custom_service({
outLetID: Number(target) as number
})
if (ret.code === 200) {
callPhone.value = ret.data.phone;
} else {
return;
}
} else {
const ret = await getMsgFromAddress([target])
callPhone.value = ret[0].phone;
}
showCall.value = true;
}
const useSentence = (content: string) => {
const useSentence = async (content: string) => {
/* 问 */
messageStore.displayNewMessage({
content: {
......@@ -164,6 +194,23 @@ export default defineComponent({
type: ChatMessageTypes.robot,
})
await ChatDBService.getInstance().handleEveryReceive({
msg: {
content: {
content: content
},
from: getFromId() as string,
target: target,
uuid: uuidv4(),
state: 'success',
datetime: new Date().getTime(),
type: ChatMessageTypes.robot,
},
masterId: getFromId() as string,
isChattingWithTargetId: true,
isRoboot: true,
})
queryFaqAnswer({
question: content
}).then((ret) => {
......@@ -177,20 +224,32 @@ export default defineComponent({
from: target,
target: getFromId(),
uuid: uuidv4(),
state: 'success',
state: null,
datetime: new Date().getTime(),
type: ChatMessageTypes.robot,
})
ChatDBService.getInstance().handleEveryReceive({
msg: {
content: {
content: ret.data
},
from: target as string,
target: getFromId(),
uuid: uuidv4(),
state: null,
datetime: new Date().getTime(),
type: ChatMessageTypes.robot,
},
masterId: getFromId() as string,
isChattingWithTargetId: true,
isRoboot: true,
})
}
})
}
onMounted(async () => {
messageStore.messages.splice(0, messageStore.messages.length);
const messageList = await ChatMessageDB.getInstance().getMessage(getFromId() as string, target);
messageStore.messages.push(...messageList);
ChatListCardDB.getInstance().readMsg(getFromId() as string, target)
})
watch(chatCardTimeStamp, async () => {
const messageList = await ChatMessageDB.getInstance().getMessage(getFromId() as string, target);
......@@ -199,14 +258,60 @@ export default defineComponent({
})
const title = ref('')
const isChatWithRoboot = computed(() => {
return route.query.outlet !== undefined
})
const initTitle = async () => {
console.log(isChatWithRoboot.value, "show isChatWithRoboot")
if (isChatWithRoboot.value) {
const list = await getDisplayNames([{ outletId: Number(route.query.targetId) }])
title.value = list[0] as string;
} else {
const list = await getDisplayNames([{ address: route.query.targetId as string }])
title.value = list[0] as string;
}
}
const initMessageList = async () => {
messageStore.messages.splice(0, messageStore.messages.length);
const messageList = await ChatMessageDB.getInstance().getMessage(getFromId() as string, route.query.targetId as string);
messageStore.messages.push(...messageList);
ChatListCardDB.getInstance().readMsg(getFromId() as string, target)
}
const notifyUserAndStaffTheChatBegin = async () => {
await sendChatMessage({
type: ChatMessageTypes.Card,
content: {
bank: CONST_START_CHAT.user.id,
name: CONST_START_CHAT.staff.id,
account: '',
} as MessageContent,
target: route.query.targetId as string
})
}
watch(() => route.query.targetId, async () => {
await initMessageList();
await initTitle();
if (!isChatWithRoboot.value && route.query.beginChat !== undefined) {
setTimeout(() => {
if (!isChatWithRoboot.value) {
notifyUserAndStaffTheChatBegin()
}
}, 1000)
}
})
onMounted(async () => {
const list = await getDisplayNamesFromAddress([target])
title.value = list[0];
const ret = await getMsgFromAddress([target])
callPhone.value = ret[0].phone;
initMessageList();
initTitle();
serviceShowValue.value = '人工服务'
})
const showCall = ref(false)
const callPhone = ref('')
......@@ -215,6 +320,8 @@ export default defineComponent({
})
return {
connectionState,
selected,
......@@ -233,6 +340,7 @@ export default defineComponent({
handleClickCall,
showCall,
callPhone,
isChatWithRoboot,
isUser
};
},
......
......@@ -92,7 +92,7 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref } from "vue";
import { computed, defineComponent, ref, PropType } from "vue";
import default_avatar_url from "@/assets/user_avatar.png";
import { messageStore } from "@/store/messagesStore";
import ChatContentMessageTextVue from "./ChatContentMessageText.vue";
......@@ -121,7 +121,7 @@ export default defineComponent({
content: { type: Object, required: true },
type: { type: Number, required: true },
time: String,
state: String,
state: String as PropType<string | null | undefined>,
uuid: { type: String, required: true },
hideDatetime: Boolean,
uploadProgress: Object,
......
......@@ -51,7 +51,7 @@ import { MessageContent } from "@/types/chat-message";
import ChatInputTextVue from "./ChatInputText.vue";
import ChatInputAlbumVue from "./ChatInputAlbum.vue";
import ChatInputCameraVue from "./ChatInputCamera.vue";
import { getFromId, target } from "@/store/appCallerStore";
import { getFromId } from "@/store/appCallerStore";
import { textInputStore } from "@/store/textInputStore";
import { v4 as uuidv4 } from 'uuid'
import Icon from "@/components/common/Icon.vue";
......@@ -78,6 +78,8 @@ export default defineComponent({
voice,
}
const target = route.query.targetId as string
/** 输入框类型,文本 or 语音 */
const inputType = ref(InputType.text);
......@@ -119,7 +121,10 @@ export default defineComponent({
const isStaff = getUserMsg()?.role === eRole.staff;
const isUser = getUserMsg()?.role === eRole.user;
if (isUser && props.serviceShowValue === "人工服务") {
if (isUser && route.query.outlet !== undefined) {
/* 当前角色是客户,
并且和网点机器人进行聊天
*/
messageStore.displayNewMessage({
content: {
content: inputText.value
......@@ -145,6 +150,7 @@ export default defineComponent({
},
masterId: getFromId() as string,
isChattingWithTargetId: true,
isRoboot: true,
})
textInputStore.clearTextMessage();
} else {
......
......@@ -16,6 +16,7 @@ import { iNearbyOutLet } from "@/service/AddressService/types"
import AddressService from "@/service/AddressService"
import router from "@/router";
import UserService from "@/service/UserService";
import { goToChatWithOutletRoboot } from "@/router/navigate";
function isInViewPort(element: HTMLElement, barHeight: number) {
const viewWidth = window.innerWidth || document.documentElement.clientWidth;
......@@ -125,17 +126,9 @@ export default defineComponent({
number: 1,
})
if (ret.code === 200) {
const ret2 = await UserService.getInstance().contact_custom_service({
outLetID: ret.data[0].outlet_id as number
goToChatWithOutletRoboot({
outletId: ret.data[0].outlet_id
})
if (ret2.code == 200) {
router.push({
name: 'Chat',
query: {
target: ret2.data.addr
}
})
}
}
}
......@@ -234,30 +227,30 @@ export default defineComponent({
<img class="label6" src={leftBg} />
</div>
<div class=" bg-white mx-5 rounded-2xl overflow-hidden mt-5">
<div class="flex justify-between text-sm text-gray-800 border-b border-product-detail-bg">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">贷款机构</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{inst_name.value}</span>
</div>
<div class="flex justify-between text-sm text-gray-800 border-b border-product-detail-bg">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">产品名称</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{product_name.value}</span>
</div>
<div class="flex text-sm text-gray-800 border-b border-product-detail-bg justify-between">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">贷款利率</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{rate_lower.value}%~{rate_upper.value}%</span>
</div>
<div class="flex text-sm text-gray-800 border-b border-product-detail-bg justify-between">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">贷款额度</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{min_amount.value}~{max_amount.value}</span>
</div>
<div class="flex text-sm text-gray-800 border-b border-product-detail-bg justify-between">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">贷款期限</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{min_date.value}个月~{max_date.value}个月</span>
</div>
<div class="flex text-sm text-gray-800 border-b border-product-detail-bg justify-between">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">担保方式</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{filterGuaranteeType(guarantee_type.value)}</span>
</div>
<div class="flex justify-between text-sm text-gray-800 border-b border-product-detail-bg">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">贷款机构</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{inst_name.value}</span>
</div>
<div class="flex justify-between text-sm text-gray-800 border-b border-product-detail-bg">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">产品名称</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{product_name.value}</span>
</div>
<div class="flex text-sm text-gray-800 border-b border-product-detail-bg justify-between">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">贷款利率</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{rate_lower.value}%~{rate_upper.value}%</span>
</div>
<div class="flex text-sm text-gray-800 border-b border-product-detail-bg justify-between">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">贷款额度</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{min_amount.value}~{max_amount.value}</span>
</div>
<div class="flex text-sm text-gray-800 border-b border-product-detail-bg justify-between">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">贷款期限</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{min_date.value}个月~{max_date.value}个月</span>
</div>
<div class="flex text-sm text-gray-800 border-b border-product-detail-bg justify-between">
<span class=" w-100 align-center bg-product-detail-bg py-4 inline-block text-center">担保方式</span>
<span class=" w-235 py-4 pr-5 inline-block break-words text-right">{filterGuaranteeType(guarantee_type.value)}</span>
</div>
</div>
<LoanDetailDescribe class=" mt-5" products={products.value} features={features.value} apply_to={apply_to.value} apply_cond={apply_cond.value} submit_cond={submit_cond.value} />
<div class="title mx-5 mt-5" >营业网点</div>
......@@ -314,10 +307,10 @@ export default defineComponent({
color: #ffffff;
}
.w-100{
width:100px;
.w-100 {
width: 100px;
}
.w-235{
width:235px;
.w-235 {
width: 235px;
}
</style>
\ No newline at end of file
<template>
<div @click="$router.push({path: 'NewsDetail', query: { uuid: info.uuid, type: 'news' }})" class=" border-b border-gray-200 py-5">
<div class=" text-base text-gray-900 font-semibold">{{ info.title }}</div>
<div class=" text-xs text-gray-800 pt-3">{{ info.desc }}</div>
<div class=" text-base text-gray-900 font-semibold news-title">{{ info.title }}</div>
<div class=" text-xs text-gray-800 pt-3 news-info">{{ info.desc }}</div>
<div
v-if="showImg"
class=" h-32 bg-app-blue mt-2 bg-cover bg-center bg-no-repeat"
......@@ -36,5 +36,16 @@ export default defineComponent({
</script>
<style scoped>
.news-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap
}
.news-info {
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-break: break-all;
}
</style>
\ No newline at end of file
<template>
<Navbar
:title="navBarTitle"
:showBackIcon="false"
/>
<Navbar :title="navBarTitle" :showBackIcon="false" />
<div class="mx-5">
<div
v-for="(item, index) in cardList"
......@@ -26,10 +23,10 @@
</div>
</div>
<div
v-if="isChatListEmpty"
v-if="!cardListLoading && isChatListEmpty"
class="empty text-center fixed w-full top-1/2 transform -translate-y-1/2 -mt-6"
>
<img src="@/assets/img/empty.png" class="mb-5" />
<img src="@/assets/img/empty.png" class="mb-5" />
<div class="no-chat mb-2.5">暂无聊天</div>
<div v-if="userType === eRole.user" class="tip">咨询客户经理后,可以在这里快捷查看消息哦!</div>
<div v-else-if="userType === eRole.staff" class="tip">客户咨询后,可以在这里快捷查看消息哦!</div>
......@@ -47,25 +44,44 @@ import { getUserMsg } from "@/utils/userMsg";
import { eRole } from "@/types/roleType";
import ChatMessageDB from "@/db/ChatMessageDB";
import router from "@/router";
import UserService from "@/service/UserService";
import { getDisplayNamesFromAddress } from "@/utils/displayName";
import { getDisplayNames, getDisplayNamesFromAddress, getDisplayNamesFromOutletId } from "@/utils/displayName";
const cardList = ref<(iChatListCard & { displayName?: string })[]>([]);
const showList = ref<boolean[]>([]);
const selectedIndex = ref<number>()
const cardListLoading = ref(false);
const renderList = async () => {
cardListLoading.value = true;
const list = await ChatListCardDB.getInstance().getCardList(getFromId() as string)
const addressList = list.map(i => i.targetId);
cardList.value = list;
const displayNames = await getDisplayNamesFromAddress(addressList)
const reqlist = list.map(i => {
if (i.isRobootCard) {
return {
outletId: Number(i.targetId),
}
} else {
return {
address: i.targetId,
}
}
})
const displayNames = await getDisplayNames(reqlist)
// const displayNames = await getDisplayNamesFromAddress(addressList)
// await getDisplayNamesFromOutletId(list)
cardList.value = list.map((item, index) => {
return {
...item,
displayName: displayNames[index]
}
})
cardListLoading.value = false;
}
onMounted(async () => {
......@@ -120,6 +136,7 @@ function handleClickItem(index: number, item: iChatListCard) {
name: 'Chat',
query: {
targetId: item.targetId,
outlet: item.isRobootCard ? 'true' : undefined
}
})
}
......
import Bridge from "@/utils/jsBridge2"
export default [
{
name: '贷款服务',
......@@ -41,7 +42,10 @@ export default [
icon: 'icon-jingcaizhibo',
color: '#0FCBA5',
cb(){
new Bridge().bridge_live()
new Bridge().bridge_live({
phone: JSON.parse(window.localStorage.getItem('USER_MSG') as string)?.userInfo.phone,
avatar: window.location.host + require('../../../assets/icons/avatar.png')
})
},
},
{
......
<template>
<div class="pb-5">
<div class="pb-5 min-h-screen overflow-scroll mb-8">
<nav-bar
title="网点服务"
:style="{ 'background-color': '#2C3C92 !important', 'color': 'white' }"
......@@ -23,29 +23,30 @@
class="mt-3 shadow-sm"
/>
</Skeleton>
<Skeleton :row="3" :loading="result.loading" class="mt-5">
<div class="overflow-scroll -mt-8 pb-5">
<p class="mt-12 mb-3 text-base font-semibold text-gray-800">附近的网点</p>
<branch
v-for="(item, index) in result.lists"
:key="index"
:name="item.name"
:distance="item.distance"
:is_normal_work="item.is_normal_work"
:latitude="item.latitude"
:location="item.location"
:longitude="item.longitude"
:opening_hours="item.opening_hours"
:weekend_status="item.weekend_status"
:outlet_id="item.outlet_id"
class="mt-3 shadow-sm"
/>
<!-- <branch :isOpen="false" class="mt-3 shadow-sm"/> -->
</div>
</Skeleton>
</div>
<!-- 附近网点 -->
<Skeleton :row="3" :loading="result.loading" class="-mt-20 mb-10"></Skeleton>
<Skeleton :row="3" :loading="result.loading" class="mt-5">
<div class="px-4 overflow-scroll -mt-8">
<p class="mt-12 mb-3 text-base font-semibold text-gray-800">附近的网点</p>
<branch
v-for="(item, index) in result.lists"
:key="index"
:name="item.name"
:distance="item.distance"
:is_normal_work="item.is_normal_work"
:latitude="item.latitude"
:location="item.location"
:longitude="item.longitude"
:opening_hours="item.opening_hours"
:weekend_status="item.weekend_status"
:outlet_id="item.outlet_id"
class="mt-3 shadow-sm"
/>
<!-- <branch :isOpen="false" class="mt-3 shadow-sm"/> -->
</div>
</Skeleton>
<Skeleton :row="3" :loading="result.loading" class="mt-10"></Skeleton>
<Skeleton :row="3" :loading="result.loading" class="mt-10"></Skeleton>
</div>
......
......@@ -15,12 +15,11 @@
<div class="px-5 py-2 items-center border-b border-gray-200">
<div class="flex justify-between items-center">
<div>
<div class=" text-sm font-semibold">登陆密码</div>
<div class=" text-sm font-semibold">设置密码</div>
<div class=" text-xs text-gray-400 pt-1">保障账户登录安全</div>
</div>
<div class="flex items-center text-xs h-1 text-right">
<span v-if="hasPassword == 3" @click="pushRouter">设置</span>
<span v-else-if="hasPassword == 2" @click="pushRouter">修改</span>
<span @click="pushRouter">设置</span>
<icon
name="icon-gengduo"
color="#8E92A3"
......@@ -43,14 +42,16 @@ import { deleteUserMsg, getUserMsg } from '@/utils/userMsg'
import filter from "@/filter"
import router from '@/router'
import { userLogout } from '@/service/UserManagementService'
import { userChangePwd,userLogin} from '@/service/UserManagementService'
import { eSmsType, sendVerifyCode } from '@/service/VerificationService'
import set from '@/views/Auth/PwdSetting/index.vue'
export default defineComponent({
components: { NavBar, Icon ,set},
components: { NavBar, Icon },
data(){
return{
role:''
}
},
computed: {
hasPassword(): eAccountType {
return eAccountType.REG_PDSET
return eAccountType.REG_NOPD
},
getPhone(){
const phone =getUserMsg()?.userInfo.phone+''
......@@ -74,16 +75,9 @@ export default defineComponent({
},
methods:{
pushRouter(){
console.log('123');
if(this.hasPassword == 3){
this.$router.push({
name: 'PwdSetting'
})
}else if(this.hasPassword == 2){
this.$router.push({
name: 'PwdModify'
})
}
},
}
})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment