api.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. import $app from "./app";
  2. import $config from "./config";
  3. const api = {};
  4. // 网络请求封装
  5. const Request = function (opts) {
  6. const originalComplete = opts.complete;
  7. return new Promise((resolve, reject) => {
  8. uni.request(
  9. Object.assign({}, opts, {
  10. complete: (res) => {
  11. const hasSuccess = Boolean(
  12. res.errMsg == "request:ok" &&
  13. res.statusCode >= 200 &&
  14. res.statusCode < 300
  15. );
  16. hasSuccess ? resolve(res.data) : reject(res);
  17. if (originalComplete && typeof originalComplete == "function")
  18. originalComplete(res);
  19. },
  20. })
  21. );
  22. });
  23. };
  24. // 路径拼接
  25. const pathJoin = function (...args) {
  26. return args.join("/").replace(/(?<!:)(\/{2,})/g, "/");
  27. };
  28. // 显示LOADING
  29. const showLoading = function () {
  30. uni.showLoading({ title: "", mask: true });
  31. };
  32. // 关闭LOADING
  33. const hideLoading = function () {
  34. uni.hideLoading();
  35. };
  36. // 获取用户TOKEN
  37. const getUserToken = function () {
  38. return uni.getStorageSync($config.keyname.userToken);
  39. };
  40. /**
  41. * 基础请求
  42. * @param {String} method 请求类型
  43. * @param {String} url 请求地址
  44. * @param {Object} data 请求数据
  45. * @param {Object} opts 配置参数
  46. */
  47. api.base = function (method, url, data, opts) {
  48. return new Promise(async (resolve, reject) => {
  49. const options = Object.assign(
  50. {
  51. // 请求地址
  52. url: pathJoin($config.url.request, url),
  53. // 请求数据
  54. data: data || {},
  55. // 请求类型
  56. method: method || "post",
  57. // 数据类型
  58. dataType: "json",
  59. // 自动显示LOADING
  60. loading: true,
  61. // 启用错误自动拦截
  62. error: true,
  63. // 请求头设定
  64. header: {
  65. "content-type": "application/json",
  66. Authorization: "Bearer " + getAccessToken(), // 修改这里,使用新的获取token方法
  67. },
  68. // 设置显示LOADING的方法
  69. showLoading: showLoading,
  70. // 设置关闭LOADING的方法
  71. hideLoading: hideLoading,
  72. },
  73. opts || {}
  74. );
  75. if (options.loading && typeof options.showLoading == "function") {
  76. options.showLoading();
  77. }
  78. Request(options)
  79. .then(async (res) => {
  80. if (options.loading && typeof options.hideLoading == "function") {
  81. options.hideLoading();
  82. }
  83. switch (res.code) {
  84. // 请求正常
  85. case "00000":
  86. resolve(res);
  87. break;
  88. // 约定401为未登录状态
  89. case "A0230":
  90. try {
  91. // 尝试刷新token
  92. console.log("进入刷新请求");
  93. const refreshResult = await refreshToken();
  94. if (refreshResult) {
  95. // 刷新成功,更新header中的token并重新请求
  96. options.header.token = getAccessToken();
  97. try {
  98. const db = await Request(options);
  99. resolve(db);
  100. } catch (err) {
  101. reject(err);
  102. }
  103. } else {
  104. // 刷新失败,执行登录
  105. await api.login();
  106. options.header.token = getAccessToken();
  107. try {
  108. const db = await Request(options);
  109. resolve(db);
  110. } catch (err) {
  111. reject(err);
  112. }
  113. }
  114. } catch (err) {
  115. reject(err);
  116. }
  117. break;
  118. // 其他错误请求
  119. default:
  120. if (options.error) {
  121. $app.popup.alert(res.msg || `${url}\r\n未知错误`, "数据请求");
  122. } else {
  123. reject(res);
  124. }
  125. break;
  126. }
  127. })
  128. .catch(async (err) => {
  129. console.log("请求失败", err.data.code);
  130. if (err.data.code == "A0230") {
  131. try {
  132. // 尝试刷新token
  133. console.log("进入刷新请求");
  134. const refreshResult = await refreshToken();
  135. if (refreshResult) {
  136. // 刷新成功,更新header中的token并重新请求
  137. options.header.token = getAccessToken();
  138. try {
  139. const db = await Request(options);
  140. resolve(db);
  141. } catch (err) {
  142. reject(err);
  143. }
  144. }
  145. } catch (err) {
  146. reject(err);
  147. }
  148. }
  149. /*失败处理,此处为非200状态码引起的错误*/
  150. options.hideLoading();
  151. $app.popup.alert(`服务器响应失败\r\n${err.msg}`, "数据请求");
  152. });
  153. });
  154. };
  155. // 新增:获取accessToken的方法
  156. const getAccessToken = function () {
  157. return uni.getStorageSync($config.keyname.accessToken);
  158. };
  159. // 新增:刷新token的方法
  160. const refreshToken = async function () {
  161. const refreshToken = uni.getStorageSync($config.keyname.refreshToken);
  162. console.log("刷新token", refreshToken);
  163. if (!refreshToken) return false;
  164. try {
  165. const res = await Request({
  166. url: pathJoin($config.url.request, $config.api.refreshToken),
  167. method: "post",
  168. data: { refreshToken },
  169. header: {
  170. "content-type": "application/json",
  171. },
  172. });
  173. if (res.code === "00000") {
  174. uni.setStorageSync($config.keyname.accessToken, res.data.accessToken);
  175. uni.setStorageSync($config.keyname.refreshToken, res.data.refreshToken);
  176. return true;
  177. }
  178. return false;
  179. } catch (e) {
  180. return false;
  181. }
  182. };
  183. /**
  184. * POST请求
  185. * @param {String} url 请求地址
  186. * @param {Object} data 请求数据
  187. * @param {Object} opts 配置参数
  188. */
  189. api.post = function (url, data, opts) {
  190. return api.base("post", url, data, Object.assign({}, opts));
  191. };
  192. /**
  193. * GET请求
  194. * @param {String} url 请求地址
  195. * @param {Object} data 请求数据
  196. * @param {Object} opts 配置参数
  197. */
  198. api.get = function (url, data, opts) {
  199. return api.base("get", url, data, Object.assign({}, opts));
  200. };
  201. /**
  202. * PUT请求
  203. * @param {String} url 请求地址
  204. * @param {Object} data 请求数据
  205. * @param {Object} opts 配置参数
  206. */
  207. api.put = function (url, data, opts) {
  208. return api.base("put", url, data, Object.assign({}, opts));
  209. };
  210. /**
  211. * 获取静态数据
  212. * @param {String} url 静态文件地址
  213. * @param {Object} data 参数数据
  214. * @param {Object} opts 配置参数
  215. */
  216. api.static = function (url, data, opts) {
  217. return new Promise(async (resolve, reject) => {
  218. // 设置选项
  219. var _opts = Object.assign(
  220. {
  221. url: /^http/.test(url) ? url : API_BASE + (url || ""),
  222. data: Object.assign({ cache: Date.now() }, data),
  223. },
  224. opts || {}
  225. );
  226. uni.request({
  227. ..._opts,
  228. success: (res) => {
  229. resolve(res.data);
  230. },
  231. });
  232. });
  233. };
  234. /**
  235. * 文件上传
  236. * @param {String} file 文件临时路径
  237. * @param {Object} opts 上传参数
  238. */
  239. api.upload = function (file, opts) {
  240. return new Promise((resolve, reject) => {
  241. const options = Object.assign(
  242. {
  243. // 请求地址
  244. url: pathJoin($config.url.upload, opts?.url || ""),
  245. // 请求数据
  246. filePath: file,
  247. // 自动显示LOADING
  248. loading: true,
  249. // 启用错误自动拦截
  250. error: true,
  251. // 请求头设定
  252. header: {
  253. token: uni.getStorageSync($config.keyname.userToken),
  254. },
  255. // 设置显示LOADING的方法
  256. showLoading: showLoading,
  257. // 设置关闭LOADING的方法
  258. hideLoading: hideLoading,
  259. },
  260. opts || {}
  261. );
  262. });
  263. };
  264. /**
  265. * 获取登录code
  266. */
  267. api.userCode = function () {
  268. return new Promise((resolve, reject) => {
  269. uni.login({
  270. provider: "weixin",
  271. success: (res) => resolve(res.code),
  272. fail: (err) => reject(err),
  273. });
  274. });
  275. };
  276. /**
  277. * 自动登录
  278. * @param {Object} data 登录数据(非必填)
  279. */
  280. api.login = function (data) {
  281. return new Promise(async (resolve, reject) => {
  282. const code = await api.userCode();
  283. api
  284. .post($config.api.login, { ...(data || {}), code })
  285. .then(async (res) => {
  286. // 保存 accessToken 和 refreshToken
  287. uni.setStorageSync($config.keyname.accessToken, res?.data?.accessToken);
  288. uni.setStorageSync(
  289. $config.keyname.refreshToken,
  290. res?.data?.refreshToken
  291. );
  292. // 保留原有的 userInfo 存储
  293. uni.setStorageSync($config.keyname.userInfo, res?.data?.userInfo);
  294. // 返回 accessToken 保持向后兼容
  295. resolve(res.data.accessToken);
  296. })
  297. .catch((err) => reject(err));
  298. });
  299. };
  300. export default api;