f
This commit is contained in:
95
src/composables/useApiFetch.js
Normal file
95
src/composables/useApiFetch.js
Normal file
@@ -0,0 +1,95 @@
|
||||
// src/plugins/fetch.js
|
||||
import { createFetch } from "@vueuse/core";
|
||||
import router from "@/router"; // 假设你使用 Vue Router
|
||||
import { useUserStore } from "@/stores/userStore";
|
||||
import { useAgentStore } from "@/stores/agentStore";
|
||||
// 创建全局的 fetch 实例
|
||||
const useApiFetch = createFetch({
|
||||
baseUrl: "/api/v1", // 你的 API 基础路径
|
||||
options: {
|
||||
async beforeFetch({ url, options }) {
|
||||
showLoadingToast({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
duration: 0, // 设置为 0 表示不会自动关闭
|
||||
loadingType: "spinner",
|
||||
});
|
||||
|
||||
const timestamp = Date.now();
|
||||
const separator = url.includes("?") ? "&" : "?"; // 判断是否已有参数
|
||||
url += `${separator}t=${timestamp}`; // 追加时间戳
|
||||
|
||||
// 在请求前添加通用的 Header,例如 Authorization
|
||||
const token = localStorage.getItem("token");
|
||||
let platform = "h5";
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
const isWechat = /micromessenger/.test(userAgent);
|
||||
if (isWechat) {
|
||||
platform = "wxh5";
|
||||
}
|
||||
options.headers['X-Platform'] = platform
|
||||
|
||||
if (token) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
Authorization: `${token}`,
|
||||
};
|
||||
}
|
||||
return { url, options };
|
||||
},
|
||||
async afterFetch({ data, response }) {
|
||||
closeToast();
|
||||
// 全局处理响应
|
||||
if (response.status === 401) {
|
||||
// 清除本地存储的 token
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem('refreshAfter')
|
||||
localStorage.removeItem('accessExpire')
|
||||
// 跳转到登录页
|
||||
router.replace("/login");
|
||||
}
|
||||
|
||||
if (data.code !== 200) {
|
||||
if (data.code === 100009) {
|
||||
// 改进的存储管理
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('refreshAfter')
|
||||
localStorage.removeItem('accessExpire')
|
||||
localStorage.removeItem('userInfo')
|
||||
localStorage.removeItem('agentInfo')
|
||||
|
||||
// 重置状态
|
||||
const userStore = useUserStore();
|
||||
const agentStore = useAgentStore();
|
||||
userStore.resetUser()
|
||||
agentStore.resetAgent()
|
||||
location.reload()
|
||||
|
||||
}
|
||||
if (data.code !== 200002 && data.code !== 200003 && data.code !== 200004 && data.code !== 100009) {
|
||||
showToast({ message: data.msg });
|
||||
}
|
||||
}
|
||||
return { data, response };
|
||||
},
|
||||
async onFetchError({ error, response }) {
|
||||
console.log("error", error);
|
||||
closeToast();
|
||||
if (response.status === 401) {
|
||||
// 清除本地存储的 token
|
||||
localStorage.removeItem("token");
|
||||
localStorage.removeItem('refreshAfter')
|
||||
localStorage.removeItem('accessExpire')
|
||||
// 跳转到登录页
|
||||
router.replace("/login");
|
||||
} else {
|
||||
if (typeof error === "string") {
|
||||
showToast({ message: error });
|
||||
}
|
||||
}
|
||||
return { error };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default useApiFetch;
|
||||
16
src/composables/useEnv.js
Normal file
16
src/composables/useEnv.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// src/composables/useEnv.js
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
// 创建一个全局的 ref
|
||||
const isWeChat = ref(false)
|
||||
|
||||
// 立即执行检测
|
||||
const userAgent = navigator.userAgent.toLowerCase()
|
||||
const keywords = ['micromessenger', 'wechat'].map(key => key.toLowerCase())
|
||||
isWeChat.value = keywords.some(keyword => userAgent.includes(keyword))
|
||||
|
||||
export function useEnv() {
|
||||
return {
|
||||
isWeChat,
|
||||
}
|
||||
}
|
||||
27
src/composables/useHttp.js
Normal file
27
src/composables/useHttp.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import { useFetch, createFetch } from '@vueuse/core';
|
||||
|
||||
export function useHttp(url, options = {}, token) {
|
||||
const fetch = createFetch(url, {
|
||||
baseUrl: '/api/v1',
|
||||
options: {
|
||||
async beforeFetch({ url, options, cancel }) {
|
||||
console.log("asdasd", options)
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
Authorization: `${token}`,
|
||||
}
|
||||
return {
|
||||
options,
|
||||
}
|
||||
},
|
||||
async afterFetch(ctx) {
|
||||
console.log("ctx", ctx)
|
||||
// if (ctx.data.code !== 200) {
|
||||
// throw new Error(ctx.data.message || '请求失败');
|
||||
// }
|
||||
return ctx;
|
||||
},
|
||||
}
|
||||
})
|
||||
return fetch(url)
|
||||
}
|
||||
18
src/composables/useRiskNotifier.js
Normal file
18
src/composables/useRiskNotifier.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { watch } from "vue";
|
||||
|
||||
/**
|
||||
* 风险评分通知 composable
|
||||
* 用于组件向父组件通知自己的风险评分(0-100分,分数越高越安全)
|
||||
*/
|
||||
export function useRiskNotifier(props, riskScore) {
|
||||
// 监听 riskScore 变化,通知父组件
|
||||
watch(
|
||||
riskScore,
|
||||
(newValue) => {
|
||||
if (props.apiId && props.notifyRiskStatus) {
|
||||
props.notifyRiskStatus(props.apiId, props.index, newValue);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
}
|
||||
212
src/composables/useSEO.js
Normal file
212
src/composables/useSEO.js
Normal file
@@ -0,0 +1,212 @@
|
||||
import { ref, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
export function useSEO() {
|
||||
const route = useRoute();
|
||||
|
||||
// 默认SEO信息
|
||||
const defaultSEO = {
|
||||
title:
|
||||
"天远助手|大数据风险报告查询与代理平台,支持个人和企业多场景风控应用",
|
||||
description:
|
||||
"天远助手,专业大数据风险报告查询与代理平台,支持个人信用查询、小微企业风控、贷前风险背调等多场景报告应用,免费开通代理权限,助力高效识别信用与风险。",
|
||||
keywords:
|
||||
"大数据风险报告查询、大数据风险评估、大数据分析报告、个人大数据风险查询、小微企业风险、贷前风险背调、代理管理平台、免费开通代理、风险管控平台、信用风险分析、企业风险报告、贷前信用审核、失信人名单查询、被执行人信息、信用黑名单查询",
|
||||
url: "https://www.zhinengcha.cn",
|
||||
};
|
||||
|
||||
// 页面SEO配置
|
||||
const pageSEO = ref({
|
||||
title: "",
|
||||
description: "",
|
||||
keywords: "",
|
||||
url: "",
|
||||
});
|
||||
|
||||
// 更新页面SEO信息
|
||||
const updateSEO = (seoConfig) => {
|
||||
const config = { ...defaultSEO, ...seoConfig };
|
||||
|
||||
// 更新页面标题
|
||||
document.title = config.title;
|
||||
|
||||
// 更新meta描述
|
||||
let metaDescription = document.querySelector('meta[name="description"]');
|
||||
if (!metaDescription) {
|
||||
metaDescription = document.createElement("meta");
|
||||
metaDescription.name = "description";
|
||||
document.head.appendChild(metaDescription);
|
||||
}
|
||||
metaDescription.content = config.description;
|
||||
|
||||
// 更新meta关键词
|
||||
let metaKeywords = document.querySelector('meta[name="keywords"]');
|
||||
if (!metaKeywords) {
|
||||
metaKeywords = document.createElement("meta");
|
||||
metaKeywords.name = "keywords";
|
||||
document.head.appendChild(metaKeywords);
|
||||
}
|
||||
metaKeywords.content = config.keywords;
|
||||
|
||||
// 更新Open Graph标签
|
||||
updateOpenGraph(config);
|
||||
|
||||
// 更新Twitter Cards
|
||||
updateTwitterCards(config);
|
||||
|
||||
// 更新canonical URL
|
||||
updateCanonicalURL(config.url);
|
||||
|
||||
// 更新结构化数据
|
||||
updateStructuredData(config);
|
||||
};
|
||||
|
||||
// 更新Open Graph标签
|
||||
const updateOpenGraph = (config) => {
|
||||
const ogTags = {
|
||||
"og:title": config.title,
|
||||
"og:description": config.description,
|
||||
"og:url": config.url,
|
||||
"og:type": "website",
|
||||
"og:site_name": "天远助手",
|
||||
"og:locale": "zh_CN",
|
||||
};
|
||||
|
||||
Object.entries(ogTags).forEach(([property, content]) => {
|
||||
let meta = document.querySelector(`meta[property="${property}"]`);
|
||||
if (!meta) {
|
||||
meta = document.createElement("meta");
|
||||
meta.setAttribute("property", property);
|
||||
document.head.appendChild(meta);
|
||||
}
|
||||
meta.content = content;
|
||||
});
|
||||
};
|
||||
|
||||
// 更新Twitter Cards
|
||||
const updateTwitterCards = (config) => {
|
||||
const twitterTags = {
|
||||
"twitter:card": "summary",
|
||||
"twitter:title": config.title,
|
||||
"twitter:description": config.description,
|
||||
"twitter:url": config.url,
|
||||
};
|
||||
|
||||
Object.entries(twitterTags).forEach(([name, content]) => {
|
||||
let meta = document.querySelector(`meta[name="${name}"]`);
|
||||
if (!meta) {
|
||||
meta = document.createElement("meta");
|
||||
meta.name = name;
|
||||
document.head.appendChild(meta);
|
||||
}
|
||||
meta.content = content;
|
||||
});
|
||||
};
|
||||
|
||||
// 更新canonical URL
|
||||
const updateCanonicalURL = (url) => {
|
||||
let canonical = document.querySelector('link[rel="canonical"]');
|
||||
if (!canonical) {
|
||||
canonical = document.createElement("link");
|
||||
canonical.rel = "canonical";
|
||||
document.head.appendChild(canonical);
|
||||
}
|
||||
canonical.href = url;
|
||||
};
|
||||
|
||||
// 更新结构化数据
|
||||
const updateStructuredData = (config) => {
|
||||
// 移除现有的结构化数据
|
||||
const existingScripts = document.querySelectorAll(
|
||||
'script[type="application/ld+json"]',
|
||||
);
|
||||
existingScripts.forEach((script) => {
|
||||
if (script.textContent.includes('"@type":"WebPage"')) {
|
||||
script.remove();
|
||||
}
|
||||
});
|
||||
|
||||
// 添加新的结构化数据
|
||||
const structuredData = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebPage",
|
||||
name: config.title,
|
||||
description: config.description,
|
||||
url: config.url,
|
||||
mainEntity: {
|
||||
"@type": "Organization",
|
||||
name: "天远助手",
|
||||
url: "https://www.zhinengcha.cn/",
|
||||
description:
|
||||
"专业大数据风险报告查询与代理平台,支持个人和企业多场景风控应用",
|
||||
},
|
||||
};
|
||||
|
||||
const script = document.createElement("script");
|
||||
script.type = "application/ld+json";
|
||||
script.textContent = JSON.stringify(structuredData);
|
||||
document.head.appendChild(script);
|
||||
};
|
||||
|
||||
// 根据路由自动更新SEO
|
||||
const updateSEOByRoute = () => {
|
||||
const routeConfigs = {
|
||||
"/": {
|
||||
title:
|
||||
"天远助手|大数据风险报告查询与代理平台,支持个人和企业多场景风控应用",
|
||||
description:
|
||||
"天远助手,专业大数据风险报告查询与代理平台,支持个人信用查询、小微企业风控、贷前风险背调等多场景报告应用,免费开通代理权限,助力高效识别信用与风险。",
|
||||
keywords:
|
||||
"大数据风险报告查询、大数据风险评估、大数据分析报告、个人大数据风险查询、小微企业风险、贷前风险背调、代理管理平台、免费开通代理、风险管控平台、信用风险分析、企业风险报告、贷前信用审核、失信人名单查询、被执行人信息、信用黑名单查询",
|
||||
},
|
||||
"/agent": {
|
||||
title: "天远助手代理 - 免费开通代理权限 | 大数据风险报告代理",
|
||||
description:
|
||||
"天远助手代理平台,免费开通代理权限,享受大数据风险报告查询服务代理收益。专业的大数据风险报告、婚姻查询、个人信用评估等服务的代理合作。",
|
||||
keywords:
|
||||
"天远助手代理, 免费代理, 大数据风险报告代理, 代理权限, 代理收益",
|
||||
},
|
||||
"/help": {
|
||||
title: "帮助中心 - 天远助手使用指南 | 常见问题解答",
|
||||
description:
|
||||
"天远助手帮助中心,提供详细的使用指南、常见问题解答、操作教程等,帮助用户更好地使用大数据风险报告查询服务。",
|
||||
keywords: "天远助手帮助, 使用指南, 常见问题, 操作教程, 客服支持",
|
||||
},
|
||||
"/help/guide": {
|
||||
title: "使用指南 - 天远助手操作教程 | 功能说明",
|
||||
description:
|
||||
"天远助手详细使用指南,包含各功能模块的操作教程、功能说明、注意事项等,让用户快速上手使用。",
|
||||
keywords: "使用指南, 操作教程, 功能说明, 快速上手, 天远助手教程",
|
||||
},
|
||||
"/example": {
|
||||
title: "示例报告 - 天远助手报告展示 | 大数据风险报告样例",
|
||||
description:
|
||||
"天远助手示例报告展示,包含大数据风险报告、婚姻状况查询、个人信用评估等服务的报告样例,让用户了解报告内容和格式。",
|
||||
keywords: "示例报告, 报告展示, 报告样例, 大数据风险报告, 婚姻查询报告",
|
||||
},
|
||||
"/service": {
|
||||
title: "客服中心 - 天远助手在线客服 | 技术支持",
|
||||
description:
|
||||
"天远助手客服中心,提供在线客服支持、技术咨询、问题反馈等服务,确保用户获得及时有效的帮助。",
|
||||
keywords: "客服中心, 在线客服, 技术支持, 问题反馈, 天远助手客服",
|
||||
},
|
||||
};
|
||||
|
||||
const currentPath = route?.path || "/";
|
||||
const config = routeConfigs[currentPath] || defaultSEO;
|
||||
|
||||
updateSEO({
|
||||
...config,
|
||||
url: `https://www.zhinengcha.cn${currentPath}`,
|
||||
});
|
||||
};
|
||||
|
||||
// 监听路由变化
|
||||
watch(() => route?.path, updateSEOByRoute, { immediate: true });
|
||||
|
||||
return {
|
||||
updateSEO,
|
||||
updateSEOByRoute,
|
||||
pageSEO,
|
||||
};
|
||||
}
|
||||
130
src/composables/useWebView.js
Normal file
130
src/composables/useWebView.js
Normal file
@@ -0,0 +1,130 @@
|
||||
import { ref, onMounted } from "vue";
|
||||
import "@/assets/uni-webview"
|
||||
|
||||
export function useWebView() {
|
||||
const platform = ref("");
|
||||
const token = ref("");
|
||||
// 检测环境并通知父窗口加载完毕
|
||||
const handleBridgeReady = () => {
|
||||
if (platform.value) {
|
||||
h5PostMessage("loaded", true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 获取 Token(从 URL 中解析)
|
||||
const getTokenFromUrl = () => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const tokenFromUrl = urlParams.get("token");
|
||||
token.value = tokenFromUrl || ""; // 如果 URL 没有 token,返回空字符串
|
||||
if (token.value) {
|
||||
localStorage.setItem("token", token.value);
|
||||
}
|
||||
return tokenFromUrl;
|
||||
};
|
||||
|
||||
// 封装 postMessage 方法
|
||||
const postMessage = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
h5PostMessage("postMessage", data);
|
||||
} else if (uni && uni.webView.postMessage) {
|
||||
uni.webView.postMessage(data);
|
||||
} else {
|
||||
console.error("uni.webView.postMessage is not available.");
|
||||
}
|
||||
};
|
||||
|
||||
const redirectTo = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
h5PostMessage("redirectTo", data)
|
||||
} else if (uni && uni.webView.redirectTo) {
|
||||
// 非 H5 环境,调用 uni.webView.redirectTo
|
||||
uni.webView.redirectTo(data);
|
||||
} else {
|
||||
console.error("uni.webView.redirectTo is not available.");
|
||||
}
|
||||
};
|
||||
|
||||
// 封装 navigateBack 方法
|
||||
const navigateBack = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
window.top.history.back();
|
||||
// h5PostMessage("navigateBack", data)
|
||||
} else if (uni && uni.webView.navigateBack) {
|
||||
// 非 H5 环境,调用 uni.webView.navigateBack
|
||||
uni.webView.navigateBack(data);
|
||||
} else {
|
||||
console.error("uni.webView.navigateBack is not available.");
|
||||
}
|
||||
};
|
||||
|
||||
// 封装 navigateTo 方法
|
||||
const navigateTo = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
// h5PostMessage("navigateTo", data)
|
||||
window.top.location.href = "/app" + data.url
|
||||
} else if (uni && uni.webView.navigateTo) {
|
||||
uni.webView.navigateTo(data);
|
||||
} else {
|
||||
console.error("uni.webView.navigateTo is not available.");
|
||||
}
|
||||
};
|
||||
const payment = (data) => {
|
||||
if (platform.value === "h5") {
|
||||
h5PostMessage("payment", data)
|
||||
} else if (uni && uni.webView.navigateTo) {
|
||||
// 非 H5 环境,调用 uni.webView.navigateTo
|
||||
uni.webView.navigateTo(data);
|
||||
} else {
|
||||
console.error("uni.webView.navigateTo is not available.");
|
||||
}
|
||||
}
|
||||
const getEnv = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let env = localStorage.getItem(platform)
|
||||
if (env) {
|
||||
platform.value = env
|
||||
resolve(env);
|
||||
} else {
|
||||
uni.webView.getEnv((env) => {
|
||||
// 遍历 env 对象,找到值为 true 的键
|
||||
const platformKey = Object.keys(env).find(key => env[key] === true);
|
||||
platform.value = platformKey;
|
||||
if (platformKey) {
|
||||
resolve(platformKey); // 返回键名(如 'h5', 'mp-weixin' 等)
|
||||
} else {
|
||||
reject('未知平台');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const envValue = await getEnv();
|
||||
console.log("当前环境", envValue)
|
||||
// 将返回的键名(如 'h5', 'mp-weixin')存储到 platform
|
||||
handleBridgeReady();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
// 获取 Token
|
||||
getTokenFromUrl();
|
||||
});
|
||||
|
||||
return {
|
||||
platform,
|
||||
token,
|
||||
getEnv,
|
||||
redirectTo,
|
||||
postMessage,
|
||||
navigateTo,
|
||||
navigateBack,
|
||||
payment
|
||||
};
|
||||
}
|
||||
const h5PostMessage = (action, data) => {
|
||||
window.parent.postMessage({ action, data, messageId: generateUniqueId(action) }, "*");
|
||||
}
|
||||
const generateUniqueId = (action) => `msg_${action}_${new Date().getTime()}`;
|
||||
236
src/composables/useWeixinShare.js
Normal file
236
src/composables/useWeixinShare.js
Normal file
@@ -0,0 +1,236 @@
|
||||
import { ref } from "vue";
|
||||
import { useEnv } from "./useEnv";
|
||||
|
||||
export function useWeixinShare() {
|
||||
const { isWeChat } = useEnv();
|
||||
const wxConfigReady = ref(false);
|
||||
const signMap = new Map(); // 存储各个链接的签名信息
|
||||
|
||||
/**
|
||||
* 从后端获取签名信息
|
||||
* @param {string} url - 需要签名的URL
|
||||
* @returns {Promise} 签名信息
|
||||
*/
|
||||
const getWxSignature = async (url) => {
|
||||
try {
|
||||
const { data, error } = await useApiFetch("/wechat/getSignature")
|
||||
.post({ url })
|
||||
.json();
|
||||
|
||||
if (error.value || data.value?.code !== 200) {
|
||||
console.error("获取微信签名失败:", error.value || data.value);
|
||||
return null;
|
||||
}
|
||||
|
||||
return data.value.data;
|
||||
} catch (err) {
|
||||
console.error("获取微信签名异常:", err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 配置微信SDK
|
||||
* @param {Object} signature - 签名信息
|
||||
* @param {Object} shareConfig - 分享配置
|
||||
*/
|
||||
const wxConfigJSSDK = (signature, shareConfig) => {
|
||||
const { title, desc, link, imgUrl } = shareConfig;
|
||||
|
||||
window.jWeixin.config({
|
||||
debug: false, // 生产环境设为false,开发时可设为true查看错误
|
||||
appId: signature.appId,
|
||||
timestamp: signature.timestamp,
|
||||
nonceStr: signature.nonceStr,
|
||||
signature: signature.signature,
|
||||
jsApiList: [
|
||||
"updateAppMessageShareData",
|
||||
"updateTimelineShareData",
|
||||
"onMenuShareAppMessage",
|
||||
"onMenuShareTimeline",
|
||||
],
|
||||
});
|
||||
|
||||
window.jWeixin.ready(() => {
|
||||
console.log("微信SDK配置成功");
|
||||
|
||||
const shareData = {
|
||||
title,
|
||||
desc,
|
||||
link,
|
||||
imgUrl,
|
||||
};
|
||||
|
||||
// 新版分享接口 - 分享给朋友
|
||||
window.jWeixin.updateAppMessageShareData({
|
||||
...shareData,
|
||||
success: function (res) {
|
||||
console.log("分享给朋友配置成功", res);
|
||||
},
|
||||
fail: function (err) {
|
||||
console.error("分享给朋友配置失败", err);
|
||||
},
|
||||
});
|
||||
|
||||
// 新版分享接口 - 分享到朋友圈
|
||||
window.jWeixin.updateTimelineShareData({
|
||||
...shareData,
|
||||
success: function (res) {
|
||||
console.log("分享到朋友圈配置成功", res);
|
||||
},
|
||||
fail: function (err) {
|
||||
console.error("分享到朋友圈配置失败", err);
|
||||
},
|
||||
});
|
||||
|
||||
// 兼容旧版微信 - 分享给朋友
|
||||
window.jWeixin.onMenuShareAppMessage({
|
||||
...shareData,
|
||||
success: function (res) {
|
||||
console.log("分享给朋友成功", res);
|
||||
},
|
||||
fail: function (err) {
|
||||
console.error("分享给朋友失败", err);
|
||||
},
|
||||
cancel: function () {
|
||||
console.log("用户取消分享");
|
||||
},
|
||||
});
|
||||
|
||||
// 兼容旧版微信 - 分享到朋友圈
|
||||
window.jWeixin.onMenuShareTimeline({
|
||||
...shareData,
|
||||
success: function (res) {
|
||||
console.log("分享到朋友圈成功", res);
|
||||
},
|
||||
fail: function (err) {
|
||||
console.error("分享到朋友圈失败", err);
|
||||
},
|
||||
cancel: function () {
|
||||
console.log("用户取消分享");
|
||||
},
|
||||
});
|
||||
|
||||
wxConfigReady.value = true;
|
||||
});
|
||||
|
||||
window.jWeixin.error((res) => {
|
||||
console.error("微信SDK配置失败:", res);
|
||||
// 常见错误:
|
||||
// 1. invalid url domain - 当前域名未在公众号后台配置
|
||||
// 2. invalid signature - 签名错误
|
||||
// 3. permission denied - 没有权限使用该接口
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 配置微信分享
|
||||
* @param {Object} shareConfig - 分享配置
|
||||
* @param {string} shareConfig.title - 分享标题
|
||||
* @param {string} shareConfig.desc - 分享描述
|
||||
* @param {string} shareConfig.link - 分享链接
|
||||
* @param {string} shareConfig.imgUrl - 分享图标URL
|
||||
*/
|
||||
const configWeixinShare = async (shareConfig = {}) => {
|
||||
console.log("configWeixinShare", shareConfig);
|
||||
console.log("isWeChat", isWeChat.value);
|
||||
console.log("window.jWeixin", window.jWeixin);
|
||||
// 只在微信环境中配置
|
||||
if (!isWeChat.value || !window.jWeixin) {
|
||||
console.log("非微信环境或微信SDK未加载");
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultConfig = {
|
||||
title:
|
||||
"天远助手|大数据风险报告查询与代理平台,支持个人和企业多场景风控应用",
|
||||
desc: "提供个人信用评估、人事背调、信贷风控、企业风险监测等服务",
|
||||
link: window.location.href.split("#")[0], // 获取当前页面URL,不包括hash
|
||||
imgUrl: "https://ass.tianyuandata.com/logo.jpg",
|
||||
};
|
||||
|
||||
const config = { ...defaultConfig, ...shareConfig };
|
||||
|
||||
// 获取当前页面的完整URL(不包括hash)
|
||||
const currentUrl = window.location.href.split("#")[0];
|
||||
|
||||
// 检查是否已有该URL的签名
|
||||
if (signMap.has(currentUrl)) {
|
||||
console.log("使用缓存的签名信息");
|
||||
wxConfigJSSDK(signMap.get(currentUrl), config);
|
||||
return;
|
||||
}
|
||||
|
||||
// 从后端获取签名
|
||||
console.log("正在获取微信签名...");
|
||||
const signature = await getWxSignature(currentUrl);
|
||||
|
||||
if (!signature) {
|
||||
console.error("获取微信签名失败,无法配置分享");
|
||||
return;
|
||||
}
|
||||
|
||||
// 缓存签名信息
|
||||
signMap.set(currentUrl, signature);
|
||||
|
||||
// 配置微信SDK
|
||||
wxConfigJSSDK(signature, config);
|
||||
};
|
||||
|
||||
/**
|
||||
* 动态更新分享配置
|
||||
* @param {Object} shareConfig - 分享配置
|
||||
*/
|
||||
const updateShareConfig = (shareConfig) => {
|
||||
configWeixinShare(shareConfig);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据当前页面动态设置分享内容
|
||||
*/
|
||||
const setDynamicShare = async () => {
|
||||
const route = window.location.pathname;
|
||||
let shareConfig = {};
|
||||
|
||||
// 根据不同的路由设置不同的分享内容
|
||||
if (route.includes("/example")) {
|
||||
shareConfig = {
|
||||
title: "天远助手 - 大数据风险报告示例",
|
||||
desc: "查看完整的大数据风险报告示例,了解个人信用评估等服务",
|
||||
link: window.location.href.split("#")[0],
|
||||
imgUrl: "https://ass.tianyuandata.com/logo.jpg",
|
||||
};
|
||||
} else if (route.includes("/agent")) {
|
||||
shareConfig = {
|
||||
title: "天远助手 - 免费开通代理权限",
|
||||
desc: "免费开通代理权限,享受大数据风险报告查询服务代理收益",
|
||||
link: window.location.href.split("#")[0],
|
||||
imgUrl: "https://ass.tianyuandata.com/logo.jpg",
|
||||
};
|
||||
} else if (route.includes("/help")) {
|
||||
shareConfig = {
|
||||
title: "天远助手 - 帮助中心",
|
||||
desc: "详细的使用指南、常见问题解答、操作教程",
|
||||
link: window.location.href.split("#")[0],
|
||||
imgUrl: "https://ass.tianyuandata.com/logo.jpg",
|
||||
};
|
||||
} else {
|
||||
shareConfig = {
|
||||
title:
|
||||
"天远助手|大数据风险报告查询与代理平台,支持个人和企业多场景风控应用",
|
||||
desc: "提供个人信用评估、人事背调、信贷风控、企业风险监测等服务",
|
||||
link: window.location.href.split("#")[0],
|
||||
imgUrl: "https://ass.tianyuandata.com/logo.jpg",
|
||||
};
|
||||
}
|
||||
|
||||
await configWeixinShare(shareConfig);
|
||||
};
|
||||
|
||||
return {
|
||||
wxConfigReady,
|
||||
configWeixinShare,
|
||||
updateShareConfig,
|
||||
setDynamicShare,
|
||||
};
|
||||
}
|
||||
32
src/composables/useZoomAdapter.js
Normal file
32
src/composables/useZoomAdapter.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ref, onMounted } from 'vue';
|
||||
import zoomAdapter from '../utils/zoomAdapter.js';
|
||||
|
||||
/**
|
||||
* 简化版缩放适配组合式函数
|
||||
*/
|
||||
export function useZoomAdapter() {
|
||||
const currentZoom = ref(1);
|
||||
const isTooHighZoom = ref(false);
|
||||
|
||||
const handleZoomChange = (event) => {
|
||||
const { zoom } = event.detail;
|
||||
currentZoom.value = zoom;
|
||||
isTooHighZoom.value = zoom > 3;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (!zoomAdapter.isInitialized) {
|
||||
zoomAdapter.init();
|
||||
}
|
||||
window.addEventListener('zoomChanged', handleZoomChange);
|
||||
});
|
||||
|
||||
return {
|
||||
currentZoom,
|
||||
isTooHighZoom,
|
||||
getZoomAdaptiveClass: () => ({
|
||||
'zoom-adaptive': true,
|
||||
'too-high-zoom': isTooHighZoom.value
|
||||
})
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user