ncloud.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. // CloudObject.ts
  2. let serverURL = `https://dev.fmode.cn/parse`;
  3. if (location.protocol == "http:") {
  4. serverURL = `http://dev.fmode.cn:1337/parse`;
  5. }
  6. export class CloudObject {
  7. className: string;
  8. id: string | undefined = undefined;
  9. createdAt: any;
  10. updatedAt: any;
  11. data: Record<string, any> = {};
  12. constructor(className: string) {
  13. this.className = className;
  14. }
  15. toPointer() {
  16. return { "__type": "Pointer", "className": this.className, "objectId": this.id };
  17. }
  18. set(json: Record<string, any>) {
  19. Object.keys(json).forEach(key => {
  20. if (["objectId", "id", "createdAt", "updatedAt"].indexOf(key) > -1) {
  21. return;
  22. }
  23. this.data[key] = json[key];
  24. });
  25. }
  26. get(key: string) {
  27. return this.data[key] || null;
  28. }
  29. async save() {
  30. let method = "POST";
  31. let url = serverURL + `/classes/${this.className}`;
  32. // 更新
  33. if (this.id) {
  34. url += `/${this.id}`;
  35. method = "PUT";
  36. }
  37. const body = JSON.stringify(this.data);
  38. const response = await fetch(url, {
  39. headers: {
  40. "content-type": "application/json;charset=UTF-8",
  41. "x-parse-application-id": "dev"
  42. },
  43. body: body,
  44. method: method,
  45. mode: "cors",
  46. credentials: "omit"
  47. });
  48. const result = await response?.json();
  49. if (result?.error) {
  50. console.error(result?.error);
  51. }
  52. if (result?.objectId) {
  53. this.id = result?.objectId;
  54. }
  55. return this;
  56. }
  57. async destroy() {
  58. if (!this.id) return;
  59. const response = await fetch(serverURL + `/classes/${this.className}/${this.id}`, {
  60. headers: {
  61. "x-parse-application-id": "dev"
  62. },
  63. body: null,
  64. method: "DELETE",
  65. mode: "cors",
  66. credentials: "omit"
  67. });
  68. const result = await response?.json();
  69. if (result) {
  70. this.id = undefined;
  71. }
  72. return true;
  73. }
  74. }
  75. // CloudQuery.ts
  76. export class CloudQuery {
  77. className: string;
  78. queryParams: Record<string, any> = { where: {} };
  79. constructor(className: string) {
  80. this.className = className;
  81. }
  82. include(...fileds: string[]) {
  83. this.queryParams["include"] = fileds;
  84. }
  85. greaterThan(key: string, value: any) {
  86. if (!this.queryParams["where"][key]) this.queryParams["where"][key] = {};
  87. this.queryParams["where"][key]["$gt"] = value;
  88. }
  89. greaterThanAndEqualTo(key: string, value: any) {
  90. if (!this.queryParams["where"][key]) this.queryParams["where"][key] = {};
  91. this.queryParams["where"][key]["$gte"] = value;
  92. }
  93. lessThan(key: string, value: any) {
  94. if (!this.queryParams["where"][key]) this.queryParams["where"][key] = {};
  95. this.queryParams["where"][key]["$lt"] = value;
  96. }
  97. lessThanAndEqualTo(key: string, value: any) {
  98. if (!this.queryParams["where"][key]) this.queryParams["where"][key] = {};
  99. this.queryParams["where"][key]["$lte"] = value;
  100. }
  101. equalTo(key: string, value: any) {
  102. if (!this.queryParams["where"]) this.queryParams["where"] = {};
  103. this.queryParams["where"][key] = value;
  104. }
  105. async get(id: string) {
  106. const url = serverURL + `/classes/${this.className}/${id}?`;
  107. const response = await fetch(url, {
  108. headers: {
  109. "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
  110. "x-parse-application-id": "dev"
  111. },
  112. body: null,
  113. method: "GET",
  114. mode: "cors",
  115. credentials: "omit"
  116. });
  117. const json = await response?.json();
  118. if (json) {
  119. let existsObject = this.dataToObj(json)
  120. return existsObject;
  121. }
  122. return null
  123. }
  124. async find(): Promise<Array<CloudObject>> {
  125. let url = serverURL + `/classes/${this.className}?`;
  126. let queryStr = ``
  127. Object.keys(this.queryParams).forEach(key => {
  128. let paramStr = JSON.stringify(this.queryParams[key]);
  129. if (key == "include") {
  130. paramStr = this.queryParams[key]?.join(",")
  131. }
  132. if (queryStr) {
  133. url += `${key}=${paramStr}`;
  134. } else {
  135. url += `&${key}=${paramStr}`;
  136. }
  137. })
  138. // if (Object.keys(this.queryParams["where"]).length) {
  139. // }
  140. const response = await fetch(url, {
  141. headers: {
  142. "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
  143. "x-parse-application-id": "dev"
  144. },
  145. body: null,
  146. method: "GET",
  147. mode: "cors",
  148. credentials: "omit"
  149. });
  150. const json = await response?.json();
  151. let list = json?.results || []
  152. let objList = list.map((item: any) => this.dataToObj(item))
  153. return objList || [];
  154. }
  155. async first() {
  156. let url = serverURL + `/classes/${this.className}?`;
  157. if (Object.keys(this.queryParams["where"]).length) {
  158. const whereStr = JSON.stringify(this.queryParams["where"]);
  159. url += `where=${whereStr}&limit=1`;
  160. }
  161. const response = await fetch(url, {
  162. headers: {
  163. "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
  164. "x-parse-application-id": "dev"
  165. },
  166. body: null,
  167. method: "GET",
  168. mode: "cors",
  169. credentials: "omit"
  170. });
  171. const json = await response?.json();
  172. const exists = json?.results?.[0] || null;
  173. if (exists) {
  174. let existsObject = this.dataToObj(exists)
  175. return existsObject;
  176. }
  177. return null
  178. }
  179. dataToObj(exists: any): CloudObject {
  180. let existsObject = new CloudObject(this.className);
  181. Object.keys(exists).forEach(key => {
  182. if (exists[key]?.__type == "Object") {
  183. exists[key] = this.dataToObj(exists[key])
  184. }
  185. })
  186. existsObject.set(exists);
  187. existsObject.id = exists.objectId;
  188. existsObject.createdAt = exists.createdAt;
  189. existsObject.updatedAt = exists.updatedAt;
  190. return existsObject;
  191. }
  192. // 在 CloudQuery 类中添加
  193. ascending(key: string) {
  194. this.queryParams["order"] = key;
  195. return this; // 支持链式调用
  196. }
  197. // 如果需要降序排序,也可以添加
  198. descending(key: string) {
  199. this.queryParams["order"] = `-${key}`;
  200. return this;
  201. }
  202. }
  203. // CloudUser.ts
  204. export class CloudUser extends CloudObject {
  205. constructor() {
  206. super("_User"); // 假设用户类在Parse中是"_User"
  207. // 读取用户缓存信息
  208. let userCacheStr = localStorage.getItem("NCloud/dev/User")
  209. if (userCacheStr) {
  210. let userData = JSON.parse(userCacheStr)
  211. // 设置用户信息
  212. this.id = userData?.objectId;
  213. this.sessionToken = userData?.sessionToken;
  214. this.data = userData; // 保存用户数据
  215. }
  216. }
  217. sessionToken: string | null = ""
  218. /** 获取当前用户信息 */
  219. async current() {
  220. if (!this.sessionToken) {
  221. console.error("用户未登录");
  222. return null;
  223. }
  224. return this;
  225. // const response = await fetch(serverURL + `/users/me`, {
  226. // headers: {
  227. // "x-parse-application-id": "dev",
  228. // "x-parse-session-token": this.sessionToken // 使用sessionToken进行身份验证
  229. // },
  230. // method: "GET"
  231. // });
  232. // const result = await response?.json();
  233. // if (result?.error) {
  234. // console.error(result?.error);
  235. // return null;
  236. // }
  237. // return result;
  238. }
  239. /** 登录 */
  240. async login(username: string, password: string): Promise<CloudUser | null> {
  241. const response = await fetch(serverURL + `/login`, {
  242. headers: {
  243. "x-parse-application-id": "dev",
  244. "Content-Type": "application/json"
  245. },
  246. body: JSON.stringify({ username, password }),
  247. method: "POST"
  248. });
  249. const result = await response?.json();
  250. if (result?.error) {
  251. console.error(result?.error);
  252. return null;
  253. }
  254. // 设置用户信息
  255. this.id = result?.objectId;
  256. this.sessionToken = result?.sessionToken;
  257. this.data = result; // 保存用户数据
  258. // 缓存用户信息
  259. console.log(result)
  260. localStorage.setItem("NCloud/dev/User", JSON.stringify(result))
  261. return this;
  262. }
  263. /** 登出 */
  264. async logout() {
  265. if (!this.sessionToken) {
  266. console.error("用户未登录");
  267. return;
  268. }
  269. const response = await fetch(serverURL + `/logout`, {
  270. headers: {
  271. "x-parse-application-id": "dev",
  272. "x-parse-session-token": this.sessionToken
  273. },
  274. method: "POST"
  275. });
  276. let result = await response?.json();
  277. if (result?.error) {
  278. console.error(result?.error);
  279. if (result?.error == "Invalid session token") {
  280. this.clearUserCache()
  281. return true;
  282. }
  283. return false;
  284. }
  285. this.clearUserCache()
  286. return true;
  287. }
  288. clearUserCache() {
  289. // 清除用户信息
  290. localStorage.removeItem("NCloud/dev/User")
  291. this.id = undefined;
  292. this.sessionToken = null;
  293. this.data = {};
  294. }
  295. /** 注册 */
  296. async signUp(username: string, password: string, additionalData: Record<string, any> = {}) {
  297. const userData = {
  298. username,
  299. password,
  300. ...additionalData // 合并额外的用户数据
  301. };
  302. const response = await fetch(serverURL + `/users`, {
  303. headers: {
  304. "x-parse-application-id": "dev",
  305. "Content-Type": "application/json"
  306. },
  307. body: JSON.stringify(userData),
  308. method: "POST"
  309. });
  310. const result = await response?.json();
  311. if (result?.error) {
  312. console.error(result?.error);
  313. return null;
  314. }
  315. // 设置用户信息
  316. // 缓存用户信息
  317. console.log(result)
  318. localStorage.setItem("NCloud/dev/User", JSON.stringify(result))
  319. this.id = result?.objectId;
  320. this.sessionToken = result?.sessionToken;
  321. this.data = result; // 保存用户数据
  322. return this;
  323. }
  324. override async save() {
  325. let method = "POST";
  326. let url = serverURL + `/users`;
  327. // 更新用户信息
  328. if (this.id) {
  329. url += `/${this.id}`;
  330. method = "PUT";
  331. }
  332. let data: any = JSON.parse(JSON.stringify(this.data))
  333. delete data.createdAt
  334. delete data.updatedAt
  335. delete data.ACL
  336. delete data.objectId
  337. const body = JSON.stringify(data);
  338. let headersOptions: any = {
  339. "content-type": "application/json;charset=UTF-8",
  340. "x-parse-application-id": "dev",
  341. "x-parse-session-token": this.sessionToken, // 添加sessionToken以进行身份验证
  342. }
  343. const response = await fetch(url, {
  344. headers: headersOptions,
  345. body: body,
  346. method: method,
  347. mode: "cors",
  348. credentials: "omit"
  349. });
  350. const result = await response?.json();
  351. if (result?.error) {
  352. console.error(result?.error);
  353. }
  354. if (result?.objectId) {
  355. this.id = result?.objectId;
  356. }
  357. localStorage.setItem("NCloud/dev/User", JSON.stringify(this.data))
  358. return this;
  359. }
  360. }
  361. export class CloudApi {
  362. async fetch(path: string, body: any, options?: {
  363. method: string
  364. body: any
  365. }) {
  366. let reqOpts: any = {
  367. headers: {
  368. "x-parse-application-id": "dev",
  369. "Content-Type": "application/json"
  370. },
  371. method: options?.method || "POST",
  372. mode: "cors",
  373. credentials: "omit"
  374. }
  375. if (body || options?.body) {
  376. reqOpts.body = JSON.stringify(body || options?.body);
  377. reqOpts.json = true;
  378. }
  379. let host = `https://dev.fmode.cn`
  380. // host = `http://127.0.0.1:1337`
  381. let url = `${host}/api/` + path
  382. console.log(url, reqOpts)
  383. const response = await fetch(url, reqOpts);
  384. let json = await response.json();
  385. return json
  386. }
  387. }