684 行多余 '},' 使 computed 对象提前闭合, detailBtnStyle/emptyBtnStyle 成为 根级孤儿键(Vue 静默忽略) → 发名片大按钮无主题色背景、空态按钮无样式, 控制台警告 Property or method "detailBtnStyle" is not defined。 发现途径: H5 实测(8080 diy 2699 页) console 捕获, 修复后警告清零。 验证: 名片 7 套件全绿
1644 lines
53 KiB
Vue
1644 lines
53 KiB
Vue
<template>
|
|
<view data-component-name="diy-card-mini" class="card-mini">
|
|
<!-- 骨架屏: 首屏加载/切换名片 -->
|
|
<view v-if="loading" class="mini-skeleton" :style="wrapStyle">
|
|
<view class="sk-row">
|
|
<view class="sk sk-avatar"></view>
|
|
<view class="sk-col">
|
|
<view class="sk sk-line" style="width:55%"></view>
|
|
<view class="sk sk-line" style="width:35%;margin-top:16rpx;"></view>
|
|
</view>
|
|
</view>
|
|
<view class="sk sk-line" style="width:100%;margin-top:28rpx;"></view>
|
|
<view class="sk sk-line" style="width:72%;margin-top:16rpx;"></view>
|
|
<view class="sk sk-btn" style="margin-top:28rpx;"></view>
|
|
</view>
|
|
|
|
<!-- 空态: 未拿到名片 -->
|
|
<view v-else-if="!card" class="mini-empty" :style="wrapStyle">
|
|
<text class="empty-icon">💳</text>
|
|
<text class="empty-tip" :style="emptyTipStyle">{{ emptyTip || '暂无名片数据' }}</text>
|
|
<view v-if="emptyActionText" class="empty-btn" :style="emptyBtnStyle" hover-class="btn-press" @tap="onEmptyAction">
|
|
<text class="empty-btn-text">{{ emptyActionText }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 名片卡(精品名片 show 同款版式: 蓝底顶带 + 白卡压边; 角标压在左上) -->
|
|
<view v-else class="mini-card-wrap">
|
|
<view class="mini-band" :style="bandStyle"></view>
|
|
<view class="mini-card fade-up" :style="wrapStyle" :class="{ 'qr-at-corner': qrPos === 'corner' }">
|
|
<!-- 角标插槽(如 self 组件的「我的名片」) -->
|
|
<view class="mini-badge-slot">
|
|
<slot name="badge"></slot>
|
|
</view>
|
|
<!-- 封面图(可选) + 遮罩 -->
|
|
<image v-if="showCover" class="mini-cover" :src="$util.img(card.cover)" mode="aspectFill" />
|
|
<view v-if="showCover" class="mini-cover-scrim"></view>
|
|
|
|
<!-- 主题渐变饰条(可选) -->
|
|
<view v-if="showGradient" class="mini-gradient" :style="gradientStyle"></view>
|
|
|
|
<!-- Logo(可选, 右上; corner 档二维码占同一位, 自动避让) -->
|
|
<image v-if="showLogo && card.logo" class="mini-logo" :src="$util.img(card.logo)" mode="aspectFit" />
|
|
|
|
<!-- 二维码·右上角浮层(corner 档: 外观由 qrStyle 决定, 资料行自动让位; 点击预览名片) -->
|
|
<view v-if="showQrCorner" class="mini-qr mini-qr-corner" :style="qrBlockStyle" @tap.stop="onQrTap">
|
|
<image class="qr-img" :style="qrImgStyle" :src="$util.img(qrSrc)" mode="aspectFit" />
|
|
<text v-if="showQrTip" class="qr-tip" :style="labelStyle">{{ qrTip || '扫码查看完整名片' }}</text>
|
|
</view>
|
|
|
|
<!-- 头部·主题渐变整块档(theme): 渐变通铺卡边 + 装饰圆, plain 档不渲染 -->
|
|
<view v-if="headTheme" class="mini-headtheme" :style="headThemeStyle">
|
|
<view class="headtheme-decor headtheme-decor--big"></view>
|
|
<view class="headtheme-decor headtheme-decor--small"></view>
|
|
<view class="mini-head" :style="cornerHeadStyle">
|
|
<view v-if="showAvatarBlock" class="mini-avatar" :style="avatarStyle">
|
|
<image v-if="card.avatar" class="avatar-img" :src="$util.img(card.avatar)" mode="aspectFill" />
|
|
<text v-else class="avatar-initial">{{ initialOf(card.name) }}</text>
|
|
</view>
|
|
<view class="mini-head-info">
|
|
<view class="name-row">
|
|
<text class="mini-name" :style="nameStyle">{{ card.name || '未命名名片' }}</text>
|
|
<text v-if="isEnterprise" class="mini-badge" :style="badgeStyle">企业</text>
|
|
</view>
|
|
<text v-if="card.card_title" class="mini-card-title" :style="cardTitleStyle">{{ card.card_title }}</text>
|
|
<text v-if="subLine" class="mini-sub" :style="subTextStyle">{{ subLine }}</text>
|
|
</view>
|
|
<!-- 二维码·头部右侧(head 档: 头像|信息|二维码 三段 flex, 零遮挡) -->
|
|
<view v-if="showQrHead" class="mini-qr mini-qr-head" :style="qrBlockStyle">
|
|
<image class="qr-img" :style="qrImgStyle" :src="$util.img(qrSrc)" mode="aspectFit" />
|
|
<text v-if="showQrTip" class="qr-tip" :style="labelStyle">{{ qrTip || '扫码查看完整名片' }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 头部·白卡档(plain, 历史默认) -->
|
|
<view v-if="!headTheme" class="mini-head" :style="cornerHeadStyle">
|
|
<view v-if="showAvatarBlock" class="mini-avatar" :style="avatarStyle">
|
|
<image v-if="card.avatar" class="avatar-img" :src="$util.img(card.avatar)" mode="aspectFill" />
|
|
<text v-else class="avatar-initial">{{ initialOf(card.name) }}</text>
|
|
</view>
|
|
<view class="mini-head-info">
|
|
<view class="name-row">
|
|
<text class="mini-name" :style="nameStyle">{{ card.name || '未命名名片' }}</text>
|
|
<text v-if="isEnterprise" class="mini-badge" :style="badgeStyle">企业</text>
|
|
</view>
|
|
<text v-if="card.card_title" class="mini-card-title" :style="cardTitleStyle">{{ card.card_title }}</text>
|
|
<text v-if="subLine" class="mini-sub" :style="subTextStyle">{{ subLine }}</text>
|
|
</view>
|
|
<!-- 二维码·头部右侧(head 档: 头像|信息|二维码 三段 flex, 零遮挡; 点击预览名片) -->
|
|
<view v-if="showQrHead" class="mini-qr mini-qr-head" :style="qrBlockStyle" @tap.stop="onQrTap">
|
|
<image class="qr-img" :style="qrImgStyle" :src="$util.img(qrSrc)" mode="aspectFit" />
|
|
<text v-if="showQrTip" class="qr-tip" :style="labelStyle">{{ qrTip || '扫码查看完整名片' }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 快捷操作·资料区上方档(2.18 actsPosition=above): below 时由下方同构块渲染 -->
|
|
<view v-if="actsAbove && showActs && acts.length && actsGrid" class="mini-acts-grid" :style="[actsBlockStyle, cornerClearStyle]">
|
|
<view v-for="(act, i) in acts" :key="'ta' + i" class="act-grid-item" :style="{ width: gridItemWidth }" hover-class="btn-press" @tap.stop="onAct(act)">
|
|
<view class="act-grid-icon" :style="actGridIconStyle(act)">
|
|
<!-- 自定义图标图片(2.18 媒体库, 优先) / SVG 线稿(2.18.1 与 wap detail 同源) / 首字兜底 -->
|
|
<image v-if="actImgOf(act)" class="act-grid-img" :src="$util.img(actImgOf(act))" mode="aspectFit" />
|
|
<view v-else-if="actLibOf(act)" class="act-grid-svg" :style="actLibStyle(act)"></view>
|
|
<view v-else-if="actSvgOf(act)" class="act-grid-svg" :style="actSvgStyle(act)"></view>
|
|
<text v-else class="act-grid-initial" :style="actGridGlyphStyle(act)">{{ actInitialOf(act) }}</text>
|
|
</view>
|
|
<text class="act-grid-label" :style="actGridLabelStyle(act)">{{ act.label }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="actsAbove && showActs && acts.length && !actsGrid" class="mini-acts" :style="[actsBlockStyle, cornerClearStyle]">
|
|
<view v-for="(act, i) in acts" :key="'ta' + i" class="act-chip"
|
|
:style="i === 0 ? actPrimaryStyle : actGhostStyle" hover-class="btn-press" @tap.stop="onAct(act)">
|
|
<text class="act-text" :style="i === 0 ? actPrimaryTextStyle : actGhostTextStyle">{{ act.label }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 资料行(可折叠; 有字形字段显图标, 无字形退化为文字标签) -->
|
|
<view v-if="showRowsBlock && shownRows.length" class="mini-rows" :style="rowsClearStyle">
|
|
<!-- 资料区标题(2.17 可选): 主题色竖条 + 标题 -->
|
|
<view v-if="rowsTitleShow" class="mini-rows-title">
|
|
<view class="rows-title-bar" :style="rowsTitleBarStyle"></view>
|
|
<text class="rows-title-text" :style="rowsTitleStyle">{{ rowsTitle }}</text>
|
|
</view>
|
|
<view v-for="(row, i) in shownRows" :key="i" class="mini-row"
|
|
:class="{ 'row-tappable': rowTapable(row) }" :hover-class="rowTapable(row) ? 'btn-press' : 'none'" @tap="onRowTap(row)">
|
|
<!-- CSS 描边图标档(2.17.1): 邮箱/网站无 iconfont 字形, 纯 view 绘制 -->
|
|
<view v-if="rowCssIcon(row)" class="row-css-wrap">
|
|
<view v-if="rowCssIcon(row) === 'mail'" class="css-ico-mail css-ico-mail--row" :style="rowCssBorderStyle(row)">
|
|
<view class="css-ico-mail-flap" :style="rowCssBorderStyle(row)"></view>
|
|
</view>
|
|
<view v-else class="css-ico-web css-ico-web--row" :style="rowCssBorderStyle(row)">
|
|
<view class="css-ico-web-h" :style="rowCssFillStyle(row)"></view>
|
|
<view class="css-ico-web-v" :style="rowCssBorderStyle(row)"></view>
|
|
</view>
|
|
</view>
|
|
<text v-else-if="rowIcon(row)" class="row-icon iconfont" :class="rowIcon(row)" :style="labelStyle"></text>
|
|
<text v-else class="row-label" :style="rowLabelStyle">{{ row.label }}</text>
|
|
<text class="row-value" :style="valueStyle">{{ row.value }}</text>
|
|
<text v-if="showCopyBtn && row.value" class="row-copy" :style="copyBtnStyle" @tap.stop="onCopyRow(row)">复制</text>
|
|
</view>
|
|
<view v-if="hasMoreRows" class="row-toggle" hover-class="btn-press" @tap="expanded = !expanded">
|
|
<text class="toggle-text" :style="toggleStyle">{{ expanded ? '收起资料' : '展开全部资料(' + hiddenCount + ')' }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 二维码·资料行下方(rows 档, 默认; 点击预览名片); mini-qr-center: 块级居中 -->
|
|
<view v-if="showQrRows" class="mini-qr mini-qr-center" :style="qrBlockStyle" @tap.stop="onQrTap">
|
|
<image class="qr-img" :style="qrImgStyle" :src="$util.img(qrSrc)" mode="aspectFit" />
|
|
<text v-if="showQrTip" class="qr-tip" :style="labelStyle">{{ qrTip || '扫码查看完整名片' }}</text>
|
|
</view>
|
|
|
|
<!-- 快捷操作·图标宫格档(grid): 彩色浅底图标 + 下方文字 -->
|
|
<view v-if="!actsAbove && showActs && acts.length && actsGrid" class="mini-acts-grid" :style="[actsBlockStyle, cornerClearStyle]">
|
|
<view v-for="(act, i) in acts" :key="i" class="act-grid-item" :style="{ width: gridItemWidth }" hover-class="btn-press" @tap.stop="onAct(act)">
|
|
<view class="act-grid-icon" :style="actGridIconStyle(act)">
|
|
<!-- 自定义图标图片(2.18 媒体库, 优先) / SVG 线稿(2.18.1 与 wap detail 同源) / 首字兜底 -->
|
|
<image v-if="actImgOf(act)" class="act-grid-img" :src="$util.img(actImgOf(act))" mode="aspectFit" />
|
|
<view v-else-if="actLibOf(act)" class="act-grid-svg" :style="actLibStyle(act)"></view>
|
|
<view v-else-if="actSvgOf(act)" class="act-grid-svg" :style="actSvgStyle(act)"></view>
|
|
<text v-else class="act-grid-initial" :style="actGridGlyphStyle(act)">{{ actInitialOf(act) }}</text>
|
|
</view>
|
|
<text class="act-grid-label" :style="actGridLabelStyle(act)">{{ act.label }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 快捷操作·胶囊芯片档(chips, 历史默认; 最小触达 72rpx; 首个为主动作) -->
|
|
<view v-if="!actsAbove && showActs && acts.length && !actsGrid" class="mini-acts" :style="[actsBlockStyle, cornerClearStyle]">
|
|
<view v-for="(act, i) in acts" :key="i" class="act-chip"
|
|
:style="actStyle" hover-class="btn-press" @tap.stop="onAct(act)">
|
|
<text class="act-text" :style="actTextStyle">{{ act.label }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 二维码·主按钮上方(bottom 档; 点击预览名片) -->
|
|
<view v-if="showQrBottom" class="mini-qr mini-qr-center" :style="qrBlockStyle" @tap.stop="onQrTap">
|
|
<image class="qr-img" :style="qrImgStyle" :src="$util.img(qrSrc)" mode="aspectFit" />
|
|
<text v-if="showQrTip" class="qr-tip" :style="labelStyle">{{ qrTip || '扫码查看完整名片' }}</text>
|
|
</view>
|
|
|
|
<!-- 发名片(对齐名片详情页: 主题色大按钮; 点击跳原生转发中转页拉起微信转发面板) -->
|
|
<view v-if="showSendBtn" class="mini-send" :style="sendBtnStyle" hover-class="btn-press" @tap.stop="onSend">
|
|
<text class="send-text">{{ sendBtnText || '发名片' }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 发送名片: 小程序端用原生转发(open-type=share 直接拉起「发送给朋友」面板, 与微信分享一致);
|
|
H5 端保持弹自定义分享抽屉(原生分享在 H5 不可用) -->
|
|
<!-- #ifdef MP-WEIXIN || MP-HARMONY -->
|
|
<button v-if="showDetailBtn" class="mini-detail" :style="detailBtnStyle" hover-class="btn-press"
|
|
open-type="share"
|
|
:data-card-id="card && card.card_id" :data-card-name="card && card.name" :data-card-qr="card && card.qr_url">
|
|
<text class="detail-text">{{ detailBtnText || '发送名片' }}</text>
|
|
</button>
|
|
<!-- #endif -->
|
|
<!-- #ifndef MP-WEIXIN -->
|
|
<view v-if="showDetailBtn" class="mini-detail" :style="detailBtnStyle" hover-class="btn-press" @tap.stop="openCardShare">
|
|
<text class="detail-text">{{ detailBtnText || '发送名片' }}</text>
|
|
</view>
|
|
<!-- #endif -->
|
|
|
|
<!-- 分享名片抽屉(2026-10-23 参考图定稿: 与精选名片 show 同款版式/文案,
|
|
复刻 pages_tool/card/detail.vue 的 share-sheet; 类名 cs- 前缀, scoped 隔离) -->
|
|
<view class="cs-mask" v-if="showShare" @tap="closeShare"></view>
|
|
<view class="cs-sheet" :class="{ 'cs-sheet-show': showShare }">
|
|
<view class="ss-bar"></view>
|
|
<view class="ss-title">分享名片</view>
|
|
<view class="ss-sub">客户打开链接即可查看名片并留言留资</view>
|
|
<view class="ss-qr-box">
|
|
<image v-if="card && card.qr_url" :src="$util.img(card.qr_url)" class="ss-qr" mode="widthFix"
|
|
show-menu-by-longpress="true" @tap="previewQr" />
|
|
</view>
|
|
<view class="ss-link">{{ (card && card.wap_url) || '' }}</view>
|
|
<view class="ss-btns">
|
|
<view class="ss-btn ss-btn-main" :style="shareBtnStyle" @tap="copyCardLink">复制链接</view>
|
|
<!-- #ifdef H5 -->
|
|
<view class="ss-btn" @tap="h5CardShare">浏览器分享</view>
|
|
<!-- #endif -->
|
|
<!-- #ifdef MP-WEIXIN || MP-HARMONY -->
|
|
<view class="ss-btn" @tap="saveCardQr">保存二维码</view>
|
|
<!-- #endif -->
|
|
</view>
|
|
<view class="ss-tip">
|
|
<!-- #ifdef MP-WEIXIN -->长按二维码也可保存到相册<!-- #endif -->
|
|
<!-- #ifdef H5 -->长按二维码可保存到相册<!-- #endif -->
|
|
<!-- #ifdef MP-HARMONY -->点击「保存二维码」存入相册<!-- #endif -->
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
// 数字名片 · 名片迷你卡基件(show/self 共用, 设计系统单一事实来源)
|
|
// 消费名片自身设计资产: cover 封面 / logo / theme_color / 渐变末色与角度 / card_title
|
|
import {
|
|
CardTokens, px2rpx, flagOn, num, initialOf, avatarBg, themeGradient, darkenColor, visibleRows,
|
|
rowIconFor, rowCssIconFor, rowActOf, normalizeQrPosition, normalizeQrStyle, resolveQrSize, qrTransform, QR_SIZES,
|
|
normalizeHeadStyle, normalizeActsLayout, normalizeActGridColorMode, normalizeActsPosition, actIconCfgOf,
|
|
WAP_LINE_ICONS, svgLineIconBg,
|
|
ACT_GRID_PRESETS, ACT_GRID_PRESET_FALLBACK, hexToRgba,
|
|
// 2.19: 显隐/文案/自定义动作归一化 + 素材图标库(与后端 CardIconLibrary 同源)
|
|
normalizeActVis, normalizeActDeleted, normalizeActLabels, normalizeCustomActs, normalizeActOrder, libIconBg,
|
|
} from './diy-card-common.js';
|
|
|
|
export default {
|
|
name: 'diy-card-mini',
|
|
props: {
|
|
card: { type: Object, default: null },
|
|
config: { type: Object, default: () => ({}) },
|
|
loading: { type: Boolean, default: false },
|
|
emptyTip: { type: String, default: '' },
|
|
emptyActionText: { type: String, default: '' },
|
|
},
|
|
data() {
|
|
return { expanded: false, showShare: false };
|
|
},
|
|
computed: {
|
|
c() {
|
|
return this.config || {};
|
|
},
|
|
wrapStyle() {
|
|
const c = this.c;
|
|
return this.$util.objToStyle({
|
|
background: flagOn(c.useCover, false) && this.card && this.card.cover ? 'transparent' : (c.bgColor || CardTokens.color.bg),
|
|
borderRadius: px2rpx(num(c.borderRadius, CardTokens.radius.md)) + 'rpx',
|
|
padding: px2rpx(num(c.padding, CardTokens.space.lg)) + 'rpx',
|
|
boxShadow: flagOn(c.showShadow, true) ? CardTokens.shadow.card : 'none',
|
|
});
|
|
},
|
|
showCover() {
|
|
return flagOn(this.c.useCover, false) && !!(this.card && this.card.cover);
|
|
},
|
|
showGradient() {
|
|
return flagOn(this.c.showGradient, false);
|
|
},
|
|
showLogo() {
|
|
// corner 档二维码占右上同一位, Logo 自动避让(面板有提示)
|
|
return flagOn(this.c.showLogo, false) && this.qrPos !== 'corner';
|
|
},
|
|
showActs() {
|
|
return flagOn(this.c.showQuick, true);
|
|
},
|
|
showRowsBlock() {
|
|
// 资料行总开关(面板「显示资料行」); 历史配置无此字段时默认显示, 兼容 1.0
|
|
return flagOn(this.c.showRows, true);
|
|
},
|
|
/**
|
|
* 二维码总条件: 开关 + 有码源(自定义图 qrImage 优先, 回落名片码 qr_url)
|
|
*/
|
|
showQrBase() {
|
|
return flagOn(this.c.showQr, false) && !!this.qrSrc;
|
|
},
|
|
/** 二维码码源(2.18): 用户自定义图片(媒体库)优先, 空=名片自动生成的码 */
|
|
qrSrc() {
|
|
const custom = String(this.c.qrImage || '').trim();
|
|
if (custom) return custom;
|
|
return (this.card && this.card.qr_url) || '';
|
|
},
|
|
qrPos() {
|
|
return normalizeQrPosition(this.c.qrPosition);
|
|
},
|
|
qrStyle() {
|
|
return normalizeQrStyle(this.c.qrStyle);
|
|
},
|
|
showQrTip() {
|
|
return flagOn(this.c.qrTipShow, true);
|
|
},
|
|
showQrRows() { return this.showQrBase && this.qrPos === 'rows'; },
|
|
showQrBottom() { return this.showQrBase && this.qrPos === 'bottom'; },
|
|
showQrHead() { return this.showQrBase && this.qrPos === 'head'; },
|
|
showQrCorner() { return this.showQrBase && this.qrPos === 'corner'; },
|
|
/** 头像开关(历史配置无此字段时默认显示) */
|
|
showAvatarBlock() {
|
|
return flagOn(this.c.showAvatar, true);
|
|
},
|
|
/**
|
|
* corner 档头部水平让位: 按浮层实际宽度反算(浮层宽[尺寸+衬底] + 右偏移20 + 呼吸20),
|
|
* 自定义大尺寸时自动跟随 —— 修复静态 180rpx 在 qrSize>120 时让位不足压住姓名区;
|
|
* 非 corner 档 / 二维码未启用时输出空对象(浮层不存在无需让位)
|
|
*/
|
|
cornerHeadStyle() {
|
|
if (this.qrPos !== 'corner' || !this.showQrBase) return {};
|
|
const size = resolveQrSize(this.qrPos, this.c.qrSize);
|
|
const pad = this.qrStyle === 'plain' ? 0 : (this.qrStyle === 'gradient' ? 12 : 20);
|
|
return { paddingRight: (size + pad + 40) + 'rpx' };
|
|
},
|
|
/**
|
|
* corner 档资料行/操作区让位量: 按二维码实际占高反算
|
|
* (浮层 top 20 + 块高[尺寸+样式衬底+tip] - 头部实际高 + 间隙 10), 防遮挡;
|
|
* 头部实际高: plain=104 / theme 档=32+104+28=164(上下 padding 增高, 2.17);
|
|
* 自定义大尺寸/关 tip 时自动跟随(不用 calc, 纯数值)
|
|
*/
|
|
cornerClearStyle() {
|
|
if (this.qrPos !== 'corner' || !this.showQrBase) return {};
|
|
const size = resolveQrSize(this.qrPos, this.c.qrSize);
|
|
const pad = this.qrStyle === 'plain' ? 0 : (this.qrStyle === 'gradient' ? 6 : 10) * 2;
|
|
const tip = this.showQrTip ? 42 : 0;
|
|
const total = 20 + size + pad + tip;
|
|
const headHeight = this.headTheme ? 164 : 104;
|
|
return { marginTop: Math.max(24, total - headHeight + 10) + 'rpx' };
|
|
},
|
|
/**
|
|
* 二维码容器样式: 只管尺寸(自定义>档位自动) + 微调位移(transform, WXSS 支持)。
|
|
* 外观衬底(白卡/主题色/渐变)在 qrImgStyle 上只包二维码图 ——
|
|
* 「扫码查看完整名片」提示(2026-10-23 用户要求)在衬底外, 无蓝底
|
|
*/
|
|
qrBlockStyle() {
|
|
const size = resolveQrSize(this.qrPos, this.c.qrSize);
|
|
const style = {
|
|
width: size + 'rpx',
|
|
};
|
|
const transform = qrTransform(this.c.qrOffsetX, this.c.qrOffsetY);
|
|
if (transform) style.transform = transform;
|
|
return this.$util.objToStyle(style);
|
|
},
|
|
/** 二维码图样式: 尺寸 + 外观衬底(plain 原图 / card 白卡 / theme 主题色 / gradient 渐变) */
|
|
qrImgStyle() {
|
|
const size = resolveQrSize(this.qrPos, this.c.qrSize);
|
|
const style = {
|
|
width: size + 'rpx',
|
|
height: size + 'rpx',
|
|
boxSizing: 'border-box',
|
|
};
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
if (this.qrStyle === 'card') {
|
|
style.background = '#ffffff';
|
|
style.border = '2rpx solid #EEF0F3';
|
|
style.borderRadius = '12rpx';
|
|
style.padding = '10rpx';
|
|
} else if (this.qrStyle === 'theme') {
|
|
style.background = theme;
|
|
style.borderRadius = '12rpx';
|
|
style.padding = '10rpx';
|
|
} else if (this.qrStyle === 'gradient') {
|
|
const end = (this.card && this.card.gradient_end) || darkenColor(theme, 0.18);
|
|
style.background = 'linear-gradient(135deg, ' + theme + ' 0%, ' + end + ' 100%)';
|
|
style.borderRadius = '16rpx';
|
|
style.padding = '6rpx';
|
|
}
|
|
return this.$util.objToStyle(style);
|
|
},
|
|
showDetailBtn() {
|
|
return flagOn(this.c.showDetailBtn, true);
|
|
},
|
|
/** 发名片按钮(名片详情页同款主按钮; 默认关, 由 show 组件打开) */
|
|
showSendBtn() {
|
|
return flagOn(this.c.showSendBtn, false);
|
|
},
|
|
sendBtnText() {
|
|
return this.c.sendBtnText || '发名片';
|
|
},
|
|
sendBtnStyle() {
|
|
return this.$util.objToStyle({
|
|
background: themeGradient(this.card),
|
|
height: px2rpx(CardTokens.touch.btnHeight) + 'rpx',
|
|
borderRadius: px2rpx(CardTokens.radius.pill) + 'rpx',
|
|
});
|
|
},
|
|
/** 头部形态(2.17): theme=渐变整块头部(历史配置无此字段时为 plain, 兼容 1.0) */
|
|
headTheme() {
|
|
return normalizeHeadStyle(this.c.headStyle) === 'theme';
|
|
},
|
|
/**
|
|
* theme 档头部块: 渐变通铺卡边(负 margin 抵消 wrapStyle 的 padding, WXSS 不用 calc)
|
|
* 内部左右 padding = 卡片原 padding, 保证头像与下方资料行左缘对齐
|
|
*/
|
|
headThemeStyle() {
|
|
const pad = px2rpx(num(this.c.padding, CardTokens.space.lg));
|
|
return this.$util.objToStyle({
|
|
background: themeGradient(this.card),
|
|
margin: '-' + pad + 'rpx -' + pad + 'rpx 0',
|
|
padding: '32rpx ' + pad + 'rpx 28rpx',
|
|
});
|
|
},
|
|
/** 资料区标题(2.17): 默认关(历史配置无此字段时不出标题) */
|
|
rowsTitleShow() {
|
|
return flagOn(this.c.showRowsTitle, false);
|
|
},
|
|
rowsTitle() {
|
|
return String(this.c.rowsTitle || '联系资料');
|
|
},
|
|
/** 快捷操作布局(2.17): 默认 chips 胶囊(历史配置无此字段时不变) */
|
|
actsGrid() {
|
|
return normalizeActsLayout(this.c.actsLayout) === 'grid';
|
|
},
|
|
/** 复制按钮(2.17): 默认关; 手机等资料行右侧浅底小按钮, 点击复制原文 */
|
|
showCopyBtn() {
|
|
return flagOn(this.c.showCopyBtn, false);
|
|
},
|
|
qrTip() {
|
|
return this.c.qrTip || '';
|
|
},
|
|
detailBtnText() {
|
|
return this.c.detailBtnText || '';
|
|
},
|
|
maxRows() {
|
|
return num(this.c.maxRows, 4);
|
|
},
|
|
rowsInfo() {
|
|
if (!this.card) return { shown: [], hasMore: false };
|
|
return visibleRows(this.card.rows, this.expanded ? 0 : this.maxRows);
|
|
},
|
|
shownRows() {
|
|
return this.rowsInfo.shown;
|
|
},
|
|
hasMoreRows() {
|
|
return !this.expanded && this.rowsInfo.hasMore;
|
|
},
|
|
hiddenCount() {
|
|
return this.rowsInfo.rest.length;
|
|
},
|
|
/**
|
|
* 快捷操作(2.19 重构): 服务端 acts(资料驱动) + 组件配置合成
|
|
* 1. actVis 显隐过滤(缺省全显, 历史形态零变化)
|
|
* 2. actLabels 文案覆盖(空/缺 = 服务端 label)
|
|
* 3. customActs 自定义动作尾接(vis=0 隐藏)
|
|
* 每项合并 cfgImg/cfgKey/cfgColor/cfgBg 四字段 —— 图标渲染统一走
|
|
* 「媒体库图 > 素材库图标 > SVG 线稿 > 首字」优先级, 免去方法内重复取配置
|
|
*/
|
|
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);
|
|
const merge = (a) => {
|
|
const t = String(a.type);
|
|
const cfg = icons[t] && typeof icons[t] === 'object' ? icons[t] : {};
|
|
return Object.assign({}, a, {
|
|
label: labels[t] || a.label,
|
|
cfgImg: String(cfg.img || '').trim(),
|
|
cfgKey: String(cfg.iconKey || '').trim(),
|
|
cfgColor: String(cfg.color || '').trim(),
|
|
cfgBg: String(cfg.bg || '').trim(),
|
|
});
|
|
};
|
|
// 2.19.1: 按 actOrder 次序输出默认动作; 后端 quickActs 扩展类型(order 外)尾接兜底
|
|
const byType = {};
|
|
raw.forEach(a => {
|
|
if (a && a.type) byType[String(a.type)] = a;
|
|
});
|
|
const out = [];
|
|
order.forEach(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 || del[t] === 1) return;
|
|
out.push(merge(a));
|
|
});
|
|
normalizeCustomActs(this.c.customActs).forEach(ca => {
|
|
if (ca.vis === 0) return;
|
|
out.push(Object.assign({}, ca, {
|
|
cfgImg: ca.img,
|
|
cfgKey: ca.iconKey,
|
|
cfgColor: ca.color,
|
|
cfgBg: ca.bg,
|
|
}));
|
|
});
|
|
return out;
|
|
},
|
|
isEnterprise() {
|
|
return this.card && this.card.card_type === 'enterprise';
|
|
},
|
|
subLine() {
|
|
const c = this.card || {};
|
|
return [c.job_title, c.company].filter(Boolean).join(' · ');
|
|
},
|
|
gradientStyle() {
|
|
return this.$util.objToStyle({ background: themeGradient(this.card) });
|
|
},
|
|
bandStyle() {
|
|
// 蓝色顶带底色: 名片主题渐变(精选名片 show 同款)
|
|
return this.$util.objToStyle({ background: themeGradient(this.card) });
|
|
},
|
|
shareBtnStyle() {
|
|
// 分享抽屉主按钮(复制链接): 主题色
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
return this.$util.objToStyle({
|
|
background: theme,
|
|
border: '2rpx solid ' + theme,
|
|
});
|
|
},
|
|
avatarStyle() {
|
|
return this.$util.objToStyle({ background: avatarBg(this.card) });
|
|
},
|
|
nameStyle() {
|
|
// theme 渐变头部档: 深底上默认白字(headNameColor 可覆盖); plain 档沿用历史配色
|
|
const autoColor = this.headTheme ? (this.c.headNameColor || '#FFFFFF') : (this.c.nameColor || CardTokens.color.text);
|
|
return this.$util.objToStyle({
|
|
color: autoColor,
|
|
fontSize: px2rpx(num(this.c.nameSize, 17)) + 'rpx',
|
|
});
|
|
},
|
|
/** 名片头衔(设计器 card_title): 默认 13px = 26rpx, 与副行 24rpx 区分 */
|
|
cardTitleStyle() {
|
|
const autoColor = this.headTheme ? (this.c.headSubColor || 'rgba(255,255,255,0.9)') : (this.c.infoColor || CardTokens.color.textSub);
|
|
return this.$util.objToStyle({
|
|
color: autoColor,
|
|
fontSize: px2rpx(num(this.c.cardTitleSize, 13)) + 'rpx',
|
|
});
|
|
},
|
|
/** 副行(公司/职位)与空态提示共用: 默认 12px = 24rpx */
|
|
subTextStyle() {
|
|
// theme 档副行默认白 85% 透明度(渐变深底可读); plain 档沿用历史配色
|
|
const autoColor = this.headTheme ? (this.c.headSubColor || 'rgba(255,255,255,0.85)') : (this.c.infoColor || CardTokens.color.textSub);
|
|
return this.$util.objToStyle({
|
|
color: autoColor,
|
|
fontSize: px2rpx(num(this.c.subSize, 12)) + 'rpx',
|
|
});
|
|
},
|
|
/** labelColor 纯色(资料行图标/二维码提示用, 不带字号) */
|
|
labelStyle() {
|
|
return this.$util.objToStyle({ color: this.c.labelColor || CardTokens.color.textLabel });
|
|
},
|
|
/** 资料行文字标签: 默认 12px = 24rpx */
|
|
rowLabelStyle() {
|
|
return this.$util.objToStyle({
|
|
color: this.c.labelColor || CardTokens.color.textLabel,
|
|
fontSize: px2rpx(num(this.c.labelSize, 12)) + 'rpx',
|
|
});
|
|
},
|
|
valueStyle() {
|
|
return this.$util.objToStyle({
|
|
color: this.c.infoColor || CardTokens.color.textSub,
|
|
fontSize: px2rpx(num(this.c.valueSize, 12)) + 'rpx',
|
|
});
|
|
},
|
|
/** 空态提示: 固定历史配色(不随 theme 头部变白 —— 空态无渐变头) */
|
|
emptyTipStyle() {
|
|
return this.$util.objToStyle({
|
|
color: this.c.infoColor || CardTokens.color.textSub,
|
|
fontSize: px2rpx(num(this.c.subSize, 12)) + 'rpx',
|
|
});
|
|
},
|
|
/** 资料区标题(2.17): 主题色竖条 + 主文字色标题 */
|
|
rowsTitleBarStyle() {
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
return this.$util.objToStyle({ background: theme });
|
|
},
|
|
rowsTitleStyle() {
|
|
return this.$util.objToStyle({
|
|
color: this.c.nameColor || CardTokens.color.text,
|
|
fontSize: px2rpx(14) + 'rpx',
|
|
fontWeight: '600',
|
|
});
|
|
},
|
|
/** 复制按钮: 主题浅底 + 主题色字(hexToRgba 动态派生, WXSS 无 color-mix) */
|
|
copyBtnStyle() {
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
return this.$util.objToStyle({
|
|
background: hexToRgba(theme, 0.12) || '#F2F3F5',
|
|
color: theme,
|
|
});
|
|
},
|
|
badgeStyle() {
|
|
// 企业徽标固定红底(参考图 2026-10-22 口径), 与头像底色解耦
|
|
return this.$util.objToStyle({ background: '#FA5151' });
|
|
},
|
|
toggleStyle() {
|
|
return this.$util.objToStyle({ color: (this.card && this.card.theme_color) || CardTokens.color.primary });
|
|
},
|
|
actStyle() {
|
|
// 快捷芯片统一「发邮件」样式(2026-10-23 参考图定稿): 白底 + 主题色描边;
|
|
// 尺寸/圆角由 .act-chip CSS 类控制(内联只出底色+描边, 不锁死尺寸)
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
return this.$util.objToStyle({
|
|
background: '#FFFFFF',
|
|
height: px2rpx(CardTokens.touch.chipHeight) + 'rpx',
|
|
padding: '0 ' + px2rpx(CardTokens.space.xl) + 'rpx',
|
|
borderRadius: px2rpx(CardTokens.radius.pill) + 'rpx',
|
|
});
|
|
},
|
|
actPrimaryTextStyle() {
|
|
return this.$util.objToStyle({
|
|
color: '#FFFFFF',
|
|
fontSize: px2rpx(num(this.c.actSize, 12)) + 'rpx',
|
|
});
|
|
},
|
|
/** 首动作(索引 0)实心底: 主题色 + 胶囊尺寸(与 actStyle/actGhostStyle 同口径) */
|
|
actPrimaryStyle() {
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
return this.$util.objToStyle({
|
|
background: theme,
|
|
height: px2rpx(CardTokens.touch.chipHeight) + 'rpx',
|
|
padding: '0 ' + px2rpx(CardTokens.space.xl) + 'rpx',
|
|
borderRadius: px2rpx(CardTokens.radius.pill) + 'rpx',
|
|
});
|
|
},
|
|
actGhostStyle() {
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
return this.$util.objToStyle({
|
|
background: 'transparent',
|
|
border: '2rpx solid ' + theme,
|
|
});
|
|
},
|
|
actTextStyle() {
|
|
return this.$util.objToStyle({ color: (this.card && this.card.theme_color) || CardTokens.color.primary });
|
|
},
|
|
actGhostTextStyle() {
|
|
return this.$util.objToStyle({
|
|
color: (this.card && this.card.theme_color) || CardTokens.color.primary,
|
|
fontSize: px2rpx(num(this.c.actSize, 12)) + 'rpx',
|
|
});
|
|
},
|
|
/** 发送名片按钮文字: 默认 13px = 26rpx */
|
|
detailTextStyle() {
|
|
return this.$util.objToStyle({
|
|
color: '#FFFFFF',
|
|
fontSize: px2rpx(num(this.c.btnSize, 13)) + 'rpx',
|
|
});
|
|
},
|
|
/** 宫格配色模式(2.17): preset 多彩预设 / theme 主题色派生 */
|
|
gridColorMode() {
|
|
return normalizeActGridColorMode(this.c.actGridColorMode);
|
|
},
|
|
/** 宫格列宽: 5 个动作一行(存通讯录入列后), 4 个及以下仍四列均分 */
|
|
gridItemWidth() {
|
|
return this.acts.length > 4 ? '20%' : '25%';
|
|
},
|
|
/** 快捷操作区位置(2.18): above=资料区上方(below 历史默认零变化) */
|
|
actsAbove() {
|
|
return normalizeActsPosition(this.c.actsPosition) === 'above';
|
|
},
|
|
/**
|
|
* 快捷操作区独立块样式(2.18): 背景/圆角/内边距, 全为默认(历史形态)时输出空串零变化
|
|
*/
|
|
actsBlockStyle() {
|
|
const c = this.c;
|
|
const bg = String(c.actsBlockBg || '').trim();
|
|
const radius = num(c.actsBlockRadius, 0);
|
|
const pad = num(c.actsBlockPad, 0);
|
|
const style = {};
|
|
if (bg) style.background = bg;
|
|
if (radius > 0) style.borderRadius = px2rpx(radius) + 'rpx';
|
|
if (pad > 0) style.padding = px2rpx(pad) + 'rpx';
|
|
return this.$util.objToStyle(style);
|
|
},
|
|
/** 资料行让位: 操作区在上方时由操作区让位, 资料行不再重复位移 */
|
|
rowsClearStyle() {
|
|
return this.actsAbove ? {} : this.cornerClearStyle;
|
|
},
|
|
detailBtnStyle() {
|
|
// 发送名片大按钮: 纯色主题实心(2026-10-22 参考图定稿, 不再用渐变);
|
|
// 高度 104rpx(用户反馈: 比触达标准 80rpx 加高一档, 参考图观感)
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
return this.$util.objToStyle({
|
|
background: theme,
|
|
height: '95rpx',
|
|
borderRadius: px2rpx(CardTokens.radius.pill) + 'rpx',
|
|
});
|
|
},
|
|
emptyBtnStyle() {
|
|
return this.$util.objToStyle({
|
|
background: CardTokens.color.primary,
|
|
height: px2rpx(CardTokens.touch.btnHeight) + 'rpx',
|
|
borderRadius: px2rpx(CardTokens.radius.pill) + 'rpx',
|
|
padding: '0 ' + px2rpx(CardTokens.space.xxl) + 'rpx',
|
|
});
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
// 模板无法访问模块导入, 需挂到实例(list.vue 同款写法); 头像缺图时显示姓氏首字
|
|
initialOf,
|
|
/** 资料行图标(开关关时退化为文字标签; field 无字形同样退化) */
|
|
rowIcon(row) {
|
|
return flagOn(this.c.showRowIcons, true) ? rowIconFor(row && row.field) : '';
|
|
},
|
|
/** 资料行 CSS 描边图标(2.17.1): 邮箱=信封 / 网站=线框地球, 同受行图标开关 */
|
|
rowCssIcon(row) {
|
|
return flagOn(this.c.showRowIcons, true) ? rowCssIconFor(row && row.field) : '';
|
|
},
|
|
/** 资料行 CSS 图标颜色: 跟随 labelColor(与 iconfont 行图标同色口径) */
|
|
rowCssColor() {
|
|
return this.c.labelColor || CardTokens.color.textLabel;
|
|
},
|
|
rowCssBorderStyle() {
|
|
return this.$util.objToStyle({ borderColor: this.rowCssColor() });
|
|
},
|
|
rowCssFillStyle() {
|
|
return this.$util.objToStyle({ background: this.rowCssColor() });
|
|
},
|
|
/** 资料行是否可点: 行点击开关 + 服务端 href 派生得出动作 */
|
|
rowTapable(row) {
|
|
return flagOn(this.c.rowTap, true) && !!rowActOf(row);
|
|
},
|
|
onRowTap(row) {
|
|
const act = rowActOf(row);
|
|
if (act) this.$emit('row-act', act);
|
|
},
|
|
onAct(act) {
|
|
this.$emit('act', act);
|
|
},
|
|
/* ---------- 分享名片抽屉(「发送名片」弹出; 版式/逻辑与精选名片 show 完全同款) ---------- */
|
|
openCardShare() {
|
|
this.showShare = true;
|
|
},
|
|
closeShare() {
|
|
this.showShare = false;
|
|
},
|
|
copyCardLink() {
|
|
const url = (this.card && this.card.wap_url) || '';
|
|
if (!url) {
|
|
uni.showToast({ title: '名片链接未返回,请稍后重试', icon: 'none' });
|
|
return;
|
|
}
|
|
uni.setClipboardData({
|
|
data: url,
|
|
success: () => uni.showToast({ title: '链接已复制', icon: 'success' }),
|
|
});
|
|
},
|
|
// H5: 优先 navigator.share(移动浏览器), 不支持则复制链接兜底
|
|
h5CardShare() {
|
|
// #ifdef H5
|
|
const url = (this.card && this.card.wap_url) || '';
|
|
if (navigator && typeof navigator.share === 'function' && url) {
|
|
navigator.share({
|
|
title: ((this.card && this.card.name) || '我的名片') + '的名片',
|
|
url: url
|
|
}).catch(() => {});
|
|
return;
|
|
}
|
|
// #endif
|
|
this.copyCardLink();
|
|
},
|
|
// 小程序/鸿蒙: 下载二维码后存相册(长按图片也可存, 抽屉底部有提示)
|
|
saveCardQr() {
|
|
const qrUrl = (this.card && this.card.qr_url) || '';
|
|
if (!qrUrl) return;
|
|
uni.downloadFile({
|
|
url: this.$util.img(qrUrl),
|
|
success: res => {
|
|
if (res.statusCode !== 200 || !res.tempFilePath) {
|
|
uni.showToast({ title: '二维码下载失败', icon: 'none' });
|
|
return;
|
|
}
|
|
uni.saveImageToPhotosAlbum({
|
|
filePath: res.tempFilePath,
|
|
success: () => uni.showToast({ title: '已保存到相册', icon: 'success' }),
|
|
fail: () => uni.showToast({ title: '保存失败,请授权相册权限', icon: 'none' }),
|
|
});
|
|
},
|
|
fail: () => uni.showToast({ title: '二维码下载失败', icon: 'none' }),
|
|
});
|
|
},
|
|
// 分享抽屉二维码: 点击放大预览(预览页长按必出「识别图中二维码」菜单, 比 image 直接长按更可靠)
|
|
previewQr() {
|
|
const url = (this.card && this.card.qr_url) || '';
|
|
if (!url) return;
|
|
const src = this.$util.img(url);
|
|
uni.previewImage({ urls: [src], current: src });
|
|
},
|
|
/** 二维码点击 → 预览名片(进详情页; qrTapPreview 开关控制, 默认开) */
|
|
onQrTap() {
|
|
if (flagOn(this.c.qrTapPreview, true)) this.$emit('detail', this.card);
|
|
},
|
|
onSend() {
|
|
this.$emit('send', this.card);
|
|
},
|
|
/** 每按钮自定义图标图片(2.18 媒体库, 优先级最高; acts 已合并 cfgImg) */
|
|
actImgOf(act) {
|
|
return String((act && act.cfgImg) || '').trim() || String(actIconCfgOf(this.c.actIcons, act && act.type).img || '').trim();
|
|
},
|
|
/**
|
|
* 素材库图标(2.19): acts 已合并 cfgKey(iconKey), 库缺 key 返回空串回落线稿档
|
|
*/
|
|
actLibOf(act) {
|
|
return String((act && act.cfgKey) || '').trim();
|
|
},
|
|
/** 素材库图标背景(实时配色: color 空回落 actIconColor 四级口径) */
|
|
actLibStyle(act) {
|
|
return this.$util.objToStyle({ backgroundImage: libIconBg(this.actLibOf(act), this.actIconColor(act)) });
|
|
},
|
|
/** 宫格 SVG 线稿(2.18.1): 与 wap detail 同源, 素材库/媒体库优先时不再进入 */
|
|
actSvgOf(act) {
|
|
return !this.actImgOf(act) && !this.actLibOf(act) && !!WAP_LINE_ICONS[String((act && act.type) || '')];
|
|
},
|
|
/**
|
|
* 图标前景色: act 合并的每按钮 color > detail 同源固定色(wx 微信绿/save 通讯录橙)
|
|
* > theme 档主题色 > preset 档预设深字
|
|
*/
|
|
actIconColor(act) {
|
|
const custom = String((act && act.cfgColor) || '').trim();
|
|
if (custom) return custom;
|
|
const ico = WAP_LINE_ICONS[String((act && act.type) || '')];
|
|
if (ico && ico.color) return ico.color;
|
|
if (this.gridColorMode === 'theme') {
|
|
return (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
}
|
|
const preset = ACT_GRID_PRESETS[(act && act.type) || ''] || ACT_GRID_PRESET_FALLBACK;
|
|
return preset.fg;
|
|
},
|
|
/** SVG 线稿背景(data URI, 颜色内嵌) */
|
|
actSvgStyle(act) {
|
|
return this.$util.objToStyle({ backgroundImage: svgLineIconBg(act && act.type, this.actIconColor(act)) });
|
|
},
|
|
actInitialOf(act) {
|
|
return String((act && act.label) || '·').charAt(0);
|
|
},
|
|
/** 宫格配色(每按钮 bg 覆盖 / preset 多彩预设 / theme 主题渐变) —— 带参, 走 methods */
|
|
actGridIconStyle(act) {
|
|
// 每按钮自定义底色优先(2.18), 空回落 preset/theme 档(acts 已合并 cfgBg)
|
|
const cfgBg = String((act && act.cfgBg) || '').trim() || String(actIconCfgOf(this.c.actIcons, act && act.type).bg || '').trim();
|
|
if (cfgBg) return this.$util.objToStyle({ background: cfgBg });
|
|
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
|
|
if (this.gridColorMode === 'theme') {
|
|
// detail 同款浅主题渐变底(145deg, 12%→20% 主题色混白)
|
|
return this.$util.objToStyle({
|
|
background: 'linear-gradient(145deg, ' + (hexToRgba(theme, 0.12) || '#F2F3F5') + ', ' + (hexToRgba(theme, 0.2) || '#F2F3F5') + ')',
|
|
});
|
|
}
|
|
const preset = ACT_GRID_PRESETS[(act && act.type) || ''] || ACT_GRID_PRESET_FALLBACK;
|
|
return this.$util.objToStyle({ background: preset.bg });
|
|
},
|
|
/** 首字兜底字色(未知类型), 与每按钮 color/固定色同口径 */
|
|
actGridGlyphStyle(act) {
|
|
return this.$util.objToStyle({ color: this.actIconColor(act) });
|
|
},
|
|
actGridLabelStyle() {
|
|
return this.$util.objToStyle({
|
|
color: this.c.labelColor || CardTokens.color.textSub,
|
|
fontSize: px2rpx(num(this.c.actSize, 12)) + 'rpx',
|
|
});
|
|
},
|
|
/** 复制按钮: 复用 row-act 的 copy 分支(rowTap 关闭时仍可独立复制) */
|
|
onCopyRow(row) {
|
|
this.$emit('row-act', { type: 'copy', value: row.value });
|
|
},
|
|
onDetail() {
|
|
this.$emit('detail', this.card);
|
|
},
|
|
onEmptyAction() {
|
|
this.$emit('empty-action');
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.card-mini {
|
|
width: 100%;
|
|
|
|
/* 顶带+白卡同容器: 顶带 top/bottom 拉伸 → 高度自适应白卡,
|
|
弧线始终距白卡底 88rpx(2026-10-23 参考图定稿, 与 show 同口径) */
|
|
.mini-card-wrap {
|
|
position: relative;
|
|
margin-top: 40rpx;
|
|
}
|
|
|
|
/* 主题色顶带: 从露沿处拉伸, 底端距白卡底 88rpx; 顶部直角, 底部 28rpx 小圆弧 */
|
|
.mini-band {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
top: -40rpx;
|
|
bottom: 88rpx;
|
|
height: auto;
|
|
border-radius: 0 0 28rpx 28rpx;
|
|
}
|
|
|
|
.mini-card {
|
|
position: relative;
|
|
overflow: hidden;
|
|
width: auto;
|
|
margin: 0 24rpx;
|
|
box-sizing: border-box;
|
|
z-index: 1;
|
|
|
|
.mini-badge-slot {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
z-index: 4;
|
|
}
|
|
|
|
.mini-cover {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 0;
|
|
}
|
|
|
|
.mini-cover-scrim {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(15, 23, 42, 0.45);
|
|
z-index: 1;
|
|
}
|
|
|
|
.mini-gradient {
|
|
/* 流内饰条(2026-10-22 参考图定稿, show 的 .card-grad-bar 同款):
|
|
不再 absolute 贴死卡顶, 改为排在头像行上方并与其拉开 28rpx */
|
|
position: relative;
|
|
z-index: 2;
|
|
width: 100%;
|
|
height: 14rpx;
|
|
border-radius: 8rpx;
|
|
margin-bottom: 28rpx;
|
|
}
|
|
|
|
.mini-logo {
|
|
position: absolute;
|
|
right: 24rpx;
|
|
top: 24rpx;
|
|
width: 64rpx;
|
|
height: 64rpx;
|
|
z-index: 3;
|
|
}
|
|
|
|
.mini-head {
|
|
position: relative;
|
|
z-index: 2;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.mini-avatar {
|
|
flex-shrink: 0;
|
|
width: 104rpx;
|
|
height: 104rpx;
|
|
border-radius: 50%;
|
|
overflow: hidden;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.avatar-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
}
|
|
|
|
.avatar-initial {
|
|
font-size: 42rpx;
|
|
font-weight: 700;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
|
|
/* theme 渐变头部档: 白描边白底字头像更贴合深底(仅 theme 档, plain 零变化) */
|
|
.mini-headtheme & {
|
|
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.10);
|
|
}
|
|
}
|
|
|
|
/* 头部·主题渐变整块档(2.17): 通铺卡边 + 装饰圆; 颜色固定白透明度, 任意主题色可见
|
|
圆角只给底部 —— 顶部贴卡边, 避免与卡片圆角叠加出双圆角 */
|
|
.mini-headtheme {
|
|
position: relative;
|
|
z-index: 2;
|
|
overflow: hidden;
|
|
border-radius: 0 0 16rpx 16rpx;
|
|
|
|
.headtheme-decor {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
background: rgba(255, 255, 255, 0.12);
|
|
pointer-events: none;
|
|
|
|
&--big {
|
|
width: 240rpx;
|
|
height: 240rpx;
|
|
right: -60rpx;
|
|
top: -80rpx;
|
|
}
|
|
|
|
&--small {
|
|
width: 120rpx;
|
|
height: 120rpx;
|
|
left: -40rpx;
|
|
bottom: -50rpx;
|
|
background: rgba(255, 255, 255, 0.08);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 资料区标题(2.17): 主题色竖条(尺寸内联) + 600 字重标题 */
|
|
.mini-rows-title {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 16rpx;
|
|
|
|
.rows-title-bar {
|
|
flex-shrink: 0;
|
|
width: 8rpx;
|
|
height: 28rpx;
|
|
border-radius: 4rpx;
|
|
margin-right: 12rpx;
|
|
}
|
|
}
|
|
|
|
/* 复制按钮(2.17): 浅底主题色小按钮(色内联), 不挤压资料值换行 */
|
|
.row-copy {
|
|
flex-shrink: 0;
|
|
margin-left: 16rpx;
|
|
padding: 4rpx 20rpx;
|
|
border-radius: 999rpx;
|
|
font-size: 22rpx;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
/* 快捷操作·图标宫格档(2.17): 均分多列, 图标浅底块 88rpx
|
|
列宽由内联 gridItemWidth 动态给出(5 动作 20% / 4 及以下 25%), 此处为兜底 */
|
|
.mini-acts-grid {
|
|
position: relative;
|
|
z-index: 2;
|
|
margin-top: 24rpx;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
|
|
.act-grid-item {
|
|
width: 25%;
|
|
box-sizing: border-box;
|
|
padding: 8rpx 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
|
|
.act-grid-icon {
|
|
width: 88rpx;
|
|
height: 88rpx;
|
|
border-radius: 24rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
/* SVG 线稿图标(2.18.1): data URI 背景呈现, 与 wap detail 同源 */
|
|
.act-grid-svg {
|
|
width: 44rpx;
|
|
height: 44rpx;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
background-size: contain;
|
|
}
|
|
|
|
/* 自定义图标图片(2.18): 铺满图标块, 圆角继承 */
|
|
.act-grid-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
border-radius: inherit;
|
|
}
|
|
|
|
.act-grid-initial {
|
|
font-size: 36rpx;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
|
|
.act-grid-label {
|
|
margin-top: 12rpx;
|
|
line-height: 1.4;
|
|
}
|
|
}
|
|
}
|
|
|
|
.mini-head-info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
margin-left: 24rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.name-row {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.mini-name {
|
|
font-size: 34rpx;
|
|
font-weight: 700;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.mini-badge {
|
|
flex-shrink: 0;
|
|
margin-left: 12rpx;
|
|
font-size: 18rpx;
|
|
color: #ffffff;
|
|
padding: 2rpx 12rpx;
|
|
border-radius: 8rpx;
|
|
}
|
|
}
|
|
|
|
.mini-card-title {
|
|
font-size: 26rpx;
|
|
margin-top: 6rpx;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.mini-sub {
|
|
font-size: 24rpx;
|
|
margin-top: 6rpx;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
}
|
|
}
|
|
|
|
.mini-rows {
|
|
position: relative;
|
|
z-index: 2;
|
|
margin-top: 24rpx;
|
|
|
|
.mini-row {
|
|
display: flex;
|
|
line-height: 2;
|
|
|
|
/* CSS 描边图标容器(2.17.1): 与 iconfont 图标列/文字标签列同宽 96rpx, 值列左缘对齐 */
|
|
.row-css-wrap {
|
|
flex-shrink: 0;
|
|
width: 96rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
align-self: center;
|
|
}
|
|
|
|
/* 行内缩小版信封/地球(宫格同构图形, 边框色内联) */
|
|
.css-ico-mail--row {
|
|
width: 30rpx;
|
|
height: 22rpx;
|
|
border-width: 3rpx;
|
|
border-radius: 4rpx;
|
|
|
|
.css-ico-mail-flap {
|
|
width: 10rpx;
|
|
height: 10rpx;
|
|
border-width: 3rpx;
|
|
top: -2rpx;
|
|
}
|
|
}
|
|
|
|
.css-ico-web--row {
|
|
width: 26rpx;
|
|
height: 26rpx;
|
|
border-width: 3rpx;
|
|
|
|
.css-ico-web-h {
|
|
height: 3rpx;
|
|
}
|
|
|
|
.css-ico-web-v {
|
|
width: 10rpx;
|
|
border-width: 3rpx;
|
|
}
|
|
}
|
|
|
|
.row-label {
|
|
flex-shrink: 0;
|
|
width: 96rpx;
|
|
font-size: 24rpx;
|
|
}
|
|
|
|
/* 图标列与文字标签列同宽, 保证值列左缘对齐(参考图口径) */
|
|
.row-icon {
|
|
flex-shrink: 0;
|
|
width: 96rpx;
|
|
text-align: center;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
.row-value {
|
|
flex: 1;
|
|
font-size: 24rpx;
|
|
word-break: break-all;
|
|
}
|
|
|
|
/* 可点行: hover-class 已给按压反馈, 此处仅标识可点(光标语义小程序无效, 保留 H5) */
|
|
&.row-tappable {
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
|
|
.row-toggle {
|
|
margin-top: 8rpx;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
|
|
.toggle-text {
|
|
font-size: 22rpx;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
}
|
|
|
|
.mini-acts {
|
|
position: relative;
|
|
z-index: 2;
|
|
margin-top: 24rpx;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
|
|
.act-chip {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-sizing: border-box;
|
|
/* 小胶囊(2026-10-22 定稿): 显式给高/内距/圆角(内联只出背景色, 尺寸走本类);
|
|
72rpx 触达标准, 按用户反馈放大一档 */
|
|
height: 60rpx;
|
|
padding: 0 32rpx;
|
|
margin: 0 16rpx 16rpx 0;
|
|
border-radius: 36rpx;
|
|
|
|
.act-text {
|
|
font-size: 26rpx;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
}
|
|
|
|
.mini-qr {
|
|
position: relative;
|
|
z-index: 2;
|
|
margin-top: 24rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
|
|
/* rows/bottom 档(流内块级)水平居中; corner/head 档不带本类, 定位不受影响 */
|
|
&.mini-qr-center {
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
}
|
|
|
|
/* 块尺寸由 qrBlockStyle 内联给出(自定义/档位), 图片填满内容盒 */
|
|
.qr-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
}
|
|
|
|
.qr-tip {
|
|
font-size: 22rpx;
|
|
margin-top: 12rpx;
|
|
}
|
|
|
|
/* head 档: 头部第三段(头像|信息|二维码), 不占额外垂直节奏 */
|
|
&.mini-qr-head {
|
|
margin-top: 0;
|
|
margin-left: 20rpx;
|
|
flex-shrink: 0;
|
|
align-self: center;
|
|
|
|
.qr-tip {
|
|
font-size: 20rpx;
|
|
margin-top: 8rpx;
|
|
}
|
|
}
|
|
|
|
/* corner 档: 右上角浮层(外观衬底由 qrStyle 内联决定, 此处只定位于层次) */
|
|
&.mini-qr-corner {
|
|
position: absolute;
|
|
top: 20rpx;
|
|
right: 20rpx;
|
|
z-index: 3;
|
|
margin-top: 0;
|
|
box-shadow: 0 4rpx 16rpx rgba(15, 23, 42, 0.12);
|
|
}
|
|
}
|
|
|
|
/* corner 档: 头部右侧让位由 cornerHeadStyle 按浮层实际宽度动态给出
|
|
(静态 180rpx 在自定义大尺寸 qrSize 下不足, 已废弃); WXSS 不支持 calc() */
|
|
&.qr-at-corner {
|
|
.mini-head {
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
}
|
|
|
|
/* 发名片主按钮(名片详情页 send-bar 同款观感) */
|
|
.mini-send {
|
|
position: relative;
|
|
z-index: 2;
|
|
margin-top: 24rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.send-text {
|
|
font-size: 30rpx;
|
|
font-weight: 600;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 发送名片大按钮: 白卡外下方(2026-10-23 参考图定稿),
|
|
与精选名片「发名片」同款布局; 左右 24rpx 与白卡对齐 */
|
|
.mini-detail {
|
|
position: relative;
|
|
z-index: 2;
|
|
margin: 24rpx 24rpx 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
/* 小程序端为 <button open-type="share">: 去掉原生默认灰底/边框, 背景由 detailBtnStyle 内联主题色给出 */
|
|
padding: 0;
|
|
border: none;
|
|
background-color: transparent;
|
|
line-height: normal;
|
|
font-size: 26rpx;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
.detail-text {
|
|
font-size: 26rpx;
|
|
font-weight: 600;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
|
|
/* 空态 */
|
|
.mini-empty {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 48rpx 24rpx;
|
|
|
|
.empty-icon {
|
|
font-size: 64rpx;
|
|
}
|
|
|
|
.empty-tip {
|
|
font-size: 24rpx;
|
|
margin-top: 16rpx;
|
|
text-align: center;
|
|
}
|
|
|
|
.empty-btn {
|
|
margin-top: 28rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.empty-btn-text {
|
|
font-size: 26rpx;
|
|
font-weight: 600;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 骨架屏 */
|
|
.mini-skeleton {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
|
|
.sk-row {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.sk-avatar {
|
|
width: 104rpx;
|
|
height: 104rpx;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.sk-col {
|
|
flex: 1;
|
|
margin-left: 24rpx;
|
|
}
|
|
}
|
|
|
|
.sk-btn {
|
|
height: 80rpx;
|
|
border-radius: 999rpx;
|
|
}
|
|
}
|
|
|
|
.sk {
|
|
background: linear-gradient(90deg, #f2f3f5 25%, #e8eaee 37%, #f2f3f5 63%);
|
|
background-size: 400rpx 100%;
|
|
animation: sk-shimmer 1.2s linear infinite;
|
|
border-radius: 8rpx;
|
|
|
|
&.sk-line {
|
|
height: 28rpx;
|
|
}
|
|
}
|
|
|
|
/* 入场动效(逐项延迟由父组件传 animation-delay) */
|
|
.fade-up {
|
|
animation: card-fade-up 240ms ease both;
|
|
}
|
|
|
|
/* 按压反馈(芯片/按钮/空态按钮共用) */
|
|
.btn-press {
|
|
opacity: 0.72;
|
|
transform: scale(0.98);
|
|
}
|
|
|
|
/* CSS 描边图标(2.17.1): iconfont 无邮件/网站字形, 纯 view 边框绘制,
|
|
颜色由内联 style 跟随 preset/theme 配色档(H5+小程序通用)。
|
|
顶层定义 —— 宫格(88rpx 图标块内)与资料行(--row 缩小版)共用同一套图形 */
|
|
.css-ico-mail {
|
|
position: relative;
|
|
width: 44rpx;
|
|
height: 32rpx;
|
|
border: 4rpx solid #B0B4BC;
|
|
border-radius: 6rpx;
|
|
box-sizing: border-box;
|
|
|
|
/* 封面折角: 只留左+下边的方块旋转 -45° 成 V 形折线 */
|
|
.css-ico-mail-flap {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: -2rpx;
|
|
width: 16rpx;
|
|
height: 16rpx;
|
|
border-left: 4rpx solid #B0B4BC;
|
|
border-bottom: 4rpx solid #B0B4BC;
|
|
transform: translateX(-50%) rotate(-45deg);
|
|
}
|
|
}
|
|
|
|
.css-ico-web {
|
|
position: relative;
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
border: 4rpx solid #B0B4BC;
|
|
border-radius: 50%;
|
|
box-sizing: border-box;
|
|
overflow: hidden;
|
|
|
|
/* 赤道横线(色由内联 background 给出) */
|
|
.css-ico-web-h {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 50%;
|
|
width: 100%;
|
|
height: 4rpx;
|
|
transform: translateY(-50%);
|
|
}
|
|
|
|
/* 经线椭圆: 左右双边框 + 椭圆圆角 */
|
|
.css-ico-web-v {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: -2rpx;
|
|
bottom: -2rpx;
|
|
width: 14rpx;
|
|
transform: translateX(-50%);
|
|
border-left: 4rpx solid #B0B4BC;
|
|
border-right: 4rpx solid #B0B4BC;
|
|
border-radius: 50%;
|
|
}
|
|
}
|
|
|
|
@keyframes sk-shimmer {
|
|
0% {
|
|
background-position: -200rpx 0;
|
|
}
|
|
|
|
100% {
|
|
background-position: 200rpx 0;
|
|
}
|
|
}
|
|
|
|
@keyframes card-fade-up {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(12rpx);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform: none;
|
|
}
|
|
}
|
|
|
|
/* 分享名片抽屉(「发送名片」弹出; 与精选名片 show 同款, 复刻 detail.vue share-sheet) */
|
|
.cs-mask {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
z-index: 100;
|
|
}
|
|
|
|
.cs-sheet {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: #ffffff;
|
|
border-radius: 24rpx 24rpx 0 0;
|
|
padding: 20rpx 32rpx 40rpx;
|
|
z-index: 101;
|
|
transform: translateY(100%);
|
|
transition: transform 0.25s;
|
|
|
|
&.cs-sheet-show {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.ss-bar {
|
|
width: 36rpx;
|
|
height: 4rpx;
|
|
border-radius: 2rpx;
|
|
background-color: #e3e7ee;
|
|
margin: 0 auto 20rpx;
|
|
}
|
|
|
|
.ss-title {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #1a1f36;
|
|
text-align: center;
|
|
}
|
|
|
|
.ss-sub {
|
|
font-size: 24rpx;
|
|
color: #9aa4b8;
|
|
text-align: center;
|
|
margin: 8rpx 0 24rpx;
|
|
}
|
|
|
|
.ss-qr-box {
|
|
display: flex;
|
|
justify-content: center;
|
|
margin-bottom: 20rpx;
|
|
|
|
.ss-qr {
|
|
width: 320rpx;
|
|
height: 320rpx;
|
|
}
|
|
}
|
|
|
|
.ss-link {
|
|
font-size: 22rpx;
|
|
color: #9aa4b8;
|
|
background-color: #f6f7f9;
|
|
border-radius: 8rpx;
|
|
padding: 14rpx 20rpx;
|
|
margin-bottom: 24rpx;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.ss-btns {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
|
|
.ss-btn {
|
|
flex: 1;
|
|
height: 80rpx;
|
|
line-height: 80rpx;
|
|
text-align: center;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
border: 1rpx solid #dcdfe6;
|
|
border-radius: 12rpx;
|
|
margin: 0;
|
|
padding: 0;
|
|
background-color: transparent;
|
|
overflow: visible;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
& + .ss-btn {
|
|
margin-left: 20rpx;
|
|
}
|
|
}
|
|
|
|
/* 主按钮颜色走 shareBtnStyle 内联(主题色), 此处只兜底默认蓝 */
|
|
.ss-btn-main {
|
|
background-color: #119dff;
|
|
border-color: #119dff;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
|
|
.ss-tip {
|
|
text-align: center;
|
|
font-size: 22rpx;
|
|
color: #b8c0cc;
|
|
margin-top: 20rpx;
|
|
}
|
|
}
|
|
</style>
|