Merge branch 'feat/camcard' of http://git.aigc-quickapp.com/Uniapp/lucky_shop into feat/camcard

# Conflicts:
#	components-diy/diy-card-show.vue
#	tests/diy-card-style-v2.test.js
This commit is contained in:
2026-10-24 11:28:34 +08:00
5 changed files with 170 additions and 20 deletions

View File

@@ -397,8 +397,9 @@ export function hexToRgba(hex, alpha) {
/** 默认动作类型序(图层面板行序与 C 端合并序一致) */
export const ACT_TYPES = ['tel', 'wx', 'mail', 'web', 'save'];
/** 自定义动作类型白名单(doAct 天然消费: tel/wx/mail/copy 分支 + else 兜底) */
export const ACT_ACTION_TYPES = ['tel', 'wx', 'mail', 'web', 'copy'];
/** 自定义动作类型白名单(doAct 天然消费: tel/wx/mail/copy 分支 + else 兜底;
* 2.19.3 扩展: sms 短信/map 导航/link 页面链接(系统链接对话框)) */
export const ACT_ACTION_TYPES = ['tel', 'wx', 'mail', 'web', 'copy', 'sms', 'map', 'link'];
export const ACT_LABEL_DEFAULTS = {
tel: '打电话',
@@ -440,6 +441,20 @@ export function normalizeActVis(vis) {
return out;
}
/**
* 默认动作删除(2.19.2): actDeleted = { type: 0|1 }, 1=已删除(C端不渲染, 面板行隐藏,
* 经「恢复」chips 找回)。与 actVis(眼睛临时隐藏)独立 —— 删除与隐藏 C 端均不渲染。
* 缺键/非法 = 未删除(0), 历史配置无此字段 → 零变化
*/
export function normalizeActDeleted(deleted) {
const src = deleted && typeof deleted === 'object' ? deleted : {};
const out = {};
ACT_TYPES.forEach(t => {
out[t] = String(src[t]) === '1' ? 1 : 0;
});
return out;
}
/**
* 默认动作文案(2.19): actLabels = { type: string }, 空/缺 = 内置默认
* 历史配置无此字段 → 全默认, 渲染零变化

View File

@@ -238,7 +238,7 @@ import {
WAP_LINE_ICONS, svgLineIconBg,
ACT_GRID_PRESETS, ACT_GRID_PRESET_FALLBACK, hexToRgba,
// 2.19: 显隐/文案/自定义动作归一化 + 素材图标库(与后端 CardIconLibrary 同源)
normalizeActVis, normalizeActLabels, normalizeCustomActs, normalizeActOrder, libIconBg,
normalizeActVis, normalizeActDeleted, normalizeActLabels, normalizeCustomActs, normalizeActOrder, libIconBg,
} from './diy-card-common.js';
export default {
@@ -459,6 +459,7 @@ export default {
acts() {
const raw = this.card && Array.isArray(this.card.acts) ? this.card.acts : [];
const vis = normalizeActVis(this.c.actVis);
const del = normalizeActDeleted(this.c.actDeleted);
const labels = normalizeActLabels(this.c.actLabels);
const icons = this.c.actIcons && typeof this.c.actIcons === 'object' ? this.c.actIcons : {};
const order = normalizeActOrder(this.c.actOrder);
@@ -480,12 +481,12 @@ export default {
});
const out = [];
order.forEach(t => {
if (byType[t] && vis[t] !== 0) out.push(merge(byType[t]));
if (byType[t] && vis[t] !== 0 && del[t] !== 1) out.push(merge(byType[t]));
});
raw.forEach(a => {
if (!a || !a.type) return;
const t = String(a.type);
if (order.indexOf(t) >= 0 || vis[t] === 0) return;
if (order.indexOf(t) >= 0 || vis[t] === 0 || del[t] === 1) return;
out.push(merge(a));
});
normalizeCustomActs(this.c.customActs).forEach(ca => {

View File

@@ -121,6 +121,7 @@ export default {
qrImage: v.qrImage,
// 2.19: 默认动作显隐/文案 + 自定义动作(基件 acts computed 合成)
actVis: v.actVis,
actDeleted: v.actDeleted,
actLabels: v.actLabels,
actOrder: v.actOrder,
customActs: v.customActs,
@@ -211,6 +212,10 @@ export default {
this.goSaveContact();
return;
}
// map(导航): value 留空回落名片地址(2.19.3)
if (act.type === 'map' && !act.value && this.card && this.card.address) {
act = Object.assign({}, act, { value: this.card.address });
}
if (!act.value) return;
if (act.type === 'tel') {
uni.makePhoneCall({ phoneNumber: act.value, fail: () => {} });
@@ -246,6 +251,36 @@ export default {
fail: () => uni.showToast({ title: '打开网站失败', icon: 'none' }),
});
// #endif
} else if (act.type === 'sms') {
// #ifdef H5
window.location.href = 'sms:' + act.value;
// #endif
// #ifndef H5
uni.setClipboardData({
data: act.value,
success: () => uni.showToast({ title: '号码已复制,请到短信粘贴', icon: 'none' }),
});
// #endif
} else if (act.type === 'map') {
uni.setClipboardData({
data: act.value,
success: () => uni.showToast({ title: '地址已复制,可粘贴到地图导航', icon: 'none' }),
});
} else if (act.type === 'link') {
var isHttp = act.value.indexOf('http://') === 0 || act.value.indexOf('https://') === 0;
if (isHttp) {
// #ifdef H5
window.location.href = act.value;
// #endif
// #ifndef H5
uni.setClipboardData({
data: act.value,
success: () => uni.showToast({ title: '链接已复制,请在浏览器打开', icon: 'none' }),
});
// #endif
} else {
this.$util.redirectTo(act.value, {});
}
} else {
uni.setClipboardData({
data: act.value,

View File

@@ -401,6 +401,10 @@ export default {
this.goSaveContact();
return;
}
// map(导航): value 留空回落名片地址(2.19.3)
if (act.type === 'map' && !act.value && this.card && this.card.address) {
act = Object.assign({}, act, { value: this.card.address });
}
if (!act.value) return;
if (act.type === 'tel') {
uni.makePhoneCall({ phoneNumber: act.value, fail: () => {} });
@@ -436,6 +440,36 @@ export default {
fail: () => uni.showToast({ title: '打开网站失败', icon: 'none' }),
});
// #endif
} else if (act.type === 'sms') {
// #ifdef H5
window.location.href = 'sms:' + act.value;
// #endif
// #ifndef H5
uni.setClipboardData({
data: act.value,
success: () => uni.showToast({ title: '号码已复制,请到短信粘贴', icon: 'none' }),
});
// #endif
} else if (act.type === 'map') {
uni.setClipboardData({
data: act.value,
success: () => uni.showToast({ title: '地址已复制,可粘贴到地图导航', icon: 'none' }),
});
} else if (act.type === 'link') {
var isHttp = act.value.indexOf('http://') === 0 || act.value.indexOf('https://') === 0;
if (isHttp) {
// #ifdef H5
window.location.href = act.value;
// #endif
// #ifndef H5
uni.setClipboardData({
data: act.value,
success: () => uni.showToast({ title: '链接已复制,请在浏览器打开', icon: 'none' }),
});
// #endif
} else {
this.$util.redirectTo(act.value, {});
}
} else {
uni.setClipboardData({
data: act.value,