ncloud.ts 12 KB

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