Commit 73e83fe8 authored by Zhang Xiaojie's avatar Zhang Xiaojie

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

parent 1209722f
This diff is collapsed.
......@@ -25,6 +25,7 @@
"secp256k1": "^4.0.2",
"uuid": "^8.3.2",
"vant": "^3.2.0",
"vconsole": "^3.0.0",
"vue": "^3.0.0",
"vue-cropperjs": "^5.0.0",
"vue-router": "^4.0.0-0",
......
<template>
<van-config-provider :theme-vars="themeVars">
<van-config-provider :theme-vars="{ skeletonRowBackgroundColor: '#bfbfbf', }">
<div id="nav" class="bg-app-bg min-h-screen">
<router-view />
</div>
......@@ -13,7 +13,6 @@ import FzmMessageProtocol from "@/utils/fzm-message-protocol";
import { generateToken } from "./utils/generateToken/generate-token";
import { defineComponent, onBeforeUnmount, onMounted, watch } from "vue";
import decodeChatMessage from "./utils/fzm-message-protocol-chat/decodeChatMessage";
import { messageStore } from "./store/messagesStore";
import ChatDBService from "@/db/ChatDBService"
import { getMasterIdFromDisplayMsg, getTargetIdFromDisplayMsg } from "./utils/chatutils";
import isChattingWith from "./utils/isChattingWith";
......@@ -27,7 +26,6 @@ import router from "./router";
import { useRoute } from "vue-router";
export default defineComponent({
setup() {
......@@ -104,7 +102,7 @@ export default defineComponent({
};
console.log(displayMsg, 'in receive');
msg && displayMsg && (ChatDBService.getInstance().handleEveryReceive({
msg: displayMsg,
masterId: getMasterIdFromDisplayMsg(displayMsg),
......@@ -126,9 +124,6 @@ export default defineComponent({
connectionState.connection?.disconnect();
});
return {
themeVars: {
skeletonRowBackgroundColor: '#bfbfbf',
},
}
}
})
......
......@@ -77,34 +77,12 @@
<p class="w-1/2 border-r border-gray-300 mb-0" @click="handleClickChatWithClientManager">联系客服</p>
<p class="w-1/2 mb-0" :class="isOpen ? 'text-app-blue' : 'text-gray-800'" @click="toCall">电话咨询</p>
</div>
<van-popup v-model:show="show" round teleport="body" :style="{ width: '90%', top: '80%' }">
<div class="text-center py-4" @click="handleClickCall">
<icon
name="icon-a-dianhua"
color="#3E4FAF"
size="17"
class="inline-block pr-3 align-text-bottom"
/>
<span class="text-app-blue text-sm align-middle font-semibold">呼叫95533</span>
</div>
</van-popup>
<van-popup
v-model:show="show"
round
:style="{ width: '90%', margin: '60px auto 0px auto', top: '80%' }"
teleport="body"
:overlay="false"
>
<div
class="text-app-blue text-sm font-semibold border-t border-gray-200 text-center py-4"
@click="show = false"
>取消</div>
</van-popup>
<show-call :show="show" :phone="phone" @hidden="hidden" />
</div>
</template>
<script lang="ts" setup>
import { computed, PropType, ref } from 'vue'
import { computed, defineComponent, PropType, ref } from 'vue'
import Icon from "@/components/common/Icon.vue"
import { transfterStrToDate } from '@/utils/transfer'
import AddressService from '@/service/AddressService'
......@@ -114,9 +92,14 @@ import jsBridge from "@/utils/jsBridge2"
import UserService from '@/service/UserService'
import { authCheck } from '@/utils/authCheck'
import router from '@/router'
import ShowCall from '@/components/showCall/index.vue'
const addressService = new AddressService()
const components = defineComponent({
ShowCall
})
const props = defineProps({
changeable: {
type: Boolean,
......@@ -207,23 +190,24 @@ const getErrorNote = () => {
getErrorNote()
let show = ref(false)
const phone = ref('')
const toCall = () => {
if (isOpen) {
show.value = true
}
authCheck(async () => {
const ret = await UserService.getInstance().contact_custom_service({
outLetID: props.outlet_id as number
})
if (ret.code === 200) {
phone.value = ret.data.phone
show.value = true
}
})
}
const handleClickCall = async () => {
const ret = await UserService.getInstance().contact_custom_service({
outLetID: props.outlet_id as number
})
if (ret.code === 200) {
new jsBridge().bridge_call(ret.data.phone, () => {
show.value = false;
})
}
const hidden = (v: boolean) => {
show.value = v
}
const handleClickNagigate = () => {
new jsBridge().bridge_navigate(`${props.longitude},${props.latitude}`, () => {
show.value = false;
......
<template>
<div>
<van-popup v-model:show="show" round teleport="body" :style="{ width: '90%', top: '80%' }" @click-overlay="hide">
<div class="text-center py-4" @click="handleClickCall">
<icon
name="icon-a-dianhua"
color="#3E4FAF"
size="17"
class="inline-block pr-3 align-text-bottom"
/>
<span class="text-app-blue text-sm align-middle font-semibold">呼叫{{ phone }}</span>
</div>
</van-popup>
<van-popup
v-model:show="show"
round
:style="{ width: '90%', margin: '60px auto 0px auto', top: '80%' }"
teleport="body"
:overlay="false"
@click-overlay="hide"
>
<div
class="text-app-blue text-sm font-semibold border-t border-gray-200 text-center py-4"
@click="hide"
>取消</div>
</van-popup>
</div>
</template>
<script lang="ts" setup>
import Vue, { ComponentInternalInstance, getCurrentInstance } from 'vue'
import jsBridge from "@/utils/jsBridge2"
const { ctx } = getCurrentInstance() as any
console.log(ctx)
const props = defineProps({
show: {
type: Boolean,
default: false,
},
phone: {
type: String,
}
})
const hide = () => {
console.log(ctx, 'ctx')
ctx.$emit('hidden', false)
}
const handleClickCall = async () => {
console.log(props.phone)
new jsBridge().bridge_call(props.phone, () => {
ctx.$emit('hidden', false)
})
}
</script>
\ No newline at end of file
import { DisplayMessage, messageStore } from '@/store/messagesStore'
import { getTargetIdFromDisplayMsg } from '@/utils/chatutils'
import { MyAppDatabase } from './index'
export default class ChatMessageDB extends MyAppDatabase {
......@@ -28,11 +29,32 @@ export default class ChatMessageDB extends MyAppDatabase {
})
}
deleteMsg({ uuid, logid }: { uuid?: string; logid?: string }) {
async deleteMsg({ uuid, logid }: { uuid?: string; logid?: string }) {
const updateChatList = async (masterId: string, target: string) => {
const latestedMsg = await this.getLatestedMessage(masterId, target)
if (latestedMsg) {
/* 如果和target还有聊天消息 */
// latestedMsg.content.content
this.chatListCard
.filter((i) => i.masterId === masterId && i.targetId === target)
.modify((i) => (i.content = latestedMsg.content.content as string))
} else {
/* 如果和target没有聊天消息 */
this.chatListCard
.filter((i) => i.masterId === masterId && i.targetId === target)
.modify((i) => (i.content = ''))
}
}
if (uuid) {
return this.chatMessage.where('uuid').equals(uuid).delete()
const item = await this.chatMessage.where('uuid').equals(uuid).first()
await this.chatMessage.where('uuid').equals(uuid).delete()
item && updateChatList(item?.masterId, getTargetIdFromDisplayMsg(item))
} else if (logid) {
return this.chatMessage.where('logid').equals(logid).delete()
const item = await this.chatMessage.where('logid').equals(logid).first()
await this.chatMessage.where('logid').equals(logid).delete()
item && updateChatList(item?.masterId, getTargetIdFromDisplayMsg(item))
} else {
throw new Error('没有uuid或者logid')
}
......@@ -63,6 +85,30 @@ export default class ChatMessageDB extends MyAppDatabase {
.toArray()
}
/* wo获取和ta之间最新的消息 */
async getLatestedMessage(from: string, target: string) {
const ret = await this.chatMessage
.filter((item) => {
return (
item.masterId === from &&
((item.state === null && target === item.from) ||
(item.state !== null && target === item.target))
)
})
.count()
console.log(ret, 'show count')
return this.chatMessage
.filter((item) => {
return (
item.masterId === from &&
((item.state === null && target === item.from) ||
(item.state !== null && target === item.target))
)
})
.last()
}
deleteMsgGroup(masterId: string, targetId: string) {
this.chatMessage
.filter((item) => {
......
import { iUserinfo } from '@/service/UserService/types'
import { MyAppDatabase } from './index'
export default class UserInfoDBService {
static instance: UserInfoDBService
private userInfo: Dexie.Table<iUserinfo, number>
static getInstance() {
if (!UserInfoDBService.instance) {
UserInfoDBService.instance = new UserInfoDBService()
}
return UserInfoDBService.instance
}
constructor() {
const db = new MyAppDatabase()
this.userInfo = db.userInfo
}
save(list: iUserinfo[]) {
return this.userInfo.bulkAdd(list)
}
async findByList(addressList: string[]) {
const list = await this.userInfo
.filter((i) => {
return addressList.includes(i.addr)
})
.toArray()
const notFoundList = addressList.filter(
(i) => list.findIndex((item) => item?.addr === i) === -1,
)
return {
foundList: list,
notFoundList,
}
}
}
import Dexie from 'dexie'
import { DisplayMessage } from '@/store/messagesStore'
import { iContact } from '@/service/UserService/types'
import { iContact, iUserinfo } from '@/service/UserService/types'
export interface iChatMessage extends DisplayMessage {
masterId: string
masterId: string // 这条消息展示在谁的页面上
}
export interface iChatListCard {
......@@ -17,19 +17,23 @@ export class MyAppDatabase extends Dexie {
chatMessage: Dexie.Table<iChatMessage, number>
chatListCard: Dexie.Table<iChatListCard, number>
contactPerson: Dexie.Table<iContact, number>
userInfo: Dexie.Table<iUserinfo, number>
constructor() {
super('MyAppDatabase')
this.version(1).stores({
this.version(1.2).stores({
chatMessage:
'++id, content, from, uuid, state, uploadProgress, type, datetime, hideDatetime, logid, masterId, readed',
chatListCard: '++id, masterId, targetId, unreadMsgCount, content',
contactPerson: '++id, addr, bank, phone, user_name',
userInfo: '++id, created_at, phone, remark, user_name, uuid, addr',
})
this.chatMessage = this.table('chatMessage')
this.chatListCard = this.table('chatListCard')
this.contactPerson = this.table('contactPerson')
this.userInfo = this.table('userInfo')
}
}
......@@ -7,7 +7,7 @@ export default {
filterDistance(distance: string){
if(!distance) return ''
const m = Number(distance)
const k = (m / 1000).toFixed(2)
const k = (m).toFixed(2)
return `${k}km`
}
} as { [key: string]: (...args: any) => any }
......@@ -32,6 +32,8 @@ import '@quasar/extras/eva-icons/eva-icons.css'
import longPress from '@/plugins/longPress'
import { format } from '@/utils/time'
const app = createApp(App)
app.config.globalProperties.$format = format
......
......@@ -35,6 +35,9 @@ const routes: Array<RouteRecordRaw> = [
{
path: '/chatList',
name: 'ChatList',
meta: {
needAuth: true
},
component: () =>
import(
/* webpackChunkName: "chatList" */ '@/views/withMenu/ChatList/index.vue'
......
import { Toast } from 'vant'
import baseAxios, { iRet } from '../index'
import { iNearbyOutLet } from './types'
import Bridge from '@/utils/jsBridge2'
class AddressService {
static instance: AddressService
static getInstance() {
......@@ -11,13 +12,44 @@ class AddressService {
}
getNearby(data: { bank_code: number; number: number }) {
// return baseAxios<iNearbyOutLet[]>({
// method: 'post',
// url: '/address/nearby',
// data: {
// ...data,
// longitude: '120.194393',
// latitude: '30.244417',
// },
// })
return new Promise<iRet<iNearbyOutLet[]>>((resolve) => {
function getGps() {
new Bridge().bridge_getGps(null, (params: any) => {
console.log(params, 'show params')
const list = params.split(',')
resolve(
baseAxios<iNearbyOutLet[]>({
method: 'post',
url: '/address/nearby',
data: {
...data,
longitude: list[0],
latitude: list[1],
},
}),
)
})
}
if ('geolocation' in window.navigator) {
window.navigator.geolocation.getCurrentPosition(
(position) => {
const la = position.coords.latitude.toString()
const lo = position.coords.longitude.toString()
console.log(position, 'position')
resolve(
baseAxios<iNearbyOutLet[]>({
method: 'post',
url: '/address/nearby',
......@@ -30,11 +62,12 @@ class AddressService {
)
},
(error) => {
Toast(error.message)
console.log(error)
getGps()
},
)
} else {
Toast('不支持获取GPS')
getGps()
}
})
}
......
import baseAxios from '../index'
import { iContact } from './types'
import { iContact, iUserinfo } from './types'
class UserService {
static instance: UserService
static getInstance() {
......@@ -23,7 +23,19 @@ class UserService {
method: 'get',
params: data,
paramsSerializer: (data: { addrs: string[] }) => {
console.log(data);
console.log(data)
return `addrs=${data.addrs.toString()}`
},
})
}
userInfo(data: { addrs: string[] }) {
return baseAxios<iUserinfo[]>({
url: '/user/user_info',
method: 'get',
params: data,
paramsSerializer: (data: { addrs: string[] }) => {
console.log(data)
return `addrs=${data.addrs.toString()}`
},
})
......
......@@ -4,3 +4,12 @@ export interface iContact {
phone: string
user_name: string
}
export interface iUserinfo {
addr: string
created_at: number
phone: string
remark: string
user_name: string
uuid: string
}
import router from '@/router'
import { getUserMsg } from '@/utils/userMsg'
import axios, { AxiosRequestConfig } from 'axios'
import { Toast } from 'vant'
......@@ -9,7 +10,13 @@ const baseAxios = axios.create({
baseAxios.interceptors.response.use(
(baseRet: AxiosRequestConfig) => {
const ret = baseRet.data as iRet
if (ret.code !== 200) {
if ([504, 503].includes(ret.code)) {
Toast.fail(ret.msg)
localStorage.clear()
router.push({
name: 'Login',
})
} else if (ret.code !== 200) {
Toast.fail(ret.msg)
}
return baseRet.data
......
import ContactPersonService from '@/db/ContactPersonService'
import UserInfoDBService from '@/db/UserInfoService'
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[]> => {
/* 数据库查 有结果拿 没结果网上查且存 */
const user = getUserMsg()
const {
foundList,
notFoundList,
} = await ContactPersonService.getInstance().findByList(addressList)
let foundList = [] as any[]
let notFoundList = [] as any[]
const fullList = foundList
if (user?.role === eRole.user) {
const ret = await ContactPersonService.getInstance().findByList(addressList)
foundList = ret.foundList
notFoundList = ret.notFoundList
} else if (user?.role === eRole.staff) {
const ret = await UserInfoDBService.getInstance().findByList(addressList)
foundList = ret.foundList
notFoundList = ret.notFoundList
}
const fullList = (foundList as unknown) as any
if (notFoundList.length !== 0) {
const ret = await UserService.getInstance().staffInfo({
addrs: notFoundList,
})
if (ret.code === 200) {
const theoseNotFoundList = ret.data.item
ContactPersonService.getInstance().save(theoseNotFoundList)
fullList.push(...theoseNotFoundList)
if (user?.role === eRole.user) {
const ret = await UserService.getInstance().staffInfo({
addrs: notFoundList,
})
if (ret.code === 200) {
const theoseNotFoundList = ret.data.item
ContactPersonService.getInstance().save(theoseNotFoundList)
fullList.push(...theoseNotFoundList)
}
} else if (user?.role === eRole.staff) {
const ret = await UserService.getInstance().userInfo({
addrs: notFoundList,
})
if (ret.code === 200) {
const theoseNotFoundList = ret.data
UserInfoDBService.getInstance().save(theoseNotFoundList)
fullList.push(...theoseNotFoundList)
}
}
}
return addressList.map((item) => {
return fullList.find((i) => i?.addr === item)?.user_name || '未知用户'
const msg = fullList.find((i: any) => i?.addr === item)
return msg?.user_name || msg?.phone
})
}
......@@ -511,5 +511,15 @@ jsBridge.prototype.bridge_navigate = function (params, success) {
}
}
/* 跳到导航软件 */
jsBridge.prototype.bridge_getGps = function (params, success) {
if (this.curApp == ANDROID) {
dsBridge.call('bridge_getGps', params, success)
}
else if (this.curApp == IOS) {
this.callHandler('bridge_getGps', params, success)
}
}
export default jsBridge;
......@@ -6,8 +6,8 @@ export function transfterStrToDate(str: string) {
start = start.replace(':', ':').replace('早上', '').replace('下午', '')
end = end.replace(':', ':').replace('早上', '').replace('下午', '')
const d = new Date()
start = `${d.getFullYear()} ${d.getMonth() + 1} ${d.getDate()} ${start}`
end = `${d.getFullYear()} ${d.getMonth() + 1} ${d.getDate()} ${end}`
start = `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()} ${start}`
end = `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()} ${end}`
const startDate = new Date(start)
const endDate = new Date(end)
return [startDate, endDate]
......
......@@ -69,6 +69,8 @@ export default defineComponent({
const optionList = [
{ name: '常用问题', id: 1 },
{ name: '人工服务', id: 2 },
{ name: '电话咨询', id: 3 },
];
const setShowSentences = (show: boolean) =>
......@@ -92,6 +94,10 @@ export default defineComponent({
} else {
setShowSentences(false)
}
if (selectedChatOption.value === 3) {
}
})
const useSentence = (content: string) => {
......@@ -150,8 +156,6 @@ export default defineComponent({
})
return {
connectionState,
selected,
......
......@@ -12,11 +12,7 @@
<!-- 消息气泡 -->
<div :class="[{ 'flex-row-reverse': fromMyself }]">
<div
:class="{ 'text-right': fromMyself }"
style="font-size: 12px;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;color: #adadad;
"
></div>
<div :class="{ 'text-right': fromMyself }" class="message_"></div>
<div
:class="[{ 'flex-row-reverse': fromMyself }]"
class="flex items-center max-w-chat-msg-bubble"
......@@ -157,7 +153,7 @@ export default defineComponent({
const textMsgActions = [
{
text: '删除', cb(data: { content: any, uuid: string, logid?: string }) {
text: '删除', cb(data: { content: any, uuid: string, logid?: string, }) {
ChatMessageDB.getInstance().deleteMsg({ uuid: data.uuid, logid: data.logid });
const index = messageStore.messages.findIndex(i => {
return i.uuid === data.uuid
......@@ -201,4 +197,12 @@ export default defineComponent({
},
});
</script>
\ No newline at end of file
</script>
<style scoped>
.message_ {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
color: #adadad;
font-weight: 400;
}
</style>
\ No newline at end of file
......@@ -13,6 +13,7 @@ export default [
routeName: 'ChatList',
icon: 'icon-liaotian-dianji',
roles: [eRole.staff, eRole.user],
showNotLogin: true,
},
{
name: '贷款',
......
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