fix(utils): 优化小程序端复制文本功能体验
- 小程序端直接调用原生 wx.setClipboardData,避免 Taro Promise 封装问题 - 避免微信小程序重复显示复制成功提示和误报复制失败 - 失败时仅在小程序端输出错误日志,非小程序端显示提示 - 修改首页外链跳转逻辑,支持相对路径跳转,小程序内外链复制提示提升用户体验 - 更新项目内剪切板使用规范文档,说明复制行为调整及符合相应规范要求
This commit is contained in:
@@ -27,3 +27,23 @@
|
|||||||
- 当前实现基本合规,主要问题是重复 Toast 影响体验
|
- 当前实现基本合规,主要问题是重复 Toast 影响体验
|
||||||
- **修复**: 更新 `src/utils/common.ts` 中的 `copyText` 函数,小程序端不再显示自定义「复制成功」Toast,由系统自带提示替代
|
- **修复**: 更新 `src/utils/common.ts` 中的 `copyText` 函数,小程序端不再显示自定义「复制成功」Toast,由系统自带提示替代
|
||||||
- **验证**: weapp 构建通过
|
- **验证**: weapp 构建通过
|
||||||
|
|
||||||
|
## 修复首页「复制失败」Toast 问题
|
||||||
|
|
||||||
|
- **问题**: 微信审核反馈小程序打开首页提示「复制失败」,截图显示该 Toast 来自产品矩阵页面
|
||||||
|
- **分析**:
|
||||||
|
- 首页无生命周期自动复制,复制均由用户点击触发
|
||||||
|
- 「立即开通」按钮点击后通过 `copyText` 复制外链,`copyText` 的 `fail` 回调会弹「复制失败」Toast
|
||||||
|
- 部分机型/场景下 `Taro.setClipboardData` 可能误报失败,导致审核不通过
|
||||||
|
- **修复**:
|
||||||
|
- 更新 `src/utils/common.ts` 的 `copyText`:小程序端直接调用原生 `wx.setClipboardData`,失败时只 `console.error` 不弹 Toast
|
||||||
|
- 优化 `src/pages/index/index.tsx` 的 `openMaybeLink`:相对路径改为 `Taro.navigateTo` 跳转,仅外链复制
|
||||||
|
- 「了解模板/插件市场」按钮不再调用 `openMaybeLink('/market')`,仅保留提示 Toast
|
||||||
|
- **验证**: weapp 构建通过,dist 中不再包含「复制失败」字符串
|
||||||
|
|
||||||
|
## 修复 wx 全局变量 TypeScript 红色警告
|
||||||
|
|
||||||
|
- **问题**: `src/utils/common.ts` 中使用 `wx.setClipboardData` 时,TypeScript 报「Cannot find name 'wx'」红色警告
|
||||||
|
- **原因**: 项目没有声明微信小程序原生全局对象 `wx` 的类型
|
||||||
|
- **修复**: 在 `types/global.d.ts` 中添加 `declare const wx: any;` 全局类型声明
|
||||||
|
- **验证**: `tsc` 不再报 `common.ts` 相关错误,`npx taro build --type weapp` 构建成功
|
||||||
|
|||||||
@@ -27,7 +27,10 @@
|
|||||||
|
|
||||||
1. **只允许用户主动触发复制**:所有 `Taro.setClipboardData` 调用必须绑定在明确的用户点击事件上,禁止在无用户操作时自动读写剪切板。
|
1. **只允许用户主动触发复制**:所有 `Taro.setClipboardData` 调用必须绑定在明确的用户点击事件上,禁止在无用户操作时自动读写剪切板。
|
||||||
2. **禁止复制后强制中断流程**:复制成功后不得强制跳转、强制关注、强制添加客服等,不能要求用户通过其他方式才能完成当前业务流程。
|
2. **禁止复制后强制中断流程**:复制成功后不得强制跳转、强制关注、强制添加客服等,不能要求用户通过其他方式才能完成当前业务流程。
|
||||||
3. **避免重复 Toast 干扰体验**:微信小程序调用 `setClipboardData` 成功后系统会自带「内容已复制」提示。为避免重复提示,统一封装 `utils/common.ts` 中的 `copyText` 函数:小程序端不再额外显示自定义 `复制成功` Toast,失败时仍显示错误提示。
|
3. **避免重复/失败 Toast 干扰体验**:微信小程序调用 `setClipboardData` 成功后系统会自带「内容已复制」提示。为避免重复提示及误报失败,统一封装 `utils/common.ts` 中的 `copyText` 函数:
|
||||||
|
- 小程序端(weapp)直接调用原生 `wx.setClipboardData`,不再额外显示自定义 `复制成功` / `复制失败` Toast
|
||||||
|
- 失败时仅通过 `console.error` 输出错误日志,便于排查
|
||||||
|
- 非小程序端保留原有成功/失败提示
|
||||||
|
|
||||||
### 项目内剪切板使用现状
|
### 项目内剪切板使用现状
|
||||||
|
|
||||||
@@ -35,5 +38,6 @@
|
|||||||
- 均通过按钮点击触发(复制咨询模板、复制密钥、复制链接、复制兑换码等)
|
- 均通过按钮点击触发(复制咨询模板、复制密钥、复制链接、复制兑换码等)
|
||||||
- 无 `getClipboardData`(自动读取剪切板)调用
|
- 无 `getClipboardData`(自动读取剪切板)调用
|
||||||
- 无复制后强制跳转或中断业务流程的行为
|
- 无复制后强制跳转或中断业务流程的行为
|
||||||
|
- 首页「立即开通」等外链按钮点击后复制链接;相对路径入口(如开发者中心)改为 `Taro.navigateTo` 跳转,不再复制
|
||||||
|
|
||||||
当前实现基本符合 5.15.4 规范。
|
当前实现基本符合 5.15.4 规范。
|
||||||
|
|||||||
@@ -70,14 +70,18 @@ function Home() {
|
|||||||
|
|
||||||
const openMaybeLink = (url?: string) => {
|
const openMaybeLink = (url?: string) => {
|
||||||
if (!url) return
|
if (!url) return
|
||||||
// 小程序内无法直接打开外链,这里统一“复制链接”降低认知成本
|
|
||||||
const abs = toAbsoluteMaybe(url)
|
const abs = toAbsoluteMaybe(url)
|
||||||
|
// 相对路径在小程序内直接跳转
|
||||||
|
if (url.startsWith('/')) {
|
||||||
|
Taro.navigateTo({ url })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 外链在小程序内无法直接打开,复制链接降低认知成本
|
||||||
if (/^https?:\/\//i.test(abs)) {
|
if (/^https?:\/\//i.test(abs)) {
|
||||||
copyText(abs)
|
copyText(abs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Taro.showToast({ title: '请在 PC 端访问该入口', icon: 'none', duration: 1600 })
|
Taro.showToast({ title: '请在 PC 端访问该入口', icon: 'none', duration: 1600 })
|
||||||
copyText(abs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const copyConsultTemplate = () => {
|
const copyConsultTemplate = () => {
|
||||||
@@ -440,7 +444,6 @@ function Home() {
|
|||||||
block
|
block
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
Taro.showToast({ title: '该入口可对接到模板/插件市场', icon: 'none', duration: 1600 })
|
Taro.showToast({ title: '该入口可对接到模板/插件市场', icon: 'none', duration: 1600 })
|
||||||
openMaybeLink('/market')
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
了解模板/插件市场
|
了解模板/插件市场
|
||||||
|
|||||||
@@ -47,27 +47,44 @@ export function wxParse(htmlText:string) {
|
|||||||
|
|
||||||
|
|
||||||
export function copyText(text: string) {
|
export function copyText(text: string) {
|
||||||
Taro.setClipboardData({
|
// 微信小程序调用 setClipboardData 成功后,系统会自带「内容已复制」提示。
|
||||||
data: text,
|
// 为避免重复 Toast 以及部分机型/场景下的误报 fail,小程序端不再额外显示自定义 Toast。
|
||||||
success: function () {
|
const isWeapp = process.env.TARO_ENV === 'weapp';
|
||||||
// 微信小程序调用 setClipboardData 成功后,系统会自带「内容已复制」提示。
|
|
||||||
// 为避免重复 Toast 影响用户体验,小程序端不再额外显示自定义 Toast。
|
if (isWeapp && typeof wx !== 'undefined' && wx.setClipboardData) {
|
||||||
if (process.env.TARO_ENV !== 'weapp') {
|
// 小程序端直接调用原生 API,避免 Taro Promise 封装可能带来的上下文/时序问题
|
||||||
|
wx.setClipboardData({
|
||||||
|
data: text,
|
||||||
|
success: function () {
|
||||||
|
// 系统自带 toast,无需额外提示
|
||||||
|
},
|
||||||
|
fail: function (res: any) {
|
||||||
|
console.error('[copyText] wx.setClipboardData failed:', res?.errMsg || res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Taro.setClipboardData({ data: text })
|
||||||
|
.then(() => {
|
||||||
|
if (!isWeapp) {
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
title: '复制成功',
|
title: '复制成功',
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
duration: 2000
|
duration: 2000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
fail: function () {
|
.catch((err: any) => {
|
||||||
Taro.showToast({
|
console.error('[copyText] Taro.setClipboardData failed:', err?.errMsg || err);
|
||||||
title: '复制失败',
|
if (!isWeapp) {
|
||||||
icon: 'none',
|
Taro.showToast({
|
||||||
duration: 2000
|
title: '复制失败',
|
||||||
});
|
icon: 'none',
|
||||||
}
|
duration: 2000
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user