/** * 轮播配图注册表(前端唯一轮播视觉清单) * ------------------------------------------------------------ * 首页轮播卡 = 「后台下发的渐变底色 + 页面 CSS 装饰层 + 一张白色插画」: * · 底色 color —— 后台 `fc_banner.color`(可随时换季调整,装饰层是中性半透明白/深绿,不串色) * · 装饰层 —— `pages/index/index.vue` 的 `.home__banner-*`(圆环 / 远山 / 光晕 / 叶脉) * · 插画 —— `static/banners/` 下的白色透明 PNG,`tools/gen-banner-art.mjs` 生成 * 若后台给某条轮播配置了 `image`(整幅配图),前端直接铺满并隐藏装饰层。 */ export const BANNER_BASE = '/static/banners/' /** 3 套内置插画:二手包裹箱 / 公文包 / 上门小家(与 icon-svg.mjs 母版同源) */ export const BANNER_ART = ['banner-art-1.png', 'banner-art-2.png', 'banner-art-3.png'] /** 内置生态绿渐变(1/2/3 号,取自 uni.scss 主色家族),后台未配置颜色时按位置取用 */ export const BANNER_BG = [ 'linear-gradient(105deg, #00d26a 0%, #10b981 50%, #34d399 100%)', 'linear-gradient(105deg, #10b981 0%, #34d399 50%, #6ee7b7 100%)', 'linear-gradient(105deg, #059669 0%, #10b981 50%, #34d399 100%)', ] /** * 后台下发的底色是否「完整可用」。 * 只认**结构完整**的渐变:`linear-gradient(...)` / `radial-gradient(...)` 等, * 括号配平、至少两个色标(顶层含逗号)、以 `)` 收尾。 * 这样既能拦下历史暖色纯色(`#FF8A5B`),也能拦下被字段宽度**截断**的半截值 * (如 `linear-gradient(` / `linear-gradient(135deg`),避免出现「样式非法 → 卡片空白」。 * 顶层括号计数而非正则,是为了兼容 `rgba(24,165,135,.9)` 这类**色标内自带括号/逗号**的写法。 */ function isCompleteGradient(value) { const head = /^(repeating-)?(linear|radial|conic)-gradient\(/i.exec(value) if (!head || value.charAt(value.length - 1) !== ')') return false let depth = 1 // 渐变函数自身的左括号已在 head 内,先计入 let commas = 0 for (let i = head[0].length; i < value.length; i++) { const ch = value.charAt(i) if (ch === '(') depth++ else if (ch === ')') depth-- else if (ch === ',' && depth === 1) commas++ // 只数「渐变函数这一层」的逗号(色标分隔) } return depth === 0 && commas >= 1 } /** * 轮播底色:只信任后台下发的**完整渐变**,其余一律回落内置春绿渐变(105deg 亮绿→深绿)。 * 历史遗留的纯色值(如旧暖色 `#FF8A5B` / `#FFB86B` / `#FF6F61`)、空值、被截断的半截值 * 都会被视为「未配置」,保证后台数据没同步时首页也不会出现与新主题冲突的暖色或空白卡;文案固定用墨绿字,故换底色不会改坏可读性。 * 需要纯色时后台填 `linear-gradient(105deg, #00E070 0%, #00E070 100%)` 即可(亮绿面 + 前端墨绿字)。 */ export function bannerBg(banner, index = 0) { const color = String((banner && banner.color) || '').trim() if (isCompleteGradient(color)) return color return BANNER_BG[Math.abs(index) % BANNER_BG.length] } /** 第 i 条轮播的默认插画(按位置循环) */ export function bannerArtUrl(index = 0) { return BANNER_BASE + BANNER_ART[Math.abs(index) % BANNER_ART.length] } /** * 是否展示金色「价值点缀」。 * 规则:绿 = 平台与内容、金 = 价值与特权 —— 只有「直降 / 免费」这类价值主张才配金色。 */ export function bannerHasValue(index = 0) { return Math.abs(index) % BANNER_ART.length !== 2 } export default { BANNER_BASE, BANNER_ART, BANNER_BG, bannerArtUrl, bannerHasValue, bannerBg }