微信小程序正常名片
This commit is contained in:
2026-10-17 17:02:22 +08:00
parent 33cd21cf78
commit 21b3247547
2 changed files with 73 additions and 16 deletions

View File

@@ -30,8 +30,8 @@
<!-- 列表 -->
<view class="card-list">
<view v-for="(item, index) in list" :key="item.id || index" class="card-item"
@tap="goDetail(item)">
<view v-for="(item, index) in list" :key="item.id || index" :data-index="index"
class="card-item" @tap="goDetail">
<view class="card-avatar">
<text>{{ avatarText(item.name) }}</text>
</view>
@@ -49,10 +49,10 @@
</view>
</view>
<!-- 收藏星标: 实心=已收藏, 空心=未收藏; 单独点击不进详情 -->
<text class="card-fav" :class="{ 'is-fav': item.is_favorite == 1 }"
@tap.stop="toggleFavorite(item)">{{ item.is_favorite == 1 ? '★' : '☆' }}</text>
<text class="card-fav" :class="{ 'is-fav': item.is_favorite == 1 }" :data-index="index"
@tap.stop="toggleFavorite">{{ item.is_favorite == 1 ? '★' : '☆' }}</text>
<view v-if="followTab === 'due' && item.follow_up_done != 1" class="card-done-btn"
@tap.stop="markDone(item)">完成</view>
:data-index="index" @tap.stop="markDone">完成</view>
<view class="card-arrow">›</view>
</view>
@@ -92,9 +92,9 @@
<view class="empty-title" v-else>还没有名片</view>
<view class="empty-sub">提交信息,申请商家为您建卡</view>
<view class="apply-form">
<input class="apply-input" :value="applyName" @input="e => applyName = e.detail.value"
<input class="apply-input" :value="applyName" @input="onApplyNameInput"
placeholder="您的姓名" />
<input class="apply-input" :value="applyMobile" @input="e => applyMobile = e.detail.value"
<input class="apply-input" :value="applyMobile" @input="onApplyMobileInput"
placeholder="手机号" type="number" />
<view class="apply-submit" :class="{ disabled: applying }" @tap="submitApply">
{{ applying ? '提交中…' : '提交申请' }}
@@ -269,7 +269,8 @@ export default {
this.refresh();
},
// 标记跟进完成(2.11.3): followDone, 成功后该卡从待跟进消失
markDone(item) {
markDone(payload) {
const item = this.resolveItem(payload);
const cardId = this.cardIdOf(item);
if (!cardId) return;
uni.showLoading({ title: '标记中…' });
@@ -300,6 +301,14 @@ export default {
});
},
// 提交建卡申请(2.11.15)
// 模板内联箭头函数(`@input="e => x = e.detail.value"`)在 H5 能跑,
// 但小程序端编译不进 wxml, 输入会失效, 统一收成方法
onApplyNameInput(e) {
this.applyName = (e && e.detail && e.detail.value) || '';
},
onApplyMobileInput(e) {
this.applyMobile = (e && e.detail && e.detail.value) || '';
},
submitApply() {
const name = (this.applyName || '').trim();
const mobile = (this.applyMobile || '').trim();
@@ -329,7 +338,8 @@ export default {
* 切换收藏(双向 toggle): 直接调, 用返回的 is_favorite 回填。
* 乐观更新 + 失败回滚; 仅看收藏模式下取消收藏则从列表移除该行。
*/
toggleFavorite(item) {
toggleFavorite(payload) {
const item = this.resolveItem(payload);
if (!item) return;
const cardId = this.cardIdOf(item);
if (!cardId) {
@@ -417,7 +427,28 @@ export default {
const raw = item.card_id || item.cardId;
return raw ? String(raw) : '';
},
goDetail(item) {
/**
* 取事件对应的行数据。
*
* 为什么需要: 列表内联事件传对象(`@tap="goDetail(item)"`)在 H5 由 Vue 直接求值没问题,
* 但小程序端要经 data-event-opts 索引回填, 实测会拿到 undefined(点击后提示"缺少编号",
* console 打印 可用字段: undefined), 导致小程序点不进详情。
* 现在模板统一改成 `:data-index="index"` + 不传参, 这里从 dataset 取索引回表拿行。
* 兼容三种入参: 数字索引 / 事件对象 / 行对象本身。
*/
resolveItem(payload) {
if (payload == null) return null;
if (typeof payload === 'number') return this.list[payload] || null;
const ds = payload.currentTarget && payload.currentTarget.dataset;
if (ds) {
const i = Number(ds.index);
if (!isNaN(i) && this.list[i]) return this.list[i];
}
// 兜底: 已经是行对象(旧写法/内部调用)
return payload.card_id || payload.cardId || payload.name ? payload : null;
},
goDetail(payload) {
const item = this.resolveItem(payload);
const cardId = this.cardIdOf(item);
if (!cardId) {
// 之前这里是静默 return: 命中时点名片毫无反应, 用户只会认为"点不进去"

View File

@@ -38,14 +38,15 @@
</view>
<view class="preset-grid">
<view class="preset-cell" v-for="p in presets" :key="p.key"
:class="{ active: p.key === selectedKey }" @tap="selectPreset(p.key)">
:class="{ active: p.key === selectedKey }" :style="cellActiveStyle(p)"
@tap="selectPreset(p.key)">
<text class="preset-tag" v-if="p.source === 'canvas'">画布式</text>
<view class="preset-thumb" :style="cellVars(p)">
<view class="pt-header" :style="cellHeader(p)"></view>
<view class="pt-body">
<view class="pt-name"></view>
<view class="pt-line"></view>
<view class="pt-line pt-short"></view>
<view class="pt-name" :style="cellText(p)"></view>
<view class="pt-line" :style="cellSoft(p)"></view>
<view class="pt-line pt-short" :style="cellSoft(p)"></view>
</view>
<view v-if="p.key === selectedKey" class="pt-check">
<view class="pt-check-mark"></view>
@@ -249,11 +250,36 @@ export default {
}
},
methods: {
/**
* 预设缩略图的配色。
*
* 为什么不用 CSS 变量: 微信小程序的渲染层不支持在内联 style 里定义自定义属性
* (`style="--card-bg:#fff"`), 整条 style 会被丢弃 → var(--card-bg) 全部回落默认值,
* 表现就是「小程序端样式缩略图全是白底黑条灰线, 没有颜色」(H5 正常)。
* 这里改为直接输出具体属性 + 具体色值, 三端一致。
*/
cellDs(p) {
return normalizeDesign(p && p.design);
},
cellVars(p) {
return designVarsFor(normalizeDesign(p.design));
const s = this.cellDs(p);
return { backgroundColor: s.bgColor, borderRadius: s.cardRadius + 'px' };
},
cellHeader(p) {
return { background: headerBgFor(normalizeDesign(p.design)) };
const s = this.cellDs(p);
// 纯色代替渐变: 小尺寸缩略图看不出渐变, 但能保证各端一定渲染
return { backgroundColor: s.themeColor };
},
cellText(p) {
return { backgroundColor: this.cellDs(p).textColor };
},
cellSoft(p) {
return { backgroundColor: this.cellDs(p).textSoft };
},
// 选中描边也要给具体色值(CSS 里的 var(--card-theme) 在小程序端同样失效)
cellActiveStyle(p) {
if (p.key !== this.selectedKey) return null;
return { borderColor: this.cellDs(p).themeColor };
},
onLoad(options) {
this.cardId = decodeURIComponent(options.card_id || '');