cc12458 1 месяц назад
Родитель
Сommit
88de270fc9
8 измененных файлов с 101 добавлено и 5 удалено
  1. 6 0
      @types/global.d.ts
  2. 2 1
      src/polyfill.ts
  3. 3 2
      src/request/api/camera.api.ts
  4. 5 0
      src/themes/fix.scss
  5. 2 0
      src/themes/index.scss
  6. 5 2
      src/themes/vant.scss
  7. 75 0
      src/tools/file.ts
  8. 3 0
      src/tools/polyfills.ts

+ 6 - 0
@types/global.d.ts

@@ -24,6 +24,12 @@ declare global {
     };
     };
   }
   }
 
 
+  interface PromiseWithResolvers<T> {
+    promise: Promise<T>;
+    resolve: (value: T | PromiseLike<T>) => void;
+    reject: (reason?: any) => void;
+  }
+
   interface Array<T> {
   interface Array<T> {
     at(index: number): T;
     at(index: number): T;
   }
   }

+ 2 - 1
src/polyfill.ts

@@ -8,8 +8,9 @@ if (typeof Promise.withResolvers !== 'function') {
       reject = rej;
       reject = rej;
     });
     });
 
 
-    return { promise, resolve, reject };
+    return { promise, resolve, reject } as PromiseWithResolvers<T>;
   };
   };
+  Object.defineProperty(Promise, 'withResolvers', {});
 }
 }
 
 
 if (typeof Array.prototype.at !== 'function') {
 if (typeof Array.prototype.at !== 'function') {

+ 3 - 2
src/request/api/camera.api.ts

@@ -2,9 +2,10 @@ import HTTP              from '@/request/alova';
 import { useVisitor }    from '@/stores';
 import { useVisitor }    from '@/stores';
 
 
 
 
-export function uploadFileMethod(file: File) {
+export function uploadFileMethod(file: File, name?: string) {
   const formData = new FormData();
   const formData = new FormData();
-  formData.append('file', file);
+  if (name) formData.append('file', file, name);
+  else formData.append('file', file);
   return HTTP.Post<{ name: string; url: string }>(`/file/upload`, formData, {});
   return HTTP.Post<{ name: string; url: string }>(`/file/upload`, formData, {});
 }
 }
 
 

+ 5 - 0
src/themes/fix.scss

@@ -1,5 +1,10 @@
 .page-header {
 .page-header {
+  min-height: var(--page-header-heigth);
   > div:not(.grow-\[3\]) {
   > div:not(.grow-\[3\]) {
     flex-grow: 0;
     flex-grow: 0;
   }
   }
+}
+
+:root:root {
+  --page-header-heigth: 68px;
 }
 }

+ 2 - 0
src/themes/index.scss

@@ -27,4 +27,6 @@
 :root:root {
 :root:root {
   --primary-color: #34a76b;
   --primary-color: #34a76b;
   --primary-color-hover: #38ff6e;
   --primary-color-hover: #38ff6e;
+  --primary: 149 53% 43%;
+  --primary-hover: 136 100% 61%;
 }
 }

+ 5 - 2
src/themes/vant.scss

@@ -10,15 +10,18 @@
   .page-content {
   .page-content {
     background-color: #0f2925;
     background-color: #0f2925;
   }
   }
+
 }
 }
 
 
 :root:root {
 :root:root {
-  --van-primary-color: #38ff6e;
+  --van-primary-color: var(--primary-color);
   --van-background-2: #0f2925;
   --van-background-2: #0f2925;
+  --van-border-color: #12312c;
+  --van-active-color: #12312c;
+  --van-text-color-3: #818181;
   --van-text-color: #fff;
   --van-text-color: #fff;
   --van-notify-font-size: 1.6rem;
   --van-notify-font-size: 1.6rem;
   --van-notify-line-height: 2rem;
   --van-notify-line-height: 2rem;
-
   --van-number-keyboard-key-height: 60px;
   --van-number-keyboard-key-height: 60px;
 }
 }
 
 

+ 75 - 0
src/tools/file.ts

@@ -0,0 +1,75 @@
+export function fileToBase64(file: File): Promise<string> {
+  return blobToBase64(file);
+}
+
+export function blobToBase64(blob: Blob, fast = true): Promise<string> {
+  return fast
+    ? blob
+        .arrayBuffer()
+        .then((buffer) => new Uint8Array(buffer))
+        .then((bytes) => {
+          let binary = '';
+          for (const byte of bytes) binary += String.fromCharCode(byte);
+          return `data:${blob.type};base64,${btoa(binary)}`;
+        })
+    : new Promise((resolve, reject) => {
+        const reader = new FileReader();
+        reader.onload = () => resolve(reader.result as string);
+        reader.onerror = reject;
+        reader.readAsDataURL(blob);
+      });
+}
+
+export function blobToFile(blob: Blob, filename?: string): File {
+  return new File([blob], filename ?? 'file', { type: blob.type });
+}
+
+export function base64ToBlob(base64: string): Blob {
+  const [header, data] = base64.split(',');
+
+  const mimeMatch = header.match(/:(.*?);/);
+  const mime = mimeMatch ? mimeMatch[1] : '';
+
+  const binary = atob(data);
+  const len = binary.length;
+  const buffer = new Uint8Array(len);
+
+  for (let i = 0; i < len; i++) buffer[i] = binary.charCodeAt(i);
+
+  return new Blob([buffer], { type: mime });
+}
+
+export function base64ToFile(base64: string, filename?: string): File {
+  const blob = base64ToBlob(base64);
+  return blobToFile(blob, filename);
+}
+
+export type TargetType = 'file' | 'blob' | 'base64';
+
+type ConvertResult<T extends TargetType> = T extends 'file' ? File : T extends 'blob' ? Blob : T extends 'base64' ? string : never;
+
+async function convert<T extends TargetType>(input: File | Blob | string, type: T, options?: { fast?: boolean; filename?: string }): Promise<ConvertResult<T>> {
+  switch (type) {
+    case 'blob': {
+      if (typeof input === 'string') input = base64ToBlob(input);
+      break;
+    }
+    case 'file': {
+      if (input instanceof File) break;
+      if (typeof input === 'string') input = base64ToFile(input, options?.filename);
+      else input = blobToFile(input, options?.filename);
+      break;
+    }
+    case 'base64': {
+      if (typeof input === 'string') break;
+      if (input instanceof File) input = await fileToBase64(input);
+      else if (input instanceof Blob) input = await blobToBase64(input, options?.fast);
+      break;
+    }
+    default:
+      throw new Error('Unsupported type');
+  }
+  return input as ConvertResult<T>;
+}
+
+export default convert;

+ 3 - 0
src/tools/polyfills.ts

@@ -1,4 +1,7 @@
 // @ts-nocheck
 // @ts-nocheck
+/**
+ * @deprecated Promise.withResolvers
+ */
 export function withResolvers<T>(): {
 export function withResolvers<T>(): {
   promise: Promise<T>;
   promise: Promise<T>;
   resolve: (value: T | PromiseLike<T>) => void;
   resolve: (value: T | PromiseLike<T>) => void;