| | |
| | | uni.showLoading({ |
| | | title: '正在保存图片...' |
| | | }); |
| | | if (normalizeOptionalText(url).startsWith('data:image/')) { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: "当前图片暂不支持直接保存,请稍后重试!", |
| | | icon: 'none' |
| | | }); |
| | | return |
| | | } |
| | | uni.getSetting({ |
| | | success: async (res) => { |
| | | if (!res.authSetting["scope.writePhotosAlbum"]) { |
| | | uni.authorize({ |
| | | scope: "scope.writePhotosAlbum", |
| | | success: async () => { |
| | | const res = await uni.getImageInfo({ |
| | | src: url |
| | | }); |
| | | uni.saveImageToPhotosAlbum({ |
| | | filePath: res.path, |
| | | success: () => { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: "保存成功!" |
| | | }); |
| | | }, |
| | | fail: () => { |
| | | uni.showToast({ |
| | | title: "保存失败,请重试!", |
| | | icon: 'error' |
| | | }); |
| | | } |
| | | }); |
| | | await saveImageFile(url) |
| | | }, |
| | | fail: () => { |
| | | uni.hideLoading(); |
| | |
| | | } |
| | | }); |
| | | } else { |
| | | const res = await uni.getImageInfo({ |
| | | src: url |
| | | }); |
| | | uni.saveImageToPhotosAlbum({ |
| | | filePath: res.path, |
| | | success: () => { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: "保存成功!" |
| | | }); |
| | | }, |
| | | fail: () => { |
| | | uni.showToast({ |
| | | title: "保存失败,请重试!", |
| | | icon: 'error' |
| | | }); |
| | | } |
| | | }); |
| | | await saveImageFile(url) |
| | | } |
| | | }, |
| | | fail: () => { |
| | |
| | | }; |
| | | |
| | | /** |
| | | * 下载图片并写入系统相册。 |
| | | */ |
| | | const saveImageFile = async (url) => { |
| | | try { |
| | | const imageInfo = await uni.getImageInfo({ |
| | | src: url |
| | | }); |
| | | await uni.saveImageToPhotosAlbum({ |
| | | filePath: imageInfo.path, |
| | | }); |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: "保存成功!" |
| | | }); |
| | | } catch (error) { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: "保存失败,请重试!", |
| | | icon: 'error' |
| | | }); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 将可选文本归一化为空字符串。 |
| | | */ |
| | | export const normalizeOptionalText = (value) => { |
| | | return typeof value === 'string' ? value.trim() : '' |
| | | } |
| | | |
| | | /** |
| | | * 从 URL、纯文本或剪贴板内容中提取 6 位邀请码。 |
| | | */ |
| | | export const extractInviteCode = (value) => { |
| | | const normalizedValue = normalizeOptionalText(value) |
| | | if (!normalizedValue) { |
| | | return '' |
| | | } |
| | | const queryMatchedInviteCode = normalizedValue.match(/[?&]inviteCode=([^&#]+)/i) |
| | | if (queryMatchedInviteCode && queryMatchedInviteCode[1]) { |
| | | const decodedInviteCode = decodeURIComponent(queryMatchedInviteCode[1]).trim().toUpperCase() |
| | | return /^[A-Z0-9]{6}$/.test(decodedInviteCode) ? decodedInviteCode : '' |
| | | } |
| | | const matchedInviteCode = normalizedValue.toUpperCase().match(/[A-Z0-9]{6}/) |
| | | return matchedInviteCode ? matchedInviteCode[0] : '' |
| | | } |
| | | |
| | | const APP_INVITE_CODE_STORAGE_KEY = 'appAutoInviteCode' |
| | |
| | | * 缓存自动识别的邀请码,供注册页优先读取。 |
| | | */ |
| | | export const cacheAppInviteCode = (inviteCode) => { |
| | | const normalizedInviteCode = normalizeOptionalText(inviteCode).toUpperCase() |
| | | const normalizedInviteCode = extractInviteCode(inviteCode) |
| | | if (!/^[A-Z0-9]{6}$/.test(normalizedInviteCode)) { |
| | | return |
| | | } |
| | |
| | | * 读取并消费自动识别的邀请码。 |
| | | */ |
| | | export const consumeAppInviteCode = () => { |
| | | const inviteCode = normalizeOptionalText(uni.getStorageSync(APP_INVITE_CODE_STORAGE_KEY)).toUpperCase() |
| | | const inviteCode = extractInviteCode(uni.getStorageSync(APP_INVITE_CODE_STORAGE_KEY)) |
| | | if (!/^[A-Z0-9]{6}$/.test(inviteCode)) { |
| | | return '' |
| | | } |