167 lines
5.9 KiB
PHP
167 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Service\wx;
|
|
|
|
use App\BaseApp\BaseWxService;
|
|
use App\Models\business\WxTemplateModel;
|
|
use App\Models\business\WxUserModel;
|
|
use App\Models\WxAppModel;
|
|
use App\Service\business\WxCardSchemeService;
|
|
use App\Service\business\WxTemplatePresetService;
|
|
use App\Service\business\WxTemplateSchemaService;
|
|
|
|
/**
|
|
* 小程序主题下发(免授权)
|
|
*
|
|
* 小程序启动时拉一次并缓存本地,拿不到就用内置兜底主题——
|
|
* 主题接口挂了不能导致小程序白屏。
|
|
*/
|
|
class WxThemeService extends BaseWxService
|
|
{
|
|
protected bool $needLogin = false;
|
|
|
|
/**
|
|
* 当前生效主题
|
|
*
|
|
* 优先级:显式 code > 登录经销商专属 template_code > 品牌配置 template_code
|
|
* > 该品牌默认模板 > 通用默认模板 > 内置预设
|
|
*/
|
|
public function current(string $code = ''): array
|
|
{
|
|
$appCode = WxAppService::getInstance()->currentCode();
|
|
$template = null;
|
|
|
|
if ($code !== '') {
|
|
$template = WxTemplateModel::where('code', $code)->where('deleted_at', 0)->where('status', 0)->first();
|
|
}
|
|
// 已登录经销商:可用专属模板覆盖品牌默认(未登录则 userInfo 为空,跳过)
|
|
if (empty($template) && (int) ($this->userInfo['is_p'] ?? 0) === 1) {
|
|
$userCode = trim((string) ($this->userInfo['template_code'] ?? ''));
|
|
if ($userCode === '' && !empty($this->userInfo['id'])) {
|
|
$userCode = (string) (WxUserModel::where('id', $this->userInfo['id'])
|
|
->where('deleted_at', 0)
|
|
->value('template_code') ?? '');
|
|
}
|
|
if ($userCode !== '') {
|
|
$template = WxTemplateModel::where('code', $userCode)
|
|
->where('deleted_at', 0)->where('status', 0)->first();
|
|
}
|
|
}
|
|
if (empty($template) && $appCode !== '') {
|
|
$bound = (string) (WxAppModel::where('code', $appCode)
|
|
->where('deleted_at', 0)
|
|
->value('template_code') ?? '');
|
|
if ($bound !== '') {
|
|
$template = WxTemplateModel::where('code', $bound)->where('deleted_at', 0)->where('status', 0)->first();
|
|
}
|
|
}
|
|
if (empty($template) && $appCode !== '') {
|
|
$template = WxTemplateModel::where('app_code', $appCode)
|
|
->where('is_default', 1)->where('deleted_at', 0)->where('status', 0)->first();
|
|
}
|
|
if (empty($template)) {
|
|
$template = WxTemplateModel::where('app_code', '')
|
|
->where('is_default', 1)->where('deleted_at', 0)->where('status', 0)->first();
|
|
}
|
|
|
|
$schema = WxTemplateSchemaService::getInstance();
|
|
if (empty($template)) {
|
|
$preset = WxTemplatePresetService::getInstance()->all()[0] ?? [];
|
|
$tokens = $preset['tokens'] ?? [];
|
|
$layout = $preset['layout'] ?? [];
|
|
return $this->packTheme(
|
|
(string) ($preset['code'] ?? 'lux-champagne'),
|
|
(string) ($preset['name'] ?? '轻奢·香槟金'),
|
|
(string) ($preset['style_tag'] ?? '轻奢'),
|
|
0,
|
|
$tokens,
|
|
$layout,
|
|
$schema,
|
|
true,
|
|
);
|
|
}
|
|
|
|
$template = $template->toArray();
|
|
$tokens = is_array($template['tokens']) ? $template['tokens'] : [];
|
|
$layout = is_array($template['layout']) ? $template['layout'] : [];
|
|
return $this->packTheme(
|
|
(string) $template['code'],
|
|
(string) $template['name'],
|
|
(string) $template['style_tag'],
|
|
(int) $template['version'],
|
|
$tokens,
|
|
$layout,
|
|
$schema,
|
|
false,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 组装主题包:令牌 + 布局 + 本模板引用到的卡片方案
|
|
*/
|
|
private function packTheme(
|
|
string $code,
|
|
string $name,
|
|
string $styleTag,
|
|
int $version,
|
|
array $tokens,
|
|
array $layout,
|
|
WxTemplateSchemaService $schema,
|
|
bool $fallback,
|
|
): array {
|
|
return [
|
|
'code' => $code,
|
|
'name' => $name,
|
|
'style_tag' => $styleTag,
|
|
'version' => $version,
|
|
'tokens' => $tokens,
|
|
'layout' => $layout,
|
|
'css_vars' => $schema->toCssVariables($tokens),
|
|
'card_schemes' => WxCardSchemeService::mapByCodes($this->collectSchemeCodes($layout)),
|
|
'features' => [
|
|
'package_enabled' => WxAppService::getInstance()->packageEnabled(),
|
|
],
|
|
'fallback' => $fallback,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 从根 card_scheme、页级 pages.*.card_scheme、区块 props.card_scheme 收集引用
|
|
*
|
|
* @return array<int, string>
|
|
*/
|
|
private function collectSchemeCodes(array $layout): array
|
|
{
|
|
$codes = [];
|
|
if (!empty($layout['card_scheme'])) {
|
|
$codes[] = (string) $layout['card_scheme'];
|
|
}
|
|
foreach ((array) ($layout['pages'] ?? []) as $page) {
|
|
$pageScheme = (string) ($page['card_scheme'] ?? '');
|
|
if ($pageScheme !== '') {
|
|
$codes[] = $pageScheme;
|
|
}
|
|
foreach ((array) ($page['sections'] ?? []) as $section) {
|
|
$code = (string) ($section['props']['card_scheme'] ?? '');
|
|
if ($code !== '') {
|
|
$codes[] = $code;
|
|
}
|
|
}
|
|
}
|
|
return $codes;
|
|
}
|
|
|
|
/**
|
|
* 可选风格列表,用于小程序里让用户自己换肤
|
|
*/
|
|
public function gallery(): mixed
|
|
{
|
|
$appCode = WxAppService::getInstance()->currentCode();
|
|
return WxTemplateModel::where('deleted_at', 0)
|
|
->where('status', 0)
|
|
->when($appCode !== '', fn ($query) => $query->whereIn('app_code', ['', $appCode]))
|
|
->orderBy('sort', 'asc')
|
|
->get(['code', 'name', 'style_tag', 'preview']);
|
|
}
|
|
}
|