main.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. import axios from "axios"
  2. import { defineStore } from "pinia";
  3. import { api } from "@/api"
  4. import router from "@/router"
  5. import { getLocalToken, removeLocalToken, saveLocalToken } from "@/utils";
  6. import type { AppNotification } from '@/interfaces';
  7. import type { IUserProfile, IUserProfileCreate, IUserProfileUpdate, MainState, Video, VideoCreate, ArticleCreate, Image, ImageDownload, VideoUploaded, YTViewsUserData, PaymentData, SimplePaymentData, VideoContent, genVideoData } from '@/interfaces';
  8. import i18n from '@/plugins/i18n'
  9. import { wsUrl } from "@/env";
  10. const defaultState: MainState = {
  11. isLoggedIn: null,
  12. token: '',
  13. logInError: false,
  14. userProfile: null,
  15. dashboardMiniDrawer: false,
  16. dashboardShowDrawer: true,
  17. notifications: [],
  18. videos: [],
  19. images: [],
  20. videosWebSocket: new WebSocket(`${wsUrl}/api/v1/videos`)
  21. };
  22. export const useMainStore = defineStore("MainStoreId", {
  23. state: () => defaultState,
  24. getters: {
  25. readhasAdminAccess: (state) =>
  26. state.userProfile && state.userProfile.is_superuser && state.userProfile.is_active,
  27. readLoginError: (state) => state.logInError,
  28. readDashboardShowDrawer: (state) => state.dashboardShowDrawer,
  29. readDashboardMiniDrawer: (state) => state.dashboardMiniDrawer,
  30. readUserProfile: (state) => state.userProfile,
  31. readToken: (state) => state.token,
  32. readIsLoggedIn: (state) => state.isLoggedIn,
  33. readFirstNotification: (state) => state.notifications.length > 0 && state.notifications[0],
  34. readVideos: (state) => state.videos,
  35. },
  36. actions: {
  37. // setters
  38. setToken(payload: string) { this.token = payload; },
  39. setLoggedIn(payload: boolean) { this.isLoggedIn = payload; },
  40. setLogInError(payload: boolean) { this.logInError = payload; },
  41. setUserProfile(payload: IUserProfile) { this.userProfile = payload },
  42. setDashboardMiniDrawer(payload: boolean) { this.dashboardMiniDrawer = payload; },
  43. setDashboardShowDrawer(payload: boolean) { this.dashboardShowDrawer = payload; },
  44. setVideos(payload: Video[]) { this.videos = payload },
  45. addNotification(payload: AppNotification) { this.notifications.push(payload); },
  46. removeNotification(payload: AppNotification) {
  47. if (payload) {
  48. this.notifications = this.notifications.filter(
  49. (notification) => notification !== payload,
  50. );
  51. }
  52. },
  53. // actions
  54. async logIn(username: string, password: string) {
  55. try {
  56. const response = await api.logInGetToken(username, password);
  57. const token: string = response.data.access_token;
  58. localStorage.setItem('email', username);
  59. if (token) {
  60. saveLocalToken(token);
  61. this.setToken(token);
  62. this.setLoggedIn(true);
  63. this.setLogInError(false);
  64. await this.getUserProfile();
  65. await this.routeLoggedIn();
  66. this.addNotification({ content: i18n.global.t("loggedIn"), color: "success" });
  67. } else {
  68. await this.logOut();
  69. }
  70. } catch (err) {
  71. this.addNotification({ content: i18n.global.t("loggedError"), color: "error" });
  72. this.setLogInError(true);
  73. await this.logOut();
  74. }
  75. },
  76. async qrLogIn(username: string, password: string, ser_no: string) {
  77. try {
  78. const response = await api.qrLogInGetToken(username, password, ser_no);
  79. return response;
  80. } catch (error) {
  81. console.log('error', error);
  82. }
  83. },
  84. async googleLogin(username: string) {
  85. try {
  86. const response = await api.googleLogin(username);
  87. const token: string = response.data.access_token;
  88. if (token) {
  89. saveLocalToken(token);
  90. this.setToken(token);
  91. this.setLoggedIn(true);
  92. this.setLogInError(false);
  93. await this.getUserProfile();
  94. await this.routeLoggedIn();
  95. this.addNotification({ content: i18n.global.t("loggedIn"), color: "success" });
  96. } else {
  97. await this.logOut();
  98. }
  99. } catch (err) {
  100. this.setLogInError(true);
  101. await this.logOut();
  102. }
  103. },
  104. async qrGoogleLogin(username: string, ser_no: string) {
  105. try {
  106. const response = await api.qrGoogleLogin(username, ser_no);
  107. return response;
  108. } catch (error) {
  109. console.log('error', error);
  110. }
  111. },
  112. async qrAddTime(code: string) {
  113. try {
  114. const response = await api.qrAddTime(this.token, code);
  115. return response;
  116. } catch (error) {
  117. console.log('error', error);
  118. return error;
  119. }
  120. },
  121. async getUserProfile() {
  122. try {
  123. const response = await api.getMe(this.token);
  124. if (response.data) {
  125. this.setUserProfile(response.data);
  126. }
  127. } catch (error) {
  128. await this.checkApiError(error);
  129. }
  130. },
  131. async updateUserProfile(payload: IUserProfileUpdate) {
  132. try {
  133. const loadingNotification = { content: i18n.global.t("saving"), showProgress: true };
  134. await this.addNotification(loadingNotification);
  135. const response = (
  136. await Promise.all([
  137. api.updateMe(this.token, payload),
  138. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
  139. ])
  140. )[0];
  141. this.setUserProfile(response.data);
  142. this.removeNotification(loadingNotification);
  143. this.addNotification({
  144. content: i18n.global.t("profileUpdated"),
  145. color: "success",
  146. });
  147. } catch (error) {
  148. await this.checkApiError(error);
  149. }
  150. },
  151. async checkLoggedIn() {
  152. if (!this.isLoggedIn) {
  153. let token = this.token;
  154. if (!token) {
  155. const localToken = getLocalToken();
  156. if (localToken) {
  157. this.setToken(localToken);
  158. token = localToken;
  159. }
  160. }
  161. if (token) {
  162. try {
  163. const response = await api.getMe(token);
  164. this.setLoggedIn(true);
  165. this.setUserProfile(response.data);
  166. // router.push("/main/dashboard");
  167. // 取得網址路徑
  168. const currentPath = window.location.pathname;
  169. if (currentPath === "/login") {
  170. router.push("/main/dashboard");
  171. } else {
  172. // 跳轉至目前路徑
  173. router.push(currentPath);
  174. }
  175. } catch (error) {
  176. await this.removeLogIn();
  177. }
  178. } else {
  179. await this.removeLogIn();
  180. }
  181. }
  182. },
  183. async cancelCheckLoggedIn() {
  184. if (!this.isLoggedIn) {
  185. let token = this.token;
  186. if (!token) {
  187. const localToken = getLocalToken();
  188. if (localToken) {
  189. this.setToken(localToken);
  190. token = localToken;
  191. }
  192. }
  193. if (token) {
  194. try {
  195. const response = await api.getMe(token);
  196. this.setLoggedIn(true);
  197. this.setUserProfile(response.data);
  198. // router.push("/main/dashboard");
  199. } catch (error) {
  200. await this.removeLogIn();
  201. }
  202. } else {
  203. await this.removeLogIn();
  204. }
  205. }
  206. },
  207. async removeLogIn() {
  208. removeLocalToken();
  209. this.setToken("");
  210. this.setLoggedIn(false);
  211. },
  212. async logOut() {
  213. await this.removeLogIn();
  214. this.routeLogOut();
  215. },
  216. async userLogOut() {
  217. await this.logOut();
  218. this.addNotification({ content: "Logged out", color: "success" });
  219. },
  220. routeLogOut() {
  221. if (router.currentRoute.value.path !== "/login") {
  222. router.push("/login");
  223. }
  224. },
  225. async checkApiError(payload: unknown) {
  226. if (axios.isAxiosError(payload)) {
  227. if (payload.response?.status === 401) {
  228. await this.logOut();
  229. }
  230. }
  231. },
  232. routeLoggedIn() {
  233. if (router.currentRoute.value.path === "/login" || router.currentRoute.value.path === "/") {
  234. router.push("/main/dashboard");
  235. }
  236. },
  237. async dispatchRemoveNotification(payload: { notification: AppNotification; timeout: number },) {
  238. return new Promise((resolve, _) => {
  239. setTimeout(() => {
  240. this.removeNotification(payload.notification);
  241. resolve(true);
  242. }, payload.timeout);
  243. });
  244. },
  245. async register(payload: IUserProfileCreate) {
  246. const loadingNotification = {
  247. content: i18n.global.t("signingUp"),
  248. showProgress: true,
  249. };
  250. try {
  251. this.addNotification(loadingNotification);
  252. const response = (
  253. await Promise.all([
  254. api.registerUser(payload),
  255. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
  256. ])
  257. )[0];
  258. this.removeNotification(loadingNotification);
  259. this.addNotification({
  260. content: i18n.global.t("registerSuccess"),
  261. color: "success",
  262. });
  263. setTimeout(() => {
  264. router.push("/login")
  265. }, 2000)
  266. } catch (error) {
  267. this.addNotification({ content: i18n.global.t("registerError"), color: "error" });
  268. await this.checkApiError(error);
  269. }
  270. },
  271. async passwordRecovery(username: string) {
  272. const loadingNotification = {
  273. content: i18n.global.t("sendingEmail"),
  274. showProgress: true,
  275. };
  276. try {
  277. this.addNotification(loadingNotification);
  278. await Promise.all([
  279. api.passwordRecovery(username),
  280. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
  281. ]);
  282. this.removeNotification(loadingNotification);
  283. this.addNotification({
  284. content: i18n.global.t("passwordMailSent"),
  285. color: "success",
  286. });
  287. await this.logOut();
  288. } catch (error) {
  289. this.removeNotification(loadingNotification);
  290. this.addNotification({ color: "error", content: i18n.global.t("incorrectUsername") });
  291. }
  292. },
  293. async resetPassword(password: string, token: string) {
  294. const loadingNotification = { content: "Resetting password", showProgress: true };
  295. try {
  296. this.addNotification(loadingNotification);
  297. await Promise.all([
  298. api.resetPassword(token, password),
  299. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
  300. ]);
  301. this.removeNotification(loadingNotification);
  302. this.addNotification({
  303. content: "Password successfully reset",
  304. color: "success",
  305. });
  306. await this.logOut();
  307. } catch (error) {
  308. this.removeNotification(loadingNotification);
  309. this.addNotification({
  310. color: "error",
  311. content: "Error resetting password",
  312. });
  313. }
  314. },
  315. async uploadPlot(video_data: VideoCreate, file: File) {
  316. const mainStore = useMainStore();
  317. try {
  318. const loadingNotification = { content: i18n.global.t("sending"), showProgress: true };
  319. mainStore.addNotification(loadingNotification);
  320. const response = (
  321. await Promise.all([
  322. await api.uploadPlot(mainStore.token, video_data, file),
  323. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  324. ])
  325. );
  326. mainStore.removeNotification(loadingNotification);
  327. if (response[0].data.accepted !== false) {
  328. mainStore.addNotification({
  329. content: i18n.global.t("fileReceived"),
  330. color: "success",
  331. })
  332. } else {
  333. mainStore.addNotification({
  334. content: i18n.global.t("uploadFailed"),
  335. color: "error",
  336. })
  337. }
  338. // mainStore.removeNotification(loadingNotification);
  339. // mainStore.addNotification({
  340. // content: i18n.global.t("fileReceived"),
  341. // color: "success",
  342. // })
  343. this.actionGetVideos();
  344. return response[0].data;
  345. } catch (error) {
  346. await mainStore.checkApiError(error);
  347. }
  348. const ret: VideoUploaded = { accepted: false, error_message: "api error", video_info: null }
  349. return ret
  350. },
  351. async uploadImage(file: File[]) {
  352. const mainStore = useMainStore();
  353. try {
  354. // const loadingNotification = { content: i18n.global.t("sending"), showProgress: true };
  355. // mainStore.addNotification(loadingNotification);
  356. const response = (
  357. await Promise.all([
  358. api.uploadImage(mainStore.token, file),
  359. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  360. ]).then(data => {
  361. for (let i = 0; i < data[0].data.filenames.length; i++) {
  362. const element = data[0].data.filenames[i];
  363. const tmpImage: Image = {
  364. file_name: file[i].name,
  365. stored_file_name: element,
  366. content: "sr",
  367. state: "subscribe",
  368. link: ""
  369. };
  370. this.addImage(tmpImage);
  371. }
  372. // localStorage.setItem('imagesList', JSON.stringify(this.images));
  373. })
  374. );
  375. // mainStore.removeNotification(loadingNotification);
  376. mainStore.addNotification({
  377. content: i18n.global.t("fileReceived"),
  378. color: "success",
  379. })
  380. // this.actionGetVideos();
  381. } catch (error) {
  382. await mainStore.checkApiError(error);
  383. }
  384. },
  385. async generateZip(model: string, list: string[]) {
  386. const mainStore = useMainStore();
  387. try {
  388. const response = (
  389. await Promise.all([
  390. api.generateZip(mainStore.token, model, list),
  391. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  392. ]).then(data => {
  393. return data;
  394. })
  395. );
  396. return response;
  397. // mainStore.addNotification({
  398. // content: i18n.global.t("fileReceived"),
  399. // color: "success",
  400. // })
  401. } catch (error) {
  402. await mainStore.checkApiError(error);
  403. }
  404. },
  405. async generateVideo(data: genVideoData, list: string[]) {
  406. const mainStore = useMainStore();
  407. try {
  408. const response = (
  409. await Promise.all([
  410. api.generateVideo(data, list),
  411. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  412. ]).then(data => {
  413. return data;
  414. })
  415. );
  416. return response;
  417. // mainStore.addNotification({
  418. // content: i18n.global.t("fileReceived"),
  419. // color: "success",
  420. // })
  421. } catch (error) {
  422. await mainStore.checkApiError(error);
  423. }
  424. },
  425. // async getImage(data: ImageDownload) {
  426. // const mainStore = useMainStore();
  427. // try {
  428. // const response = (
  429. // await Promise.all([
  430. // api.getImage(mainStore.token, data),
  431. // await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  432. // ])
  433. // );
  434. // } catch (error) {
  435. // await mainStore.checkApiError(error);
  436. // }
  437. // },
  438. addImage(payload: Image) {
  439. this.images.push(payload);
  440. },
  441. async finishImage(payload: ImageDownload) {
  442. const WS = new WebSocket(`${wsUrl}/api/v1/images/sr`);
  443. let image = this.images.filter(e => {
  444. return payload.stored_file_name.includes(e.stored_file_name)
  445. });
  446. const mainStore = useMainStore();
  447. try {
  448. const response = await api.downloadImage(mainStore.token, payload);
  449. if (image) {
  450. image.map(e => {
  451. e.state = "completed";
  452. e.link = response.data;
  453. })
  454. }
  455. } catch (error) {
  456. await mainStore.checkApiError(error);
  457. }
  458. // 全部完成後回傳 WebSocket
  459. let processing = this.images.find(e => e.state !== "completed");
  460. if (!processing) {
  461. setTimeout(() => {
  462. // WS.close();
  463. WS.send("unsubscribe");
  464. }, 1000)
  465. }
  466. return !this.images.some(e => e.state === "completed")
  467. },
  468. async uploadArticle(article_data: ArticleCreate) {
  469. const mainStore = useMainStore();
  470. try {
  471. const loadingNotification = { content: i18n.global.t("sending"), showProgress: true };
  472. mainStore.addNotification(loadingNotification);
  473. const response = (
  474. await Promise.all([
  475. api.uploadArticle(mainStore.token, article_data),
  476. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  477. ])
  478. );
  479. mainStore.removeNotification(loadingNotification);
  480. mainStore.addNotification({
  481. content: i18n.global.t("fileReceived"),
  482. color: "success",
  483. })
  484. // this.actionGetVideos();
  485. } catch (error) {
  486. await mainStore.checkApiError(error);
  487. }
  488. },
  489. async actionGetVideos() {
  490. const mainStore = useMainStore();
  491. try {
  492. const response = await api.getVideos(mainStore.token)
  493. if (response) {
  494. this.setVideos(response.data);
  495. }
  496. } catch (error) {
  497. await mainStore.checkApiError(error);
  498. }
  499. },
  500. async ecpayPaymentHTML(amount: number) {
  501. const mainStore = useMainStore();
  502. try {
  503. const response = await api.ecpayPaymentHTML(mainStore.token, amount)
  504. if (response) {
  505. return response.data;
  506. }
  507. } catch (error) {
  508. await mainStore.checkApiError(error);
  509. }
  510. },
  511. async YTViewsTestPayment(user_data: YTViewsUserData, lang: string) {
  512. const mainStore = useMainStore();
  513. try {
  514. const response = (
  515. await Promise.all([
  516. api.YTViewsTestPayment(user_data, lang),
  517. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  518. ])
  519. );
  520. if (response[0]) {
  521. return response[0].data;
  522. }
  523. } catch (error) {
  524. await mainStore.checkApiError(error);
  525. }
  526. },
  527. async YTViewsPayment(user_data: YTViewsUserData, lang: string) {
  528. const mainStore = useMainStore();
  529. try {
  530. const response = (
  531. await Promise.all([
  532. api.YTViewsPayment(user_data, lang),
  533. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  534. ])
  535. );
  536. if (response[0]) {
  537. return response[0].data;
  538. }
  539. } catch (error) {
  540. await mainStore.checkApiError(error);
  541. }
  542. },
  543. async getYTViewsList() {
  544. const mainStore = useMainStore();
  545. try {
  546. const response = await api.getYTViewsList();
  547. if (response) {
  548. return response.data;
  549. }
  550. } catch (error) {
  551. await mainStore.checkApiError(error);
  552. }
  553. },
  554. async TestPayment(payment_data: PaymentData, lang: string) {
  555. const mainStore = useMainStore();
  556. try {
  557. const response = (
  558. await Promise.all([
  559. api.TestPayment(payment_data, mainStore.token, lang),
  560. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  561. ])
  562. );
  563. if (response[0]) {
  564. return response[0].data;
  565. }
  566. } catch (error) {
  567. await mainStore.checkApiError(error);
  568. }
  569. },
  570. async Payment(payment_data: PaymentData, lang: string) {
  571. const mainStore = useMainStore();
  572. try {
  573. const response = (
  574. await Promise.all([
  575. api.Payment(payment_data, mainStore.token, lang),
  576. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  577. ])
  578. );
  579. if (response[0]) {
  580. return response[0].data;
  581. }
  582. } catch (error) {
  583. await mainStore.checkApiError(error);
  584. }
  585. },
  586. async getPaymentList() {
  587. const mainStore = useMainStore();
  588. try {
  589. const response = await api.getYTViewsList();
  590. if (response) {
  591. return response.data;
  592. }
  593. } catch (error) {
  594. await mainStore.checkApiError(error);
  595. }
  596. },
  597. async simplePayment(payment_data: SimplePaymentData, lang: string) {
  598. const mainStore = useMainStore();
  599. try {
  600. const response = (
  601. await Promise.all([
  602. api.simplePayment(payment_data, lang),
  603. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  604. ])
  605. );
  606. if (response[0]) {
  607. console.log('simplePayment', response);
  608. return response[0].data;
  609. }
  610. } catch (error) {
  611. await mainStore.checkApiError(error);
  612. }
  613. },
  614. async uploadVideoContent(content: VideoContent, file: []) {
  615. let jsonContent = JSON.stringify(content);
  616. const mainStore = useMainStore();
  617. try {
  618. const response = await api.uploadVideoContent(jsonContent, file);
  619. console.log('uploadVideoContent response', response);
  620. if (response) {
  621. return response.data;
  622. }
  623. } catch (error) {
  624. console.log('error', error);
  625. // await mainStore.checkApiError(error);
  626. }
  627. },
  628. async zipTranslate(lang: string, file: File) {
  629. const mainStore = useMainStore();
  630. try {
  631. const response = (
  632. await Promise.all([
  633. api.zipTranslate(lang, file),
  634. await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 0)),
  635. ]).then(data => {
  636. return data;
  637. })
  638. );
  639. return response;
  640. } catch (error) {
  641. await mainStore.checkApiError(error);
  642. }
  643. },
  644. }
  645. });