From d7fbf72df4c3f03d3cffdf5f920c988b1b7d56e2 Mon Sep 17 00:00:00 2001 From: dzc <2388224167@qq.com> Date: Wed, 27 May 2026 15:19:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=B0=8F=E7=A8=8B=E5=BA=8F=E6=96=B0?= =?UTF-8?q?=E7=9A=84=E6=8C=87=E7=BA=B9=E5=94=AF=E4=B8=80=E7=BC=96=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/tabbar/my.vue | 2 +- src/sheep/api/user.ts | 4 +- .../crud/crud-layout/crud-layout.vue | 3 ++ .../components/verify-device-imp-model.vue | 3 ++ src/sheep/utils/device-unique.ts | 38 ++++++++++++++++++ src/static/icon/act_cancel.png | Bin 0 -> 5393 bytes src/static/icon/act_coupon.png | Bin 0 -> 6456 bytes 7 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 src/sheep/utils/device-unique.ts create mode 100644 src/static/icon/act_cancel.png create mode 100644 src/static/icon/act_coupon.png diff --git a/src/pages/tabbar/my.vue b/src/pages/tabbar/my.vue index 77bc48c..fa36e0b 100644 --- a/src/pages/tabbar/my.vue +++ b/src/pages/tabbar/my.vue @@ -101,7 +101,7 @@ const state = reactive({ { text: "我参加的活动", icon: "/static/icon/act.png", path: "/pages/merchant/my-act-list" }, { text: "我的钱包", icon: "/static/icon/service_3.png", path: "/pages/wallet/list" }, { text: "我的人脸", icon: "/static/icon/service_5.png", path: "/pages/human-face/list" }, - { text: "车辆管理", icon: "/static/icon/service_6.png", path: "/pages/car/user-car/list" }, + // { text: "车辆管理", icon: "/static/icon/service_6.png", path: "/pages/car/user-car/list" }, { text: "清除缓存", icon: "/static/icon/clear-storage.png", path: "" }, ], appInfo: "", diff --git a/src/sheep/api/user.ts b/src/sheep/api/user.ts index d108239..f0d14de 100644 --- a/src/sheep/api/user.ts +++ b/src/sheep/api/user.ts @@ -112,7 +112,7 @@ export default { }), // 设备认证 - verifyDevice: (data: { mobilePhone: string; code: string, uniqueCode?: string, deviceJson?: string }) => + verifyDevice: (data: { mobilePhone: string; code: string, deviceUniqueCode?: string }) => request({ url: "/thirdparty/thirdPartyOAth2/mini-app/verify-device", method: "POST", @@ -120,7 +120,7 @@ export default { }), // 判断该设备是否被验证 - isVerifyDevice: (data: { mobile: string; userId: string, uniqueCode?: string, deviceJson?: string }) => + isVerifyDevice: (data: { mobile: string; userId: string, uniqueCode?: string, deviceUniqueCode?: string }) => request({ url: "/thirdparty/thirdPartyOAth2/is-verify-device", method: "POST", diff --git a/src/sheep/components/crud/crud-layout/crud-layout.vue b/src/sheep/components/crud/crud-layout/crud-layout.vue index 5588aa8..d756303 100644 --- a/src/sheep/components/crud/crud-layout/crud-layout.vue +++ b/src/sheep/components/crud/crud-layout/crud-layout.vue @@ -5,6 +5,7 @@ import { router, hooks, constant } from "@@/index" import { useTabbarStore } from "@@/stores/tabbar" import { jump } from "@/sheep/router"; import { userApi } from "@@/api/index" +import { buildUserDeviceFingerprint } from "@@/utils/device-unique" import VerifyDeviceImpModel from "../../verify-device-imp-model.vue" @@ -133,9 +134,11 @@ async function checkVerifyDevice() { if (constant.DEVICE_VERIFY_WRITE_LIST.includes(userInfo.sysUser.phone)) { return } + const fingerprint = await buildUserDeviceFingerprint(true) const _params = { mobile: userInfo.sysUser.phone, userId: userInfo.sysUser.userId, + deviceUniqueCode: fingerprint?.fingerprint, } try { const { data, code }: any = await userApi.isVerifyDevice(_params) diff --git a/src/sheep/components/verify-device-imp-model.vue b/src/sheep/components/verify-device-imp-model.vue index 6976ba4..679d44c 100644 --- a/src/sheep/components/verify-device-imp-model.vue +++ b/src/sheep/components/verify-device-imp-model.vue @@ -31,6 +31,7 @@ import { ref, reactive, watch, onUnmounted } from "vue" import { constant } from "@@/index" import { userApi } from "@@/api" import { getMiniUniqueCode, getDeviceKey } from "@@/utils/mini-tool" +import { buildUserDeviceFingerprint } from "@@/utils/device-unique" const props = withDefaults( defineProps<{ @@ -109,9 +110,11 @@ const doSubmit = async () => { if (!isPass) return uni.showLoading({ title: "验证中...", mask: true }) + const fingerprint = await buildUserDeviceFingerprint(false) const params = { mobilePhone: form.mobilePhone, code: form.code, + deviceUniqueCode: fingerprint?.fingerprint, } const res: any = await userApi.verifyDevice(params) if (res.code != 0) { diff --git a/src/sheep/utils/device-unique.ts b/src/sheep/utils/device-unique.ts new file mode 100644 index 0000000..3114b41 --- /dev/null +++ b/src/sheep/utils/device-unique.ts @@ -0,0 +1,38 @@ +import CryptoJS from "crypto-js" +import { constant } from "@@/index" + +const INSTALL_ID_KEY = "DEVICE_INSTALL_ID" + +export async function buildUserDeviceFingerprint(force?: boolean) { + if (!force) { + const cacheResult = uni.getStorageSync(INSTALL_ID_KEY) + if (cacheResult) { + return cacheResult + } + } + const userInfo = uni.getStorageSync(constant.storageConstant.USERINFO) + const systemInfo = await uni.getSystemInfo() + const payload = { + userId: userInfo.sysUser.userId || "", + uniPlatform: systemInfo.uniPlatform || "", + hostName: systemInfo.hostName || "", + osName: systemInfo.osName || "", + osVersion: systemInfo.osVersion || "", + deviceModel: systemInfo.deviceModel || systemInfo.model || "", + deviceType: systemInfo.deviceType || "", + devicePixelRatio: String(systemInfo.devicePixelRatio || ""), + pixelRatio: String(systemInfo.pixelRatio || ""), + screenWidth: String(systemInfo.screenWidth || ""), + screenHeight: String(systemInfo.screenHeight || ""), + windowWidth: String(systemInfo.windowWidth || ""), + windowHeight: String(systemInfo.windowHeight || ""), + } + const raw = JSON.stringify(payload) + const fingerprint = CryptoJS.MD5(raw).toString() + const result = { + fingerprint, + payload, + } + uni.setStorageSync(INSTALL_ID_KEY, result) + return result +} diff --git a/src/static/icon/act_cancel.png b/src/static/icon/act_cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..56792bb8c17379ad27ca54e8ad980c144506746f GIT binary patch literal 5393 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 literal 0 HcmV?d00001 diff --git a/src/static/icon/act_coupon.png b/src/static/icon/act_coupon.png new file mode 100644 index 0000000000000000000000000000000000000000..47da934e01373254052c909cc38fd67015fd20ec GIT binary patch literal 6456 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 literal 0 HcmV?d00001