fix(mini-user): address textarea freeze, input align, wechat share invoke
CI / verify (pull_request) Has been cancelled

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-15 20:48:33 +08:00
parent 966ddc9219
commit 9a3ccabcc9
10 changed files with 299 additions and 46 deletions
@@ -0,0 +1,56 @@
.share-guide {
position: fixed;
inset: 0;
z-index: 10000;
background: rgba(0, 0, 0, 0.55);
display: flex;
flex-direction: column;
align-items: flex-end;
padding: 12px 16px;
box-sizing: border-box;
}
.share-guide__arrow {
width: 0;
height: 0;
margin-right: 18px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 14px solid #fff;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.12));
}
.share-guide__card {
margin-top: 0;
margin-right: 8px;
max-width: 260px;
padding: 16px 18px;
border-radius: 12px;
background: #fff;
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
text-align: left;
}
.share-guide__title {
display: block;
font-size: 16px;
font-weight: 700;
color: #1a1a1a;
margin-bottom: 8px;
}
.share-guide__desc {
display: block;
font-size: 13px;
line-height: 1.5;
color: #666;
}
.share-guide__ok {
display: block;
margin-top: 14px;
text-align: right;
font-size: 14px;
font-weight: 600;
color: #a61d24;
}
@@ -1,5 +1,7 @@
import { useState } from 'react';
import { Button, Text, View } from '@tarojs/components';
import { handleShareButtonClick, type PageSharePayload } from '../lib/wechat-share';
import './ShareGuide.css';
type ShareNavButtonProps = {
payload?: PageSharePayload;
@@ -8,9 +10,11 @@ type ShareNavButtonProps = {
/**
* 顶栏分享:
* - 小程序:open-type=share 弹出微信分享面板
* - H5 微信:JSSDK 配置后提示点右上角 ···
* - H5 微信:JSSDK share / 右上角引导蒙层
*/
export default function ShareNavButton({ payload }: ShareNavButtonProps) {
const [guideVisible, setGuideVisible] = useState(false);
if (process.env.TARO_ENV === 'weapp') {
return (
<Button className="page-nav-bar__btn page-nav-bar__share-btn" openType="share" hoverClass="none">
@@ -20,13 +24,27 @@ export default function ShareNavButton({ payload }: ShareNavButtonProps) {
}
return (
<View
className="page-nav-bar__btn"
onClick={() => {
void handleShareButtonClick(payload);
}}
>
<Text className="page-nav-bar__icon page-nav-bar__icon--share"></Text>
</View>
<>
<View
className="page-nav-bar__btn"
onClick={() => {
void handleShareButtonClick(payload).then((res) => {
if (res.showGuide) setGuideVisible(true);
});
}}
>
<Text className="page-nav-bar__icon page-nav-bar__icon--share"></Text>
</View>
{guideVisible ? (
<View className="share-guide" onClick={() => setGuideVisible(false)}>
<View className="share-guide__arrow" />
<View className="share-guide__card">
<Text className="share-guide__title"></Text>
<Text className="share-guide__desc"> ··· </Text>
<Text className="share-guide__ok"></Text>
</View>
</View>
) : null}
</>
);
}
+25 -15
View File
@@ -6,7 +6,7 @@ import { toast } from './api';
import { isWechatEnv, weixinSdk } from './weixin';
export const DEFAULT_SHARE_TITLE = '你吃饭,杜康买单';
export const DEFAULT_SHARE_DESC = '杜康好客 · 买酒享权益,全城门店可用';
export const DEFAULT_SHARE_DESC = '杜康好客 · 买美酒,享好礼,全城门店可用';
export const WECHAT_SHARE_HINT = '请点击右上角 ··· 分享给好友';
export function getDefaultShareImageUrl(): string {
@@ -51,14 +51,17 @@ export type PageSharePayload = {
link?: string;
};
/** 点击「分享」按钮 */
export async function handleShareButtonClick(payload?: PageSharePayload): Promise<void> {
// 小程序:由 Button open-type="share" 触发,无需在此拉起
/**
* 点击「分享」按钮。
* H5:走微信 JSSDK 配置分享卡片,并尝试 invoke 调起面板;否则返回需展示引导蒙层。
*/
export async function handleShareButtonClick(
payload?: PageSharePayload,
): Promise<{ showGuide: boolean }> {
if (process.env.TARO_ENV === 'weapp' || isMiniProgram()) {
try {
await Taro.showShareMenu({ withShareTicket: true, showShareItems: ['shareAppMessage', 'shareTimeline'] });
} catch {
/* 旧基础库可能不支持 showShareItems */
try {
await Taro.showShareMenu({ withShareTicket: true });
} catch {
@@ -66,24 +69,31 @@ export async function handleShareButtonClick(payload?: PageSharePayload): Promis
}
}
toast(WECHAT_SHARE_HINT);
return;
return { showGuide: false };
}
if (!isWechatEnv()) {
toast('请在微信内打开后分享');
return;
return { showGuide: false };
}
const data = buildDefaultShareData({
title: payload?.title,
desc: payload?.desc,
imgUrl: payload?.imgUrl,
link: payload?.link,
});
try {
await applyWechatShare({
title: payload?.title,
desc: payload?.desc,
imgUrl: payload?.imgUrl,
link: payload?.link,
});
const result = await weixinSdk.share(data);
if (result.invoked) {
return { showGuide: false };
}
toast(WECHAT_SHARE_HINT);
} catch {
toast('分享配置失败,请刷新后重试');
return { showGuide: true };
} catch (e) {
toast(e instanceof Error ? e.message : '分享配置失败,请刷新后重试');
return { showGuide: true };
}
}
@@ -166,12 +166,26 @@ export default function AddressEditPage() {
</View>
<View className="address-form-field">
<Text className="address-form-label"></Text>
<Textarea
className="address-form-textarea"
placeholder="街道门牌号等"
value={form.detail}
onInput={(e) => setForm((prev) => ({ ...prev, detail: e.detail.value }))}
/>
{process.env.TARO_ENV === 'h5' ? (
<textarea
className="address-form-textarea address-form-textarea--native"
placeholder="街道门牌号等"
rows={3}
value={form.detail}
onChange={(e) => {
const value = e.currentTarget.value;
setForm((prev) => ({ ...prev, detail: value }));
}}
/>
) : (
<Textarea
className="address-form-textarea"
placeholder="街道门牌号等"
value={form.detail}
maxlength={200}
onInput={(e) => setForm((prev) => ({ ...prev, detail: e.detail.value }))}
/>
)}
</View>
<View className="address-form-row">
<Text></Text>
+11
View File
@@ -126,6 +126,7 @@
min-height: 88px;
padding: 12px 14px;
border: none;
outline: none;
border-radius: var(--radius-md);
background: var(--color-card);
box-shadow: var(--shadow-card);
@@ -134,6 +135,14 @@
color: var(--color-on-surface);
box-sizing: border-box;
display: block;
resize: vertical;
-webkit-appearance: none;
appearance: none;
}
/* H5 原生 textarea:避免 Taro Textarea 受控输入卡死 */
.address-form-textarea--native {
font-family: inherit;
}
.address-form-textarea textarea,
@@ -144,11 +153,13 @@
padding: 0 !important;
margin: 0 !important;
border: none !important;
outline: none !important;
background: transparent !important;
box-sizing: border-box !important;
font-size: 15px !important;
line-height: 1.5 !important;
color: inherit;
resize: none;
}
.address-form-row {
+23
View File
@@ -43,8 +43,31 @@
height: 52px;
font-size: 24px;
font-weight: 700;
line-height: 52px;
color: var(--color-heritage-red);
text-align: center;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.redeem-input input,
.redeem-input .taro-input,
.redeem-input .weui-input {
width: 100% !important;
height: 100% !important;
min-height: 0 !important;
padding: 0 !important;
margin: 0 !important;
border: none !important;
background: transparent !important;
box-sizing: border-box !important;
font-size: 24px !important;
font-weight: 700 !important;
line-height: normal !important;
color: inherit;
text-align: center !important;
}
.redeem-tips {
+19
View File
@@ -43,8 +43,27 @@
border-radius: var(--radius-md);
background: var(--color-surface-container-low);
font-size: 13px;
line-height: 40px;
color: var(--color-on-surface);
box-sizing: border-box;
display: flex;
align-items: center;
}
.store-search input,
.store-search .taro-input,
.store-search .weui-input {
width: 100% !important;
height: 100% !important;
min-height: 0 !important;
padding: 0 !important;
margin: 0 !important;
border: none !important;
background: transparent !important;
box-sizing: border-box !important;
font-size: 13px !important;
line-height: normal !important;
color: inherit;
}
.store-category-tabs {