feat: 龙里小程序第一次上传

This commit is contained in:
zoujing committed 2026-09-16 16:52:50 +08:00
commit f23d598328
59 files changed
+11482

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
import request from "../base/request";
/**
* 权益相关接口
* 核心口径(v0.8/v0.11):权益不绑定具体商品、可多次使用;
* 领取与使用只累加次数,不改变可用状态,无幂等约束。
*/
/** 权益中心列表 */
export const fetchBenefits = (params = {}) => request.get("/longli/benefit/list", params);
/** 我的权益列表 */
export const fetchMyBenefits = (params = {}) => request.get("/longli/benefit/mine", params);
/** 领取权益 */
export const claimBenefit = (id) => request.post("/longli/benefit/claim", { id });
/** 记录一次使用(只累加 use_count + last_used_at,不失效) */
export const useBenefit = (id) => request.post("/longli/benefit/use", { id });
/** 商家关联的到店权益 */
export const fetchRelatedBenefits = (entityId) =>
request.get("/longli/benefit/related", { related_entity_id: entityId });
+24
View File
@@ -0,0 +1,24 @@
import request from "../base/request";
/**
* 内容(板块 / 目录 / 条目 / 素材)接口
* 字段口径见 需求说明 §2 / §5 / §6
*/
/** 获取全部板块(4 个:票根经济 / 旅居服务 / 全域美食 / 龙里特产) */
export const fetchSections = () => request.get("/longli/content/sections");
/** 获取板块详情(含分组与条目,已过滤 enabled=false 与空分组) */
export const fetchSection = (sectionKey) => request.get("/longli/content/section", { key: sectionKey });
/** 获取条目详情 */
export const fetchItem = (collection, id) => request.get("/longli/content/item", { collection, id });
/** 获取同类型推荐(排除自身) */
export const fetchRelatedItems = (params) => request.get("/longli/content/related", params);
/** 首页精选推荐(一期为运营固定位,二期由后端下发) */
export const fetchFeaturedItems = () => request.get("/longli/content/featured");
/** 素材(导览图等) */
export const fetchAssets = (params = {}) => request.get("/longli/content/assets", params);
+43
View File
@@ -0,0 +1,43 @@
/**
* 登录 / 用户相关接口
* ---------------------------------------------------------------------------
* 与 YGChatCS src/request/api/LoginApi.js 保持一致(同一后端客户端 clientId = 2)。
* 取 token 走 OAuth2 客户端凭据 Basic custom:custom,请求体是 form-urlencoded。
*/
import request from "../base/request";
/** 网关内置 OAuth2 客户端凭据(与 YGChatCS 相同,非用户凭据) */
const BASIC_AUTH = "Basic Y3VzdG9tOmN1c3RvbQ==";
/**
* code 换 token
* @param {{ openIdCode: string[], grant_type: string, clientId: string, scope: string }} args
*/
export const oauthToken = (args) =>
request.post("/auth/oauth2/token", args, {
header: {
Authorization: BASIC_AUTH,
"Content-Type": "application/x-www-form-urlencoded",
},
silent: true,
});
/**
* 绑定手机号
* @param {{ wechatPhoneCode: string, clientId: string }} args
*/
export const bindUserPhone = (args) => request.post("/hotelBiz/user/bindUserPhone", args);
/** 检测当前登录用户是否已绑定手机号 → { data: boolean } */
export const checkUserPhone = (config = {}) =>
request.get("/hotelBiz/user/checkUserHasBindPhone", {}, config);
/** 获取当前登录用户的手机号(脱敏) */
export const getLoginUserPhone = (args = {}, config = {}) =>
request.get("/hotelBiz/user/getLoginUserPhone", args, config);
/** 服务协议原文 */
export const getServiceAgreement = (args = {}) => request.get("/hotelBiz/mainScene/serviceAgreement", args);
/** 隐私政策原文 */
export const getPrivacyAgreement = (args = {}) => request.get("/hotelBiz/mainScene/privacyPolicy", args);
+78
View File
@@ -0,0 +1,78 @@
/**
* 服务地址解析(参照 YGChatCS request/base/config.js)
* ---------------------------------------------------------------------------
* 启动时用版本号去生产网关换当前环境的 httpUrl:
* POST https://biz.nianxx.cn/hotelBiz/versionManager/getInfo { versionValue }
* → { code: 0, data: { httpUrl, wssUrl } }
* 换不到(版本未登记 / 网络异常)就退回内置测试网关,保证登录等真实接口仍可用。
*/
import {
getEnvConfig,
setBaseUrl,
USE_MOCK_USER,
FORCE_BASE_URL,
BASE_URL_PRO,
BASE_URL_DEV,
SERVICE_URL_PATH,
} from "@/config/env";
import request from "./request";
/** 对外暴露的版本号,发版前与 env.js 的 VERSION 同步 */
export const VERSION = getEnvConfig().version;
let envReady = false;
let envPromise = null;
/** 是否已完成服务地址解析 */
export const isEnvReady = () => envReady;
/**
* 幂等确保服务地址已就绪:并发调用共用同一个请求。
* 登录等真实接口在发请求前 await 它,避免拿不到 baseURL。
*/
export const ensureEnvReady = () => {
if (envReady) return Promise.resolve(getEnvConfig().baseUrl);
if (!envPromise) {
envPromise = getEvnUrl().finally(() => {
envPromise = null;
});
}
return envPromise;
};
const pickHttpUrl = (res) => {
if (!res || res.code !== 0 || !res.data) return "";
return res.data.httpUrl || res.data.baseUrl || "";
};
export const getEvnUrl = async () => {
const env = getEnvConfig();
// 手动钉死地址:跳过服务地址接口
if (FORCE_BASE_URL) {
setBaseUrl(FORCE_BASE_URL);
envReady = true;
return env.baseUrl;
}
// 登录也走 mock 时不需要真实服务地址
if (USE_MOCK_USER) {
setBaseUrl(env.baseUrl || BASE_URL_DEV);
envReady = true;
return env.baseUrl;
}
try {
const res = await request.post(
`${BASE_URL_PRO}${SERVICE_URL_PATH}`,
{ versionValue: env.version },
{ noToken: true, silent: true }
);
setBaseUrl(pickHttpUrl(res) || BASE_URL_DEV);
} catch (e) {
setBaseUrl(BASE_URL_DEV);
}
envReady = true;
return getEnvConfig().baseUrl;
};
+97
View File
@@ -0,0 +1,97 @@
/**
* 统一请求封装(参照 YGChatCS 的 request 层,按本项目裁剪)
* - 自动拼 baseURL(http 开头则原样使用)
* - 自动带 clientId(网关鉴权靠它,本项目 = "2")
* - 自动带 Authorization: Bearer <token>;显式传 header.Authorization 时不覆盖(OAuth 取 token 用 Basic)
* - 424 视为登录失效:清 token → 广播退出 → 跳登录页
*/
import { getEnvConfig } from "@/config/env";
import { NOTICE_EVENT_LOGOUT } from "@/constant";
import { clearLoginState, getAccessToken } from "@/constant/token";
import { goLogin } from "@/utils/nav";
const defaultHeader = {
"Content-Type": "application/json",
};
/** 当前栈顶是否已是登录页(避免 424 时反复 stack 登录页) */
const isOnLoginPage = () => {
try {
const pages = getCurrentPages();
if (!pages || !pages.length) return false;
return pages[pages.length - 1].route === "pages/login/index";
} catch (e) {
return false;
}
};
function request(url, args = {}, method = "POST", customConfig = {}) {
const { noToken = false, silent = false, token: explicitToken, ...rest } = customConfig;
const env = getEnvConfig();
let fullUrl = url;
if (!/^http/.test(url)) {
fullUrl = `${env.baseUrl}${url}`;
}
const header = {
...defaultHeader,
clientId: env.clientId,
...(rest.header || {}),
};
if (noToken) {
delete header.Authorization;
} else if (!header.Authorization) {
const token = explicitToken || getAccessToken();
if (token) header.Authorization = `Bearer ${token}`;
}
const config = {
...rest,
header,
method,
timeout: env.timeout,
data: args,
};
return new Promise((resolve, reject) => {
uni.request({
url: fullUrl,
...config,
success: (res) => {
const { statusCode = 0, data } = res;
if (statusCode === 424) {
clearLoginState();
uni.$emit(NOTICE_EVENT_LOGOUT);
if (!isOnLoginPage()) setTimeout(() => goLogin(), 500);
}
if (statusCode >= 200 && statusCode < 300) {
resolve(data);
return;
}
if (!silent) {
const msg = (data && (data.message || data.msg)) || `请求失败(${statusCode})`;
uni.showToast({ title: msg, icon: "none" });
}
reject(res);
},
fail: (err) => {
if (!silent) {
uni.showToast({ title: "网络异常,请稍后重试", icon: "none" });
}
reject(err);
},
});
});
}
request.post = (url, args = {}, config = {}) => request(url, args, "POST", config);
request.get = (url, args = {}, config = {}) => request(url, args, "GET", config);
request.put = (url, args = {}, config = {}) => request(url, args, "PUT", config);
request.del = (url, args = {}, config = {}) => request(url, args, "DELETE", config);
export default request;