|
@@ -36,6 +36,15 @@ public class ApiSettingService {
|
|
|
@Value("${yoshop.base-url}")
|
|
@Value("${yoshop.base-url}")
|
|
|
private String baseUrl;
|
|
private String baseUrl;
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 对齐 PHP common\model\store\Setting::defaultData()。
|
|
|
|
|
+ * <p>PHP 的 getAll() 是 {@code resetOptions(defaultData, data)}:库内没有该项(或该项缺字段)时
|
|
|
|
|
+ * 用默认值补齐。Java 侧此前缺项一律返回空数组,导致客户端拿到
|
|
|
|
|
+ * {@code pageCategoryTemplate = []},分类页读 {@code setting.style} 得到 undefined,
|
|
|
|
|
+ * 三个模板组件都不渲染(页面空白)。这里只列公开设置项用到的字段。
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final Map<String, Map<String, Object>> DEFAULT_VALUES = buildDefaults();
|
|
|
|
|
+
|
|
|
// ---------------------------------------------------------------- 设置项
|
|
// ---------------------------------------------------------------- 设置项
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -54,6 +63,16 @@ public class ApiSettingService {
|
|
|
return decoded == null ? new ArrayList<>() : decoded;
|
|
return decoded == null ? new ArrayList<>() : decoded;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 读取设置项并按 PHP 默认值补齐(对应 getAll() 里的 resetOptions(defaultData, data))。
|
|
|
|
|
+ * 用于需要向客户端暴露的公开设置项。
|
|
|
|
|
+ */
|
|
|
|
|
+ public Object getItemWithDefaults(String key) {
|
|
|
|
|
+ Object actual = getItem(key);
|
|
|
|
|
+ Map<String, Object> defaults = DEFAULT_VALUES.get(key);
|
|
|
|
|
+ return defaults == null ? actual : mergeDefaults(actual, defaults);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 商城公共设置(仅暴露可公开项),对齐 PHP Setting::getPublic:
|
|
* 商城公共设置(仅暴露可公开项),对齐 PHP Setting::getPublic:
|
|
|
* appTheme / pageCategoryTemplate / points / recharge / register / customer。
|
|
* appTheme / pageCategoryTemplate / points / recharge / register / customer。
|
|
@@ -61,15 +80,17 @@ public class ApiSettingService {
|
|
|
public Map<String, Object> getPublicSetting() {
|
|
public Map<String, Object> getPublicSetting() {
|
|
|
Map<String, Object> data = new LinkedHashMap<>();
|
|
Map<String, Object> data = new LinkedHashMap<>();
|
|
|
// 店铺页面风格设置:PHP 取 getItem(app_theme)['data']
|
|
// 店铺页面风格设置:PHP 取 getItem(app_theme)['data']
|
|
|
- Object appThemeItem = getItem("app_theme");
|
|
|
|
|
|
|
+ Object appThemeItem = getItemWithDefaults("app_theme");
|
|
|
Object appTheme = appThemeItem instanceof Map<?, ?> map ? map.get("data") : null;
|
|
Object appTheme = appThemeItem instanceof Map<?, ?> map ? map.get("data") : null;
|
|
|
data.put("appTheme", appTheme);
|
|
data.put("appTheme", appTheme);
|
|
|
- data.put("pageCategoryTemplate", getItem("page_category_template"));
|
|
|
|
|
- data.put("points", pick(getItem("points"), "points_name", "describe"));
|
|
|
|
|
- data.put("recharge", pick(getItem("recharge"), "is_entrance", "is_custom", "describe"));
|
|
|
|
|
- data.put("register", pick(getItem("register"),
|
|
|
|
|
|
|
+ data.put("pageCategoryTemplate", getItemWithDefaults("page_category_template"));
|
|
|
|
|
+ data.put("points", pickCamel(getItemWithDefaults("points"), "points_name", "describe"));
|
|
|
|
|
+ data.put("recharge", pickCamel(getItemWithDefaults("recharge"),
|
|
|
|
|
+ "is_entrance", "is_custom", "describe"));
|
|
|
|
|
+ data.put("register", pick(getItemWithDefaults("register"),
|
|
|
"registerMethod", "isManualBind", "isOauthMpweixin", "isOauthMobileMpweixin"));
|
|
"registerMethod", "isManualBind", "isOauthMpweixin", "isOauthMobileMpweixin"));
|
|
|
- data.put("customer", pick(getItem("customer"), "enabled", "provider", "config"));
|
|
|
|
|
|
|
+ data.put("customer", pick(getItemWithDefaults("customer"),
|
|
|
|
|
+ "enabled", "provider", "config"));
|
|
|
return data;
|
|
return data;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -119,6 +140,131 @@ public class ApiSettingService {
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------- 工具
|
|
// ---------------------------------------------------------------- 工具
|
|
|
|
|
|
|
|
|
|
+ /** 对齐 PHP common\model\store\Setting::defaultData(),只保留公开设置项用到的字段 */
|
|
|
|
|
+ private static Map<String, Map<String, Object>> buildDefaults() {
|
|
|
|
|
+ Map<String, Map<String, Object>> all = new LinkedHashMap<>();
|
|
|
|
|
+ // 店铺页面风格设置(PHP getAppTheme 取这里的 data 字段)
|
|
|
|
|
+ all.put("app_theme", kv(
|
|
|
|
|
+ "mode", 10,
|
|
|
|
|
+ "themeTemplateIdx", 0,
|
|
|
|
|
+ "data", kv(
|
|
|
|
|
+ "gradualChange", 1,
|
|
|
|
|
+ "mainBg", "#fa2209",
|
|
|
|
|
+ "mainBg2", "#ff6335",
|
|
|
|
|
+ "mainText", "#ffffff",
|
|
|
|
|
+ "viceBg", "#ffb100",
|
|
|
|
|
+ "viceBg2", "#ffb900",
|
|
|
|
|
+ "viceText", "#ffffff")));
|
|
|
|
|
+ // 分类页模板:style=30 即「分类+商品」,前端按它选择渲染哪个组件
|
|
|
|
|
+ all.put("page_category_template", kv(
|
|
|
|
|
+ "style", 30,
|
|
|
|
|
+ "shareTitle", "全部分类",
|
|
|
|
|
+ "showAddCart", true,
|
|
|
|
|
+ "cartStyle", 1));
|
|
|
|
|
+ // 积分设置
|
|
|
|
|
+ all.put("points", kv(
|
|
|
|
|
+ "pointsName", "积分",
|
|
|
|
|
+ "describe", "1. 积分不可兑现、不可转让, 仅可在本平台使用。\n"
|
|
|
|
|
+ + "2. 您在本平台参加特定活动也可使用积分, 详细使用规则以具体活动时的规则为准。\n"
|
|
|
|
|
+ + "3. 积分的数值精确到个位(小数点后全部舍弃, 不进行四舍五入)。\n"
|
|
|
|
|
+ + "4. 每次购物赠送的积分将在订单完成后(包括退换货流程完成)到账。\n"));
|
|
|
|
|
+ // 用户充值设置
|
|
|
|
|
+ all.put("recharge", kv(
|
|
|
|
|
+ "isEntrance", 1,
|
|
|
|
|
+ "isCustom", 1,
|
|
|
|
|
+ "describe", "1. 账户充值仅限微信在线方式支付,充值金额实时到账;\n"
|
|
|
|
|
+ + "2. 账户充值套餐赠送的金额即时到账;\n"
|
|
|
|
|
+ + "3. 账户余额有效期:自充值日起至用完即止;\n"
|
|
|
|
|
+ + "4. 若有其它疑问,可拨打客服电话400-000-1234"));
|
|
|
|
|
+ // 账户注册设置
|
|
|
|
|
+ all.put("register", kv(
|
|
|
|
|
+ "registerMethod", 10,
|
|
|
|
|
+ "isManualBind", 1,
|
|
|
|
|
+ "isOauthMpweixin", 1,
|
|
|
|
|
+ "isOauthMobileMpweixin", 1));
|
|
|
|
|
+ // 商城客服设置
|
|
|
|
|
+ all.put("customer", kv(
|
|
|
|
|
+ "enabled", 1,
|
|
|
|
|
+ "provider", "mpwxkf",
|
|
|
|
|
+ "config", kv("mpwxkf", new ArrayList<>())));
|
|
|
|
|
+ return all;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 便捷构造有序 Map(保持与 PHP 默认值相同的字段顺序) */
|
|
|
|
|
+ private static Map<String, Object> kv(Object... pairs) {
|
|
|
|
|
+ Map<String, Object> map = new LinkedHashMap<>();
|
|
|
|
|
+ for (int i = 0; i + 1 < pairs.length; i += 2) {
|
|
|
|
|
+ map.put(String.valueOf(pairs[i]), pairs[i + 1]);
|
|
|
|
|
+ }
|
|
|
|
|
+ return map;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 对齐 PHP resetOptions:默认值打底、实际值覆盖,两边都是对象时递归合并;
|
|
|
|
|
+ * 实际值不是对象(库内缺项时返回的 [])则直接用默认值。
|
|
|
|
|
+ */
|
|
|
|
|
+ private static Object mergeDefaults(Object actual, Map<?, ?> defaults) {
|
|
|
|
|
+ if (!(actual instanceof Map<?, ?> actualMap)) {
|
|
|
|
|
+ return defaults;
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> merged = new LinkedHashMap<>();
|
|
|
|
|
+ for (Map.Entry<?, ?> entry : defaults.entrySet()) {
|
|
|
|
|
+ merged.put(String.valueOf(entry.getKey()), entry.getValue());
|
|
|
|
|
+ }
|
|
|
|
|
+ for (Map.Entry<?, ?> entry : actualMap.entrySet()) {
|
|
|
|
|
+ String key = String.valueOf(entry.getKey());
|
|
|
|
|
+ Object defaultValue = merged.get(key);
|
|
|
|
|
+ Object actualValue = entry.getValue();
|
|
|
|
|
+ if (defaultValue instanceof Map<?, ?> && actualValue instanceof Map<?, ?>) {
|
|
|
|
|
+ merged.put(key, mergeDefaults(actualValue, (Map<?, ?>) defaultValue));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ merged.put(key, actualValue);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return merged;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 对齐 PHP helper::pick,但输出键名统一转驼峰(Java 出参口径)。
|
|
|
|
|
+ * 源数据里下划线与驼峰两种写法都认:库内的 PHP 设置多为 points_name,默认值表用 pointsName。
|
|
|
|
|
+ */
|
|
|
|
|
+ private static Object pickCamel(Object source, String... columns) {
|
|
|
|
|
+ if (!(source instanceof Map<?, ?> sourceMap)) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, String> wanted = new LinkedHashMap<>();
|
|
|
|
|
+ for (String column : columns) {
|
|
|
|
|
+ wanted.put(column, toCamel(column));
|
|
|
|
|
+ wanted.put(toCamel(column), toCamel(column));
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> picked = new LinkedHashMap<>();
|
|
|
|
|
+ for (Map.Entry<?, ?> entry : sourceMap.entrySet()) {
|
|
|
|
|
+ String output = wanted.get(String.valueOf(entry.getKey()));
|
|
|
|
|
+ if (output != null) {
|
|
|
|
|
+ picked.put(output, entry.getValue());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return picked;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** points_name / is_entrance → pointsName / isEntrance */
|
|
|
|
|
+ private static String toCamel(String key) {
|
|
|
|
|
+ if (!key.contains("_")) {
|
|
|
|
|
+ return key;
|
|
|
|
|
+ }
|
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
+ boolean upperNext = false;
|
|
|
|
|
+ for (char c : key.toCharArray()) {
|
|
|
|
|
+ if (c == '_') {
|
|
|
|
|
+ upperNext = true;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ sb.append(upperNext ? Character.toUpperCase(c) : c);
|
|
|
|
|
+ upperNext = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return sb.toString();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 对齐 PHP helper::pick:按源数据顺序取指定键。
|
|
* 对齐 PHP helper::pick:按源数据顺序取指定键。
|
|
|
* 源不是对象(缺失项返回的 []) 时同样返回 [],与 PHP 空数组一致。
|
|
* 源不是对象(缺失项返回的 []) 时同样返回 [],与 PHP 空数组一致。
|