Initial project commit
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
export const checkLogin = () => {
|
||||
const token = uni.getStorageSync("access_token");
|
||||
if (!token) {
|
||||
uni.showToast({ title: "请先登录", icon: "none" });
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({ url: "/pages/login/index" });
|
||||
}, 300);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
const cityData = [
|
||||
{ province: "北京市", cities: ["北京市"] },
|
||||
{ province: "天津市", cities: ["天津市"] },
|
||||
{ province: "上海市", cities: ["上海市"] },
|
||||
{ province: "重庆市", cities: ["重庆市"] },
|
||||
{ province: "河北省", cities: ["石家庄市","唐山市","秦皇岛市","邯郸市","邢台市","保定市","张家口市","承德市","沧州市","廊坊市","衡水市"] },
|
||||
{ province: "山西省", cities: ["太原市","大同市","阳泉市","长治市","晋城市","朔州市","晋中市","运城市","忻州市","临汾市","吕梁市"] },
|
||||
{ province: "辽宁省", cities: ["沈阳市","大连市","鞍山市","抚顺市","本溪市","丹东市","锦州市","营口市","阜新市","辽阳市","盘锦市","铁岭市","朝阳市","葫芦岛市"] },
|
||||
{ province: "吉林省", cities: ["长春市","吉林市","四平市","辽源市","通化市","白山市","松原市","白城市","延边朝鲜族自治州"] },
|
||||
{ province: "黑龙江省", cities: ["哈尔滨市","齐齐哈尔市","鸡西市","鹤岗市","双鸭山市","大庆市","伊春市","佳木斯市","七台河市","牡丹江市","黑河市","绥化市","大兴安岭地区"] },
|
||||
{ province: "江苏省", cities: ["南京市","无锡市","徐州市","常州市","苏州市","南通市","连云港市","淮安市","盐城市","扬州市","镇江市","泰州市","宿迁市"] },
|
||||
{ province: "浙江省", cities: ["杭州市","宁波市","温州市","嘉兴市","湖州市","绍兴市","金华市","衢州市","舟山市","台州市","丽水市"] },
|
||||
{ province: "安徽省", cities: ["合肥市","芜湖市","蚌埠市","淮南市","马鞍山市","淮北市","铜陵市","安庆市","黄山市","滁州市","阜阳市","宿州市","六安市","亳州市","池州市","宣城市"] },
|
||||
{ province: "福建省", cities: ["福州市","厦门市","莆田市","三明市","泉州市","漳州市","南平市","龙岩市","宁德市"] },
|
||||
{ province: "江西省", cities: ["南昌市","景德镇市","萍乡市","九江市","新余市","鹰潭市","赣州市","吉安市","宜春市","抚州市","上饶市"] },
|
||||
{ province: "山东省", cities: ["济南市","青岛市","淄博市","枣庄市","东营市","烟台市","潍坊市","济宁市","泰安市","威海市","日照市","临沂市","德州市","聊城市","滨州市","菏泽市"] },
|
||||
{ province: "河南省", cities: ["郑州市","开封市","洛阳市","平顶山市","安阳市","鹤壁市","新乡市","焦作市","濮阳市","许昌市","漯河市","三门峡市","南阳市","商丘市","信阳市","周口市","驻马店市"] },
|
||||
{ province: "湖北省", cities: ["武汉市","黄石市","十堰市","宜昌市","襄阳市","鄂州市","荆门市","孝感市","荆州市","黄冈市","咸宁市","随州市","恩施土家族苗族自治州"] },
|
||||
{ province: "湖南省", cities: ["长沙市","株洲市","湘潭市","衡阳市","邵阳市","岳阳市","常德市","张家界市","益阳市","郴州市","永州市","怀化市","娄底市","湘西土家族苗族自治州"] },
|
||||
{ province: "广东省", cities: ["广州市","韶关市","深圳市","珠海市","汕头市","佛山市","江门市","湛江市","茂名市","肇庆市","惠州市","梅州市","汕尾市","河源市","阳江市","清远市","东莞市","中山市","潮州市","揭阳市","云浮市"] },
|
||||
{ province: "海南省", cities: ["海口市","三亚市","三沙市","儋州市"] },
|
||||
{ province: "四川省", cities: ["成都市","自贡市","攀枝花市","泸州市","德阳市","绵阳市","广元市","遂宁市","内江市","乐山市","南充市","眉山市","宜宾市","广安市","达州市","雅安市","巴中市","资阳市","阿坝藏族羌族自治州","甘孜藏族自治州","凉山彝族自治州"] },
|
||||
{ province: "贵州省", cities: ["贵阳市","六盘水市","遵义市","安顺市","毕节市","铜仁市","黔西南布依族苗族自治州","黔东南苗族侗族自治州","黔南布依族苗族自治州"] },
|
||||
{ province: "云南省", cities: ["昆明市","曲靖市","玉溪市","保山市","昭通市","丽江市","普洱市","临沧市","楚雄彝族自治州","红河哈尼族彝族自治州","文山壮族苗族自治州","西双版纳傣族自治州","大理白族自治州","德宏傣族景颇族自治州","怒江傈僳族自治州","迪庆藏族自治州"] },
|
||||
{ province: "西藏自治区", cities: ["拉萨市","日喀则市","昌都市","林芝市","山南市","那曲市","阿里地区"] },
|
||||
{ province: "陕西省", cities: ["西安市","铜川市","宝鸡市","咸阳市","渭南市","延安市","汉中市","榆林市","安康市","商洛市"] },
|
||||
{ province: "甘肃省", cities: ["兰州市","嘉峪关市","金昌市","白银市","天水市","武威市","张掖市","平凉市","酒泉市","庆阳市","定西市","陇南市","临夏回族自治州","甘南藏族自治州"] },
|
||||
{ province: "青海省", cities: ["西宁市","海东市","海北藏族自治州","黄南藏族自治州","海南藏族自治州","果洛藏族自治州","玉树藏族自治州","海西蒙古族藏族自治州"] },
|
||||
{ province: "内蒙古自治区", cities: ["呼和浩特市","包头市","乌海市","赤峰市","通辽市","鄂尔多斯市","呼伦贝尔市","巴彦淖尔市","乌兰察布市","兴安盟","锡林郭勒盟","阿拉善盟"] },
|
||||
{ province: "广西壮族自治区", cities: ["南宁市","柳州市","桂林市","梧州市","北海市","防城港市","钦州市","贵港市","玉林市","百色市","贺州市","河池市","来宾市","崇左市"] },
|
||||
{ province: "宁夏回族自治区", cities: ["银川市","石嘴山市","吴忠市","固原市","中卫市"] },
|
||||
{ province: "新疆维吾尔自治区", cities: ["乌鲁木齐市","克拉玛依市","吐鲁番市","哈密市","昌吉回族自治州","博尔塔拉蒙古自治州","巴音郭楞蒙古自治州","阿克苏地区","克孜勒苏柯尔克孜自治州","喀什地区","和田地区","伊犁哈萨克自治州","塔城地区","阿勒泰地区"] },
|
||||
{ province: "香港特别行政区", cities: ["香港"] },
|
||||
{ province: "澳门特别行政区", cities: ["澳门"] },
|
||||
{ province: "台湾省", cities: ["台北市","新北市","桃园市","台中市","台南市","高雄市","基隆市","新竹市","嘉义市"] },
|
||||
];
|
||||
|
||||
export default cityData;
|
||||
@@ -0,0 +1,11 @@
|
||||
// #ifdef H5
|
||||
const API_BASE = "/api/v1";
|
||||
const SERVER_ORIGIN = window.location.origin;
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
const API_BASE = "http://10.0.10.11:8000/api/v1";
|
||||
const SERVER_ORIGIN = "http://10.0.10.11:8000";
|
||||
// #endif
|
||||
|
||||
export { API_BASE, SERVER_ORIGIN };
|
||||
@@ -0,0 +1,7 @@
|
||||
import { SERVER_ORIGIN } from "./config";
|
||||
|
||||
export const resolveImageUrl = (url) => {
|
||||
if (!url) return "";
|
||||
if (url.startsWith("http://") || url.startsWith("https://")) return url;
|
||||
return SERVER_ORIGIN + url;
|
||||
};
|
||||
@@ -0,0 +1,157 @@
|
||||
import { API_BASE } from "./config";
|
||||
|
||||
let isRefreshing = false;
|
||||
let pendingQueue = [];
|
||||
|
||||
const isHtmlLike = (value) =>
|
||||
typeof value === "string" && value.trim().startsWith("<");
|
||||
|
||||
export const extractList = (payload) => {
|
||||
if (Array.isArray(payload?.items)) return payload.items;
|
||||
if (Array.isArray(payload?.data)) return payload.data;
|
||||
if (Array.isArray(payload)) return payload;
|
||||
return [];
|
||||
};
|
||||
|
||||
const doRequest = (options) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const token = uni.getStorageSync("access_token");
|
||||
uni.request({
|
||||
url: API_BASE + options.url,
|
||||
method: options.method || "GET",
|
||||
data: options.data,
|
||||
header: {
|
||||
"Content-Type": "application/json",
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
...options.header,
|
||||
},
|
||||
success: (res) => resolve(res),
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const tryRefreshToken = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const rt = uni.getStorageSync("refresh_token");
|
||||
if (!rt) return reject(new Error("no_refresh_token"));
|
||||
|
||||
uni.request({
|
||||
url: API_BASE + "/auth/refresh",
|
||||
method: "POST",
|
||||
header: { "Content-Type": "application/json" },
|
||||
data: { refresh_token: rt },
|
||||
success: (res) => {
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
const { access_token, refresh_token } = res.data;
|
||||
uni.setStorageSync("access_token", access_token);
|
||||
if (refresh_token) uni.setStorageSync("refresh_token", refresh_token);
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error("refresh_failed"));
|
||||
}
|
||||
},
|
||||
fail: () => reject(new Error("refresh_network_error")),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const goLogin = () => {
|
||||
uni.removeStorageSync("access_token");
|
||||
uni.removeStorageSync("refresh_token");
|
||||
const pages = getCurrentPages();
|
||||
const current = pages[pages.length - 1];
|
||||
const route = current ? `/${current.route}` : "";
|
||||
if (route !== "/pages/login/index") {
|
||||
uni.navigateTo({ url: "/pages/login/index" });
|
||||
}
|
||||
};
|
||||
|
||||
const handleError = (res) => {
|
||||
const code = res.statusCode;
|
||||
if (code === 403) return "没有权限执行此操作";
|
||||
if (code === 404) return "请求的资源不存在";
|
||||
if (code === 409) return "数据冲突,请刷新重试";
|
||||
if (code === 422) {
|
||||
const detail = res.data?.detail;
|
||||
if (Array.isArray(detail) && detail.length > 0) {
|
||||
return detail.map((d) => d.msg || d.message).join(";");
|
||||
}
|
||||
}
|
||||
if (code === 429) return "操作过于频繁,请稍后再试";
|
||||
if (code >= 500) return "服务器繁忙,请稍后重试";
|
||||
const raw = res.data?.message || res.data?.detail || "请求失败";
|
||||
return typeof raw === "string" ? raw : JSON.stringify(raw);
|
||||
};
|
||||
|
||||
const request = (options) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
doRequest(options)
|
||||
.then((res) => {
|
||||
if (isHtmlLike(res.data)) {
|
||||
const msg = "接口返回异常,请检查网络或服务状态";
|
||||
uni.showToast({ title: msg, icon: "none" });
|
||||
return reject(new Error(msg));
|
||||
}
|
||||
|
||||
if (res.statusCode === 401) {
|
||||
if (isRefreshing) {
|
||||
pendingQueue.push({ options, resolve, reject });
|
||||
return;
|
||||
}
|
||||
|
||||
isRefreshing = true;
|
||||
tryRefreshToken()
|
||||
.then(() => {
|
||||
isRefreshing = false;
|
||||
doRequest(options).then((r2) => {
|
||||
if (r2.statusCode >= 200 && r2.statusCode < 300) {
|
||||
resolve(r2.data);
|
||||
} else {
|
||||
const msg = handleError(r2);
|
||||
uni.showToast({ title: msg, icon: "none" });
|
||||
reject(new Error(msg));
|
||||
}
|
||||
});
|
||||
pendingQueue.forEach((p) => {
|
||||
doRequest(p.options).then((r2) => {
|
||||
if (r2.statusCode >= 200 && r2.statusCode < 300) {
|
||||
p.resolve(r2.data);
|
||||
} else {
|
||||
p.reject(new Error(handleError(r2)));
|
||||
}
|
||||
});
|
||||
});
|
||||
pendingQueue = [];
|
||||
})
|
||||
.catch(() => {
|
||||
isRefreshing = false;
|
||||
pendingQueue.forEach((p) => p.reject(new Error("登录已过期")));
|
||||
pendingQueue = [];
|
||||
goLogin();
|
||||
reject(new Error("登录已过期,请重新登录"));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
resolve(res.data);
|
||||
} else {
|
||||
const msg = handleError(res);
|
||||
uni.showToast({ title: msg, icon: "none" });
|
||||
reject(new Error(msg));
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.showToast({ title: "网络连接失败,请检查网络", icon: "none" });
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const get = (url, data) => request({ url, method: "GET", data });
|
||||
export const post = (url, data) => request({ url, method: "POST", data });
|
||||
export const put = (url, data) => request({ url, method: "PUT", data });
|
||||
export const del = (url, data) => request({ url, method: "DELETE", data });
|
||||
|
||||
export default request;
|
||||
@@ -0,0 +1,25 @@
|
||||
export const formatSpotPrice = (spot) => {
|
||||
if (!spot) {
|
||||
return { label: "", isFree: false };
|
||||
}
|
||||
|
||||
if (spot.is_free) {
|
||||
return { label: "免费", isFree: true };
|
||||
}
|
||||
|
||||
const min = spot.price_min;
|
||||
const max = spot.price_max;
|
||||
|
||||
if (min != null && max != null) {
|
||||
if (Number(min) === Number(max)) {
|
||||
return { label: `收费 ¥${min}`, isFree: false };
|
||||
}
|
||||
return { label: `收费 ¥${min} - ¥${max}`, isFree: false };
|
||||
}
|
||||
|
||||
if (min != null || max != null) {
|
||||
return { label: `收费 ¥${min ?? max}`, isFree: false };
|
||||
}
|
||||
|
||||
return { label: "收费", isFree: false };
|
||||
};
|
||||
Reference in New Issue
Block a user