保单数量接口联调

master
wujingling0908 2 weeks ago
parent cbf2ba72f1
commit 28deaa60bf
  1. 2
      src/App.vue
  2. 33
      src/components/abstract.vue
  3. 16
      src/components/chat-content.vue
  4. 4
      src/components/gmNetwork-address.vue
  5. 15
      src/main.js
  6. 2
      src/store/app.js
  7. 40
      src/utils/index.js
  8. 100
      src/views/chat.vue

@ -106,7 +106,7 @@ onUnmounted(() => {
<template> <template>
<div id="app" class="app-wrapper opacity"> <div id="app" class="app-wrapper opacity">
<RouterView v-slot="{ Component }"> <RouterView v-slot="{ Component }">
<keep-alive include="chat"> <keep-alive include="chat-new">
<component :is="Component" /> <component :is="Component" />
</keep-alive> </keep-alive>
</RouterView> </RouterView>

@ -2,6 +2,7 @@
import { ref, onMounted, computed, inject } from 'vue'; import { ref, onMounted, computed, inject } from 'vue';
import { Post } from '@/utils/https' import { Post } from '@/utils/https'
import { messageSend } from '@/utils/api' import { messageSend } from '@/utils/api'
import { getHiddenProp, getVisibilityState, decryptByVersionNo1, isSit, Encrypt, isDev, isProd } from "@/utils";
const store = inject('appStore', null) const store = inject('appStore', null)
const businessHandleInfo = ref({}) const businessHandleInfo = ref({})
const abstractList = computed(() => [ const abstractList = computed(() => [
@ -51,6 +52,37 @@ const businessHandle = () => {
}); });
} }
} }
const isIdentityNo = (value) => /^\d{15}$|^\d{17}[\dXx]$/.test(String(value || '').trim())
// 与 liics 一致:明文身份证来自解密 userInfo.pid(encryptPid 是给外部系统用的密文,不能直接解)
const getIdentityCardno = () => {
const versionNo = store.userInfo?.versionNo1 || ''
const pidCipher = store.userInfo?.pid || ''
if (!versionNo || !pidCipher) return ''
const identityCardno = decryptByVersionNo1(versionNo, pidCipher)
console.log('decrypt pid =>', JSON.stringify(identityCardno))
return isIdentityNo(identityCardno) ? identityCardno.trim() : ''
}
const getOrderCount = () => {
try {
const identityCardno = getIdentityCardno()
if (!identityCardno) {
console.warn('证件号解密失败', {
hasPid: Boolean(store.userInfo?.pid),
hasVersionNo1: Boolean(store.userInfo?.versionNo1),
})
return
}
Post('policy/queryCount', {
dentityCardno: identityCardno,
})
} catch (error) {
console.log(error)
}
}
const toDetail = (record) => { const toDetail = (record) => {
const text = record?.name const text = record?.name
console.log('text',text); console.log('text',text);
@ -61,6 +93,7 @@ const toDetail = (record) => {
} }
onMounted(async () => { onMounted(async () => {
businessHandle() businessHandle()
getOrderCount()
}) })
</script> </script>
<template> <template>

@ -1,7 +1,7 @@
<template> <template>
<div class="chat-content-box historicRecords" v-if="historylist && historylist.length > 0"> <div class="chat-content-box historicRecords" v-if="historylist && historylist.length > 0">
<div <div
:class="[$elder ? 'elder-wrapper' : '', (integratedUser && manualService == 2 && item.sessionId === sessionId) ? 'disable-sys-menu' : '']" :class="[elder ? 'elder-wrapper' : '', (integratedUser && manualService == 2 && item.sessionId === sessionId) ? 'disable-sys-menu' : '']"
class="chat-content-box-item opacity" style="position: relative;" v-for="(item, index) in historylist" class="chat-content-box-item opacity" style="position: relative;" v-for="(item, index) in historylist"
:key="index" :id="item.VIEW_ID" :key="index" :id="item.VIEW_ID"
v-show="(item.msgText && item.msgText != 'null') || item.cmd === 'ServiceSessionOpenedEvent'" v-show="(item.msgText && item.msgText != 'null') || item.cmd === 'ServiceSessionOpenedEvent'"
@ -25,7 +25,7 @@
"> ">
<span class="session-tips">{{ <span class="session-tips">{{
FormatDate(item.timestamp, "yyyy年MM月dd日 hh:mm") FormatDate(item.timestamp, "yyyy年MM月dd日 hh:mm")
}}</span> }}</span>
</div> </div>
<!-- <div class="chat-content-other" v-if="item.fromFlag == 'other'"> <!-- <div class="chat-content-other" v-if="item.fromFlag == 'other'">
<span class="session-tips" v-html="item.msgText"></span> <span class="session-tips" v-html="item.msgText"></span>
@ -170,7 +170,7 @@
<div class="content-left-main scheduleTimeout-box"> <div class="content-left-main scheduleTimeout-box">
<div class="leave-message-cont" v-html="item.msgText"></div> <div class="leave-message-cont" v-html="item.msgText"></div>
<!-- 2021/12 关爱版开启留言按钮, 隐藏95950000 95980000 95985000渠道留言按钮 --> <!-- 2021/12 关爱版开启留言按钮, 隐藏95950000 95980000 95985000渠道留言按钮 -->
<div class="leave-message-btn" v-if="!$nohxmessage.includes(source) && userInfo.blacklistFlag != '1'"> <div class="leave-message-btn" v-if="!(($nohxmessage || []).includes(source)) && userInfo.blacklistFlag != '1'">
<button class="answer-items" disabled="disabled" @click.stop="leaveMessageBtn($event)"> <button class="answer-items" disabled="disabled" @click.stop="leaveMessageBtn($event)">
点击此处,给我们留言 点击此处,给我们留言
</button> </button>
@ -195,7 +195,7 @@
<div class="content-left-main"> <div class="content-left-main">
<div class="leave-message-cont" v-html="item.msgText"></div> <div class="leave-message-cont" v-html="item.msgText"></div>
<!-- 2021/12 关爱版开启留言按钮, 隐藏95950000 95980000 95985000渠道留言按钮 --> <!-- 2021/12 关爱版开启留言按钮, 隐藏95950000 95980000 95985000渠道留言按钮 -->
<div class="leave-message-btn" v-if="!$nohxmessage.includes(source) && userInfo.blacklistFlag != '1'"> <div class="leave-message-btn" v-if="!(($nohxmessage || []).includes(source)) && userInfo.blacklistFlag != '1'">
<button class="answer-items" disabled="disabled" @click.stop="leaveMessageBtn($event)"> <button class="answer-items" disabled="disabled" @click.stop="leaveMessageBtn($event)">
点击此处,给我们留言 点击此处,给我们留言
</button> </button>
@ -1216,7 +1216,6 @@ export default {
isWX: false, isWX: false,
isAndroid: false, isAndroid: false,
audioItemId: '', audioItemId: '',
elder: this.$elder,
hxOpenSuccesed: [], hxOpenSuccesed: [],
quoteMenuTimestamp: null, quoteMenuTimestamp: null,
quoteMenuItem: null, quoteMenuItem: null,
@ -1256,6 +1255,7 @@ export default {
'hxOpenSucceseds', 'hxOpenSucceseds',
'integratedUser', 'integratedUser',
'token', 'token',
'elder',
]), ]),
}, },
created() { created() {
@ -2260,7 +2260,7 @@ export default {
background-color: #4c4c4c; background-color: #4c4c4c;
} }
::v-deep .quote-active-bubble { :deep(.quote-active-bubble) {
filter: brightness(0.9) !important; filter: brightness(0.9) !important;
opacity: 0.9 !important; opacity: 0.9 !important;
transition: all 0.2s; transition: all 0.2s;
@ -2297,8 +2297,8 @@ export default {
line-height: normal; line-height: normal;
} }
::v-deep .quote-display-inner img[alt="small-image"], :deep(.quote-display-inner img[alt="small-image"]),
::v-deep .quote-display-inner img[alt="big-image"] { :deep(.quote-display-inner img[alt="big-image"]) {
display: inline-block !important; display: inline-block !important;
vertical-align: middle !important; vertical-align: middle !important;
width: 20px !important; width: 20px !important;

@ -397,7 +397,7 @@ export default {
left: 0; left: 0;
} }
.edit-address-edit-box >>> .van-field__label.edit-box-cell { .edit-address-edit-box :deep() .van-field__label.edit-box-cell {
width: 75px; width: 75px;
} }
@ -413,7 +413,7 @@ export default {
display: inline-block; display: inline-block;
} }
.edit-box-checkbox-item >>> .van-checkbox__label { .edit-box-checkbox-item :deep() .van-checkbox__label {
margin-top: 2px; margin-top: 2px;
} }

@ -4,6 +4,7 @@ import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import pinia from './store' import pinia from './store'
import { useAppStore } from './store/app.js'
import Vant from 'vant' import Vant from 'vant'
import 'vant/lib/index.css' import 'vant/lib/index.css'
import Vue3Lazyload from 'vue3-lazyload' import Vue3Lazyload from 'vue3-lazyload'
@ -69,4 +70,18 @@ app.config.globalProperties.$post = Post
app.config.globalProperties.$xss = (val) => xss(val) app.config.globalProperties.$xss = (val) => xss(val)
app.config.globalProperties.$getImageUrl = (key) => imageService.getImageByKey(key) app.config.globalProperties.$getImageUrl = (key) => imageService.getImageByKey(key)
// Vue2 遗留全局量:关爱版标识、不展示环信留言的渠道
Object.defineProperty(app.config.globalProperties, '$elder', {
enumerable: true,
configurable: true,
get() {
try {
return !!useAppStore().elder
} catch (e) {
return false
}
},
})
app.config.globalProperties.$nohxmessage = []
app.mount('#app') app.mount('#app')

@ -1,5 +1,5 @@
import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { defineStore } from 'pinia'
import { fetchPost, upLoadImgHttp } from '@/utils/https' import { fetchPost, upLoadImgHttp } from '@/utils/https'
import wsConnection from '@/utils/socket' import wsConnection from '@/utils/socket'

@ -382,10 +382,46 @@ export function Encrypt(Okey, Oiv, payload) {
} }
export function Decryption(Okey, Oiv, value) { export function Decryption(Okey, Oiv, value) {
if (value === undefined || value === null || value === '') return ''
if (typeof value !== 'string' && typeof value !== 'number') return ''
const key = CryptoJS.enc.Utf8.parse(Okey); const key = CryptoJS.enc.Utf8.parse(Okey);
const iv = CryptoJS.enc.Utf8.parse(Oiv); const iv = CryptoJS.enc.Utf8.parse(Oiv);
const decrypt = CryptoJS.AES.decrypt(value, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); const normalized = String(value).replace(/\s+/g, '')
return CryptoJS.enc.Utf8.stringify(decrypt); const options = { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
// 1) 历史 Hex 密文
if (/^[0-9A-Fa-f]+$/.test(normalized) && normalized.length % 32 === 0) {
const hexDecrypt = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Hex.parse(normalized) },
key,
options,
)
const hexText = CryptoJS.enc.Utf8.stringify(hexDecrypt)
if (hexText) return hexText
}
// 2) 兼容原 OpenSSL/Base64 字符串解密(ASR 等存量逻辑)
const opensslDecrypt = CryptoJS.AES.decrypt(normalized, key, options)
const opensslText = CryptoJS.enc.Utf8.stringify(opensslDecrypt)
if (opensslText) return opensslText
// 3) 显式按裸 Base64 ciphertext 再试(与 Encrypt 输出对齐)
const rawDecrypt = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Base64.parse(normalized) },
key,
options,
)
return CryptoJS.enc.Utf8.stringify(rawDecrypt)
}
export function decryptByVersionNo1(versionNo1Cipher, cipherText) {
if (!versionNo1Cipher || !cipherText) return ''
const year = new Date().getFullYear()
const versionNo1 = DecryptionECB(`${year}${year}${year}${year}`, versionNo1Cipher)
const key = versionNo1.substring(0, 16)
const iv = versionNo1.substring(16, 32)
if (key.length !== 16 || iv.length !== 16) return ''
return Decryption(key, iv, cipherText)
} }
export function DecryptionECB(keyECB, valueECB) { export function DecryptionECB(keyECB, valueECB) {

@ -104,40 +104,40 @@ onMounted(async () => {
setComplaint(urlParams.value.complaint || ""); //扩展参数 setComplaint(urlParams.value.complaint || ""); //扩展参数
setNavigationCorpus(urlParams.value.navigationCorpus || ""); //扩展参数 setNavigationCorpus(urlParams.value.navigationCorpus || ""); //扩展参数
wx.miniProgram.getEnv((res) => { wx.miniProgram.getEnv((res) => {
console.log(res,'res'); console.log(res, 'res');
}) })
// 渠道校验 // 渠道校验
let checkToast = null // let checkToast = null
try { // try {
checkToast = showLoadingToast({ // checkToast = showLoadingToast({
message: '加载中...', // message: '加载中...',
duration: 0, // duration: 0,
loadingType: 'spinner', // loadingType: 'spinner',
forbidClick: true, // forbidClick: true,
}) // })
const checkRes = await Post('config/downSource', { // const checkRes = await Post('config/downSource', {
source: urlParams.value.ht || '95810000', // source: urlParams.value.ht || '95810000',
}) // })
checkToast.close() // checkToast.close()
if (checkRes.code === 0 && checkRes.data !== null) { // if (checkRes.code === 0 && checkRes.data !== null) {
showDialog({ // showDialog({
title: '提示', // title: '提示',
message: checkRes.data.toast, // message: checkRes.data.toast,
confirmButtonText: '确定', // confirmButtonText: '确定',
}).then((res) => { // }).then((res) => {
Utils.closeWindow() // Utils.closeWindow()
}) // })
return // return
} // }
} catch (error) { // } catch (error) {
console.log('渠道校验异常:', error) // console.log('渠道校验异常:', error)
if (checkToast) { // if (checkToast) {
checkToast.close(); // checkToast.close();
} // }
} // }
urlParams.value = Utils.getUrlParams() urlParams.value = Utils.getUrlParams()
await initToken() initToken()
}) })
// 方法 // 方法
@ -210,6 +210,9 @@ const initToken = async () => {
if (store.hotUser) { if (store.hotUser) {
getHotUserData() getHotUserData()
} }
//保存分支机构
const branchCompany = res.data.branchCompany || '';
store.setBranchCompany(branchCompany);
// 微信鉴权异步执行,不阻塞 token 初始化主流程。 // 微信鉴权异步执行,不阻塞 token 初始化主流程。
if (((Utils.isWeiXin() && !Utils.isMiniProgram()) || isDev()) && nextUserInfo.versionNo1) { if (((Utils.isWeiXin() && !Utils.isMiniProgram()) || isDev()) && nextUserInfo.versionNo1) {
@ -217,20 +220,25 @@ const initToken = async () => {
console.warn('微信鉴权异步执行失败:', error) console.warn('微信鉴权异步执行失败:', error)
}) })
} }
// 获取 ASR 配置(elderlyData 必须是可解密的字符串)
try { try {
if (isElder && data.elderlyData && nextUserInfo.versionNo1) { const elderlyData = data.elderlyData
if (isElder && typeof elderlyData === 'string' && elderlyData && nextUserInfo.versionNo1) {
const year = new Date().getFullYear() const year = new Date().getFullYear()
const versionNo = DecryptionECB( const versionNo = DecryptionECB(
`${year}${year}${year}${year}`, `${year}${year}${year}${year}`,
nextUserInfo.versionNo1, nextUserInfo.versionNo1,
) )
const decrypted = Decryption( const key = versionNo.substring(0, 16)
versionNo.substring(0, 16), const iv = versionNo.substring(16, 32)
versionNo.substring(16, 32), if (key.length === 16 && iv.length === 16) {
data.elderlyData, const decrypted = Decryption(key, iv, elderlyData)
) const deAsrConfig = decrypted.length >= 2 ? decrypted.slice(1, -1) : decrypted
store.asrConfig = JSON.parse(decrypted.slice(1, -1)) console.log('deAsrConfig', deAsrConfig)
if (deAsrConfig) {
store.setAsrConfig(JSON.parse(deAsrConfig))
}
}
} }
} catch (error) { } catch (error) {
console.warn('获取 ASR 配置失败:', error) console.warn('获取 ASR 配置失败:', error)
@ -386,8 +394,7 @@ const getToken = async () => {
bpErrorCode: urlParams.value.bErrorCode || urlParams.value.brErrorCode || '', bpErrorCode: urlParams.value.bErrorCode || urlParams.value.brErrorCode || '',
bpErrorContent: bpErrorContent:
urlParams.value.bErrorContent || urlParams.value.bErrorContent ||
`${urlParams.value.policyNo ? urlParams.value.policyNo + '#' : ''}${ `${urlParams.value.policyNo ? urlParams.value.policyNo + '#' : ''}${urlParams.value.errorMsg ? urlParams.value.errorMsg : ''
urlParams.value.errorMsg ? urlParams.value.errorMsg : ''
}` || }` ||
'', '',
bpErrorModule: urlParams.value.bErrorModule || '', // 电子回访断点服务 bpErrorModule: urlParams.value.bErrorModule || '', // 电子回访断点服务
@ -425,7 +432,7 @@ const initBxSDK = () => {
// deb: "false", // deb: "false",
// }) // })
} }
// 异步微信鉴权方法 // 异步微信鉴权方法
const initWxAuth = async (versionNo1) => { const initWxAuth = async (versionNo1) => {
try { try {
// 异步获取微信配置参数 // 异步获取微信配置参数
@ -476,8 +483,8 @@ const initWxAuth = async (versionNo1) => {
} }
} }
// 获取微信鉴权配置参数 // 获取微信鉴权配置参数
const getWxAuthConfig = async (versionNo1) => { const getWxAuthConfig = async (versionNo1) => {
const v1 = versionNo1 const v1 = versionNo1
try { try {
const url = encodeURIComponent(window.location.href.split('#')[0]) const url = encodeURIComponent(window.location.href.split('#')[0])
@ -552,7 +559,7 @@ const loadSdk = () => {
}) })
} }
//获取高温用户弹窗数据 //获取高温用户弹窗数据
const getHotUserData = () => { const getHotUserData = () => {
Get("product/tip/select") Get("product/tip/select")
.then((res) => { .then((res) => {
if (res.code === 0 && res.data) { if (res.code === 0 && res.data) {
@ -592,7 +599,4 @@ const getHotUserData = () => {
} }
</script> </script>
<style scoped> <style scoped></style>
</style>

Loading…
Cancel
Save