Browse Source

feat(初始化): 首次提交

zdc 2 years ago
commit
62e8237024
100 changed files with 2498 additions and 0 deletions
  1. 12 0
      .editorconfig
  2. 7 0
      .eslintrc
  3. 6 0
      .gitignore
  4. BIN
      .swc/plugins/v4/200063c2c798457e0f441f309e564fe9e258e1dcb142b8c6a1df1cbb41ae9bd9
  5. 31 0
      babel.config.js
  6. 20 0
      cmd/api_generate/.gitignore
  7. 35 0
      cmd/api_generate/base/interface.ts
  8. 19 0
      cmd/api_generate/dc/userApi.ts
  9. 11 0
      cmd/api_generate/dc_boss.ts
  10. 8 0
      cmd/api_generate/interface/api_generate_impl.ts
  11. 26 0
      cmd/api_generate/json2entity.ts
  12. 18 0
      cmd/api_generate/package.json
  13. 103 0
      cmd/api_generate/tsconfig.json
  14. 254 0
      cmd/api_generate/utils/docUtill.ts
  15. 252 0
      cmd/api_generate/utils/docUtillTs.ts
  16. 39 0
      cmd/start.ts
  17. 11 0
      config/dev.js
  18. 95 0
      config/index.js
  19. 37 0
      config/prod.js
  20. 86 0
      package.json
  21. 15 0
      project.config.json
  22. 9 0
      project.tt.json
  23. 23 0
      src/apis/userApi.ts
  24. 18 0
      src/app.config.ts
  25. 23 0
      src/app.scss
  26. 48 0
      src/app.tsx
  27. 0 0
      src/appConfig.ts
  28. BIN
      src/assets/home_logo.png
  29. BIN
      src/assets/icon_home_back.png
  30. BIN
      src/assets/icon_home_characteristic.png
  31. BIN
      src/assets/icon_home_characteristic_b_0.png
  32. BIN
      src/assets/icon_home_characteristic_b_1.png
  33. BIN
      src/assets/icon_home_characteristic_b_2.png
  34. BIN
      src/assets/icon_home_characteristic_b_3.png
  35. BIN
      src/assets/icon_home_characteristic_i_0.png
  36. BIN
      src/assets/icon_home_characteristic_i_1.png
  37. BIN
      src/assets/icon_home_characteristic_i_2.png
  38. BIN
      src/assets/icon_home_characteristic_i_3.png
  39. BIN
      src/assets/icon_home_process.png
  40. BIN
      src/assets/icon_home_process_capital.png
  41. BIN
      src/assets/icon_home_process_data.png
  42. BIN
      src/assets/icon_home_process_qualifications.png
  43. BIN
      src/assets/icon_mine_aggrement.png
  44. BIN
      src/assets/icon_mine_avatar.png
  45. BIN
      src/assets/icon_mine_back.png
  46. BIN
      src/assets/icon_mine_business.png
  47. BIN
      src/assets/icon_mine_service.png
  48. BIN
      src/assets/icon_mine_setting.png
  49. BIN
      src/assets/icon_mine_upgrade.png
  50. BIN
      src/assets/logo.png
  51. 19 0
      src/component/button/index.scss
  52. 29 0
      src/component/button/index.tsx
  53. 72 0
      src/component/flex/index.scss
  54. 90 0
      src/component/flex/index.tsx
  55. 39 0
      src/component/label/index.scss
  56. 26 0
      src/component/label/index.tsx
  57. 0 0
      src/component/layout/index.scss
  58. 38 0
      src/component/layout/index.tsx
  59. 0 0
      src/component/net-image/index.scss
  60. 40 0
      src/component/net-image/index.tsx
  61. 15 0
      src/component/padding/index.scss
  62. 65 0
      src/component/padding/index.tsx
  63. 24 0
      src/component/routes/hooks/useDidShow.ts
  64. 18 0
      src/component/routes/hooks/useParams.ts
  65. 4 0
      src/component/routes/index.less
  66. 76 0
      src/component/routes/index.tsx
  67. 25 0
      src/component/routes/provider/route.tsx
  68. 15 0
      src/component/sizeBox/index.tsx
  69. 9 0
      src/config/index.d.ts
  70. 4 0
      src/config/index.js
  71. 17 0
      src/context/appContext.tsx
  72. 17 0
      src/index.html
  73. 4 0
      src/pages/home/index.config.ts
  74. 52 0
      src/pages/home/index.scss
  75. 112 0
      src/pages/home/index.tsx
  76. 3 0
      src/pages/index/index.config.ts
  77. 4 0
      src/pages/index/index.scss
  78. 0 0
      src/pages/index/index.tsx
  79. 3 0
      src/pages/template/index.config.ts
  80. 4 0
      src/pages/template/index.scss
  81. 0 0
      src/pages/template/index.tsx
  82. 4 0
      src/pages/user/login/index.config.ts
  83. 16 0
      src/pages/user/login/index.scss
  84. 44 0
      src/pages/user/login/index.tsx
  85. 4 0
      src/pages/user/mine/index.config.ts
  86. 27 0
      src/pages/user/mine/index.scss
  87. 55 0
      src/pages/user/mine/index.tsx
  88. 3 0
      src/pages/user/setting/index.config.ts
  89. 4 0
      src/pages/user/setting/index.scss
  90. 29 0
      src/pages/user/setting/index.tsx
  91. 13 0
      src/pages/web/index.tsx
  92. 6 0
      src/routes/route.d.ts
  93. 17 0
      src/routes/route.h5.ts
  94. 2 0
      src/routes/route.weapp.ts
  95. 28 0
      src/style/mixin.scss
  96. 37 0
      src/style/variable.scss
  97. 8 0
      src/utils/imgUtils.ts
  98. 42 0
      src/utils/modalUtil.ts
  99. 103 0
      src/utils/request.ts
  100. 26 0
      src/utils/routeUtil.ts

+ 12 - 0
.editorconfig

@@ -0,0 +1,12 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false

+ 7 - 0
.eslintrc

@@ -0,0 +1,7 @@
+{
+  "extends": ["taro/react"],
+  "rules": {
+    "react/jsx-uses-react": "off",
+    "react/react-in-jsx-scope": "off"
+  }
+}

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
+dist/
+deploy_versions/
+.temp/
+.rn_temp/
+node_modules/
+.DS_Store

BIN
.swc/plugins/v4/200063c2c798457e0f441f309e564fe9e258e1dcb142b8c6a1df1cbb41ae9bd9


+ 31 - 0
babel.config.js

@@ -0,0 +1,31 @@
+// babel-preset-taro 更多选项和默认值:
+// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
+module.exports = {
+  presets: [
+    ['taro', {
+      framework: 'react',
+      ts: true
+    }]
+  ],
+  plugins: [
+    [
+      "import",
+      {
+        libraryName: "@taroify/core",
+        libraryDirectory: "",
+        style: true,
+      },
+      "@taroify/core",
+    ],
+    [
+      "import",
+      {
+        libraryName: "@taroify/icons",
+        libraryDirectory: "",
+        camel2DashComponentName: false,
+        style: () => "@taroify/icons/style",
+      },
+      "@taroify/icons",
+    ],
+  ]
+}

+ 20 - 0
cmd/api_generate/.gitignore

@@ -0,0 +1,20 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/npm-debug.log*
+/yarn-error.log
+/yarn.lock
+/package-lock.json
+
+# production
+/dist
+
+# misc
+.DS_Store
+
+# umi
+/src/.umi
+/src/.umi-production
+/src/.umi-test
+/.env.local

+ 35 - 0
cmd/api_generate/base/interface.ts

@@ -0,0 +1,35 @@
+
+
+export enum IMethod {
+    "post",
+    "put",
+    "get",
+    "delete"
+}
+
+export type IParamsTypeEnum = "String" | "bool" | "num" | "DateTime" | "object" | "list" | "enum" | "int" | "double" | "dynamic";
+export type IParamsTypeEnum1 = "String" | "bool" | "num" | "DateTime" | "int" | "double";
+
+export type IParamsType = {
+    type: IParamsTypeEnum, jsonKey?: string, required?: boolean, desc?: string, enum?: Record<string, string | number>, child?: Record<string, IParamsType> | "String" | "bool" | "num" | "DateTime" | "double" | "int",
+    final?: boolean,
+    url?: boolean
+};
+
+export interface IApiDocFuncInterface {
+    body?: Record<string, IParamsType>;
+    params?: Record<string, IParamsType>;
+    response?: Record<string, IParamsType> | IParamsTypeEnum1 | [Record<string, IParamsType> | IParamsTypeEnum1];
+}
+
+export interface IApiDocInterface {
+    [key: string]: {
+        funcName: string;
+        desc?: string;
+        contentType?: "json" | "urlencoded" | "formData",
+        "post"?: IApiDocFuncInterface;
+        "put"?: IApiDocFuncInterface;
+        "delete"?: IApiDocFuncInterface;
+        "get"?: IApiDocFuncInterface;
+    };
+}

+ 19 - 0
cmd/api_generate/dc/userApi.ts

@@ -0,0 +1,19 @@
+import { IApiDocInterface } from "../base/interface";
+
+const userApiDoc: IApiDocInterface = {
+    "/adm/account/verificationCode": {
+        funcName: "getCode",
+        desc: "获取验证码",
+        post: {
+            // params: {
+            //     type: { type: "num", desc: "查询类型 0:查询全部(不传时默认),1:查询充值可用币种,2:查询提现可用币种", required: true, },
+            // },
+            response: {
+                imgToken: { type: "String", desc: "图片token", required: true, },
+                verification: { type: "String", desc: "验证码", required: true, },
+            }
+        }
+    },
+}
+
+export default userApiDoc;

+ 11 - 0
cmd/api_generate/dc_boss.ts

@@ -0,0 +1,11 @@
+import userApiDoc from "./dc/userApi";
+import DocUtilTs from "./utils/docUtillTs";
+
+new DocUtilTs(
+    {
+        filePath: "./src/apis",
+        fileName: "userApi",
+        name: "UserApi",
+        doc: userApiDoc,
+    }
+);

+ 8 - 0
cmd/api_generate/interface/api_generate_impl.ts

@@ -0,0 +1,8 @@
+import { IApiDocInterface } from "../base/interface";
+
+export default interface ApiGenerateImpl {
+    filePath: string;
+    name: string;
+    fileName: string;
+    doc: IApiDocInterface;
+}

+ 26 - 0
cmd/api_generate/json2entity.ts

@@ -0,0 +1,26 @@
+// { type: "num", desc: "查询类型 0:查询全部(不传时默认),1:查询充值可用币种,2:查询提现可用币种", required: true, }
+import ncp from "copy-paste";
+import { IParamsType } from "./base/interface";
+import DocUtil from "./utils/docUtill";
+
+let res = ncp.paste();
+console.log(JSON, res);
+console.log(JSON.parse(res));
+let obj = JSON.parse(res);
+
+let result: Record<string, IParamsType> = {};
+
+Object.entries(obj).forEach(p => {
+    let required = p != null;
+    let type = !required ? null : typeof (p[1]) as any;
+    if (type === "string") {
+        type = DocUtil.firstUpper(type);
+    }
+    result[p[0]] = { required, type, desc: "" };
+    if (required === true) {
+        delete result[p[0]].required;
+    }
+})
+
+console.log(333, result);
+

+ 18 - 0
cmd/api_generate/package.json

@@ -0,0 +1,18 @@
+{
+  "name": "api_generate",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "@types/copy-paste": "^1.1.30",
+    "@types/lodash": "^4.14.191",
+    "@types/node": "^18.0.6",
+    "copy-paste": "^1.3.0",
+    "qs": "^6.11.0"
+  }
+}

+ 103 - 0
cmd/api_generate/tsconfig.json

@@ -0,0 +1,103 @@
+{
+  "compilerOptions": {
+    /* Visit https://aka.ms/tsconfig to read more about this file */
+
+    /* Projects */
+    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
+    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
+    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
+    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
+    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
+
+    /* Language and Environment */
+    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
+    // "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
+    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
+    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
+    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
+    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
+
+    /* Modules */
+    "module": "commonjs",                                /* Specify what module code is generated. */
+    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
+    // "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
+    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
+    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
+    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
+    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
+    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
+    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
+    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
+    // "resolveJsonModule": true,                        /* Enable importing .json files. */
+    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
+
+    /* JavaScript Support */
+    // "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
+    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+    /* Emit */
+    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
+    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
+    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
+    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+    // "outDir": "./",                                   /* Specify an output folder for all emitted files. */
+    // "removeComments": true,                           /* Disable emitting comments. */
+    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
+    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
+    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
+    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
+    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
+    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
+    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
+    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
+    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
+    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
+    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+    /* Interop Constraints */
+    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
+    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
+    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
+    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
+
+    /* Type Checking */
+    "strict": true,                                      /* Enable all strict type-checking options. */
+    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
+    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
+    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
+    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
+    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
+    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
+    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
+    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
+    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
+    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
+    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
+    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
+    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
+    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
+    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
+
+    /* Completeness */
+    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
+    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
+  }
+}

+ 254 - 0
cmd/api_generate/utils/docUtill.ts

@@ -0,0 +1,254 @@
+import fs from 'fs';
+import { IApiDocFuncInterface, IParamsType } from "../base/interface";
+import ApiGenerateImpl from "../interface/api_generate_impl";
+import { execSync } from 'child_process';
+
+export default class DocUtil {
+
+    static runner(app: string) {
+        execSync("cd ../" + app + " && flutter pub run build_runner build ");
+    }
+
+
+    static firstUpper(name: string) {
+        let nameSpilit = name.split("");
+        nameSpilit[0] = name[0].toUpperCase();
+        return nameSpilit.join("");
+    }
+
+    static lowerCamelCase(name: string) {
+        let nameSpilit = name.split("_");
+        if (nameSpilit.length > 1) {
+            nameSpilit.forEach((p, i) => {
+                if (i > 0) {
+                    nameSpilit[i] = this.firstUpper(nameSpilit[i]);
+                }
+            })
+        }
+        return nameSpilit.join("");
+        // nameSpilit[0] = name[0].toUpperCase();
+        // return nameSpilit.join("");
+    }
+
+    public info: ApiGenerateImpl;
+
+    public entity: string = "";
+    public funcs: string = "";
+
+
+
+
+    constructor(_info: ApiGenerateImpl) {
+        this.info = _info;
+        let api = this.info.doc;
+        for (const key in api) {
+            const apis = api[key];
+            for (const objKey in apis) {
+                const element = (apis as any)[objKey] as IApiDocFuncInterface;
+                if (['post', 'put', 'get', 'delete'].includes(objKey)) {
+                    let name = `${apis.funcName}Using${DocUtil.firstUpper(objKey)}`;
+                    let entityName = DocUtil.firstUpper(name);
+                    let body = !!element.body && this.paramsTemple(`${entityName}Body`, element.body) && `${entityName}Body`;
+                    let params = !!element.params && this.paramsTemple(`${entityName}Params`, element.params) && `${entityName}Params`;
+                    let response: string | false = false;
+                    let responseList = false;
+                    /// 是否复杂的返回值-需要反序列化
+                    let responsecomplex = false;
+                    if (element.response) {
+                        if (typeof element.response === "string") {
+                            response = element.response;
+                        }
+                        else if (Array.isArray(element.response)) {
+                            responseList = true;
+                            // response = `List<${element.}>`;
+                            let _type = element.response[0];
+                            if (typeof _type === "string") {
+                                response = _type;
+                            }
+                            else {
+                                responsecomplex = true;
+                                response = this.paramsTemple(`${entityName}Response`, _type) && `${entityName}Response`;
+                            }
+                        }
+                        else {
+                            responsecomplex = true;
+                            response = this.paramsTemple(`${entityName}Response`, element.response) && `${entityName}Response`;
+                        }
+                    }
+                    // let response = !!element.response && ((typeof element.response === "string") ? element.response : this.paramsTemple(`${entityName}Response`, element.response) && `${entityName}Response`);
+                    this.funcs += this.funcTemple({
+                        desc: apis.desc,
+                        name,
+                        method: objKey,
+                        url: key,
+                        body,
+                        params,
+                        response,
+                        responseList,
+                        responsecomplex,
+                        element
+                    });
+
+                }
+            }
+        }
+        fs.writeFileSync(this.info.filePath + "/" + this.info.fileName + ".dart", this.buildContent());
+    }
+
+    // enum StatusCode {
+    //     @JsonValue(200)
+    //     success,
+    //     @JsonValue('500')
+    //     weird,
+    //   }
+
+    public buildContent() {
+        return `
+        import 'package:dio/dio.dart';
+        import 'package:dc/utils/request_util.dart';
+        import 'package:json_annotation/json_annotation.dart';
+        part '${this.info.fileName + ".g.dart"}';
+        ${this.entity}
+        
+        class ${this.info.name} {
+            ${this.funcs}
+        }
+        `
+    };
+
+
+    public funcTemple(obj: {
+        name: string,
+        desc?: string,
+        method: string,
+        url: string,
+        body: string | false,
+        params: string | false,
+        response: string | false,
+        responseList: boolean,
+        responsecomplex: boolean,
+        element: IApiDocFuncInterface
+    }) {
+        let serialize = "";
+        let _response = obj.response || "dynamic";
+        if (obj.response) {
+            if (obj.responseList) {
+                _response = `List<${obj.response}>`;
+            }
+            if (obj.responsecomplex) {
+                if (obj.responseList) {
+                    serialize = `, serialize: (data)=> [for (var i in data) ${obj.response}.fromJson(i)]`;
+                } else {
+                    serialize = `, serialize: (data)=> ${obj.response}.fromJson(data)`;
+                }
+            }
+            else {
+                serialize = `,serialize:(dynamic data)=>data`
+            }
+        }
+        let url = obj.url;
+        if (obj.element.params) {
+            for (const key in obj.element.params) {
+                const element = obj.element.params[key];
+                if (element.url === true) {
+                    url = url.replace(`{${key}}`, `\${params.${key}}`);
+                }
+            }
+        }
+
+        return (
+            `   
+        /// ${obj.desc}
+        static RequestUtil<${_response || "dynamic"}> ${obj.name}({${obj.body ? "required" : ""} ${obj.body || "dynamic"} body,${obj.params ? "required" : ""} ${obj.params || "dynamic"} params, bool showLoading = false, bool tips = false, bool errorTips = false, bool successTips = false, Options? options, Function(int, int)? onSendProgress,}) {
+            return RequestUtil<${_response || "dynamic"}>('${url}', RequestMethod.${obj.method}, body: body${obj.body ? ".toJson()" : ""}, params: params${obj.params ? ".toJson()" : ""}, showLoading: showLoading, tips: tips, errorTips: errorTips, successTips: successTips, options: options,onSendProgress:onSendProgress${serialize},);
+        }
+    `
+        )
+    };
+
+    public enumTemple(name: string, params: Record<string, number | string>) {
+        let _list: string[] = []
+        for (const key in params) {
+            const element = params[key];
+            let _element = typeof element === "string" ? `"${element}"` : element;
+            _list.push(`@JsonValue(${_element})`);
+            _list.push(DocUtil.lowerCamelCase(element.toString()) + ",");
+        }
+        this.entity +=
+            `
+        enum ${DocUtil.firstUpper(name)} {
+            ${_list.join("\r\n")}
+          }
+        `
+    }
+
+    public paramsTemple(name: string, params: Record<string, IParamsType>) {
+        let str = "";
+        let iniStr: string[] = [];
+
+        for (const key in params) {
+            const element = params[key];
+            let jsonKey = element.jsonKey ? `@JsonKey(name: "${element.jsonKey}")` : "";
+            let _final = element.final != false ? "final " : "";
+            if (element.type === "object" && element.child && typeof element.child !== "string") {
+                this.paramsTemple(name + DocUtil.firstUpper(key), element.child);
+                str += `
+                /// ${element.desc}
+                ${jsonKey}
+                ${_final} ${name + DocUtil.firstUpper(key)}${element.required != false ? "" : "?"} ${key};
+                `
+                iniStr.push(` ${element.required != false ? "required" : ""} this.${key}`);
+            }
+            else if (element.type === "enum") {
+                if (element.enum) {
+                    this.enumTemple(name + DocUtil.firstUpper(key), element.enum);
+                    str += `
+                    /// ${element.desc}
+                    ${jsonKey}
+                    ${_final} ${name + DocUtil.firstUpper(key)}${element.required != false ? "" : "?"} ${key};
+                    `
+                    iniStr.push(` ${element.required != false ? "required" : ""} this.${key}`);
+                }
+            }
+            else if (element.type === "list" && element.child) {
+                let _type = "";
+                if (typeof element.child !== "string") {
+                    this.paramsTemple(name + DocUtil.firstUpper(key), element.child);
+                    _type = name + DocUtil.firstUpper(key);
+                }
+                else {
+                    _type = element.child;
+                }
+                str += `
+                /// ${element.desc}
+                ${jsonKey}
+                ${_final} List<${_type}>${element.required != false ? "" : "?"} ${key};
+                `
+                iniStr.push(` ${element.required != false ? "required" : ""} this.${key}`);
+            }
+            else {
+                str += `
+                /// ${element.desc}
+                ${jsonKey}
+                ${_final} ${element.type}${element.required != false ? "" : "?"} ${key};
+                `
+                iniStr.push(` ${element.required != false ? "required" : ""} this.${key}`);
+            }
+        }
+
+        this.entity += `
+        @JsonSerializable()
+        class ${name} {
+    
+        ${str}
+    
+        ${name}({${iniStr.join(", ")}});
+    
+        factory ${name}.fromJson(Map<String, dynamic> json) => _$${name}FromJson(json);
+    
+        Map<String, dynamic> toJson() => _$${name}ToJson(this);
+        }
+    `
+        return true;
+    }
+}

+ 252 - 0
cmd/api_generate/utils/docUtillTs.ts

@@ -0,0 +1,252 @@
+import fs from 'fs';
+import { IApiDocFuncInterface, IParamsType } from "../base/interface";
+import ApiGenerateImpl from "../interface/api_generate_impl";
+import { execSync } from 'child_process';
+
+export default class DocUtilTs {
+
+    static runner(app: string) {
+        execSync("cd ../" + app + " && flutter pub run build_runner build ");
+    }
+
+
+    static firstUpper(name: string) {
+        let nameSpilit = name.split("");
+        nameSpilit[0] = name[0].toUpperCase();
+        return nameSpilit.join("");
+    }
+
+    static lowerCamelCase(name: string) {
+        let nameSpilit = name.split("_");
+        if (nameSpilit.length > 1) {
+            nameSpilit.forEach((p, i) => {
+                if (i > 0) {
+                    nameSpilit[i] = this.firstUpper(nameSpilit[i]);
+                }
+            })
+        }
+        return nameSpilit.join("");
+        // nameSpilit[0] = name[0].toUpperCase();
+        // return nameSpilit.join("");
+    }
+
+    public info: ApiGenerateImpl;
+
+    public entity: string = "";
+    public funcs: string = "";
+
+
+
+
+    constructor(_info: ApiGenerateImpl) {
+        this.info = _info;
+        let api = this.info.doc;
+        for (const key in api) {
+            const apis = api[key];
+            for (const objKey in apis) {
+                const element = (apis as any)[objKey] as IApiDocFuncInterface;
+                if (['post', 'put', 'get', 'delete'].includes(objKey)) {
+                    let name = `${apis.funcName}Using${DocUtilTs.firstUpper(objKey)}`;
+                    let entityName = DocUtilTs.firstUpper(name);
+                    let body = !!element.body && this.paramsTemple(`${entityName}Body`, element.body) && `${entityName}Body`;
+                    let params = !!element.params && this.paramsTemple(`${entityName}Params`, element.params) && `${entityName}Params`;
+                    let response: string | false = false;
+                    let responseList = false;
+                    /// 是否复杂的返回值-需要反序列化
+                    let responsecomplex = false;
+                    if (element.response) {
+                        if (typeof element.response === "string") {
+                            response = element.response;
+                        }
+                        else if (Array.isArray(element.response)) {
+                            responseList = true;
+                            // response = `List<${element.}>`;
+                            let _type = element.response[0];
+                            if (typeof _type === "string") {
+                                response = _type;
+                            }
+                            else {
+                                responsecomplex = true;
+                                response = this.paramsTemple(`${entityName}Response`, _type) && `${entityName}Response`;
+                            }
+                        }
+                        else {
+                            responsecomplex = true;
+                            response = this.paramsTemple(`${entityName}Response`, element.response) && `${entityName}Response`;
+                        }
+                    }
+                    // let response = !!element.response && ((typeof element.response === "string") ? element.response : this.paramsTemple(`${entityName}Response`, element.response) && `${entityName}Response`);
+                    this.funcs += this.funcTemple({
+                        desc: apis.desc,
+                        name,
+                        method: objKey,
+                        url: key,
+                        body,
+                        params,
+                        response,
+                        responseList,
+                        responsecomplex,
+                        element,
+                        contentType: apis.contentType
+                    });
+
+                }
+            }
+        }
+        fs.writeFileSync(this.info.filePath + "/" + this.info.fileName + ".ts", this.buildContent());
+    }
+
+    // enum StatusCode {
+    //     @JsonValue(200)
+    //     success,
+    //     @JsonValue('500')
+    //     weird,
+    //   }
+
+    public buildContent() {
+        return `
+        import RequestUtil, { AxiosRequestConfigFunc } from "@/utils/request";
+        
+        ${this.entity}
+        
+        export default class ${this.info.name} {
+            ${this.funcs}
+        }
+        `
+    };
+
+    public mapType(type: any): string {
+        let obj: any = {
+            String: "string",
+            int: "number",
+            double: "number"
+        }
+        return obj[type];
+    }
+
+
+    public funcTemple(obj: {
+        name: string,
+        desc?: string,
+        method: string,
+        url: string,
+        body: string | false,
+        params: string | false,
+        response: string | false,
+        responseList: boolean,
+        responsecomplex: boolean,
+        element: IApiDocFuncInterface,
+        contentType?: "json" | "urlencoded" | "formData"
+    }) {
+        let serialize = "";
+        let _response = obj.response || "any";
+        if (obj.response) {
+            if (obj.responseList) {
+                _response = `${obj.response}[]`;
+            }
+            if (obj.responsecomplex) {
+                if (obj.responseList) {
+                    serialize = `, serialize: (data)=> [for (var i in data) ${obj.response}.fromJson(i)]`;
+                } else {
+                    serialize = `, serialize: (data)=> ${obj.response}.fromJson(data)`;
+                }
+            }
+            else {
+                serialize = `,serialize:(dynamic data)=>data`
+            }
+        }
+        let url = obj.url;
+        if (obj.element.params) {
+            for (const key in obj.element.params) {
+                const element = obj.element.params[key];
+                if (element.url === true) {
+                    console.log(333, key)
+                    url = url.replace(`{${key}}`, `\${options.params!.${key}}`);
+                }
+            }
+        }
+
+        return (
+            `   
+        /// ${obj.desc}
+        static  ${obj.name}(options:AxiosRequestConfigFunc<${obj.body || "any"},${obj.params || "any"}> ):RequestUtil<${_response || "any"}> {
+            return new RequestUtil<${_response || "any"}>(\`${url}\`,'${obj.method.toUpperCase()}' ,options);
+        }
+    `
+        )
+    };
+
+    public enumTemple(name: string, params: Record<string, number | string>) {
+        let _list: string[] = []
+        for (const key in params) {
+            const element = params[key];
+            let _element = typeof element === "string" ? `"${element}"` : element;
+            _list.push(`@JsonValue(${_element})`);
+            _list.push(DocUtilTs.lowerCamelCase(element.toString()) + ",");
+        }
+        this.entity +=
+            `
+       export enum ${DocUtilTs.firstUpper(name)} {
+            ${_list.join("\r\n")}
+          }
+        `
+    }
+
+    public paramsTemple(name: string, params: Record<string, IParamsType>) {
+        let str = "";
+        let iniStr: string[] = [];
+
+        for (const key in params) {
+            const element = params[key];
+            let jsonKey = element.jsonKey ? `@JsonKey(name: "${element.jsonKey}")` : "";
+            let _final = element.final != false ? "" : "";
+            if (element.type === "object" && element.child && typeof element.child !== "string") {
+                this.paramsTemple(name + DocUtilTs.firstUpper(key), element.child);
+                str += `
+                /// ${element.desc}
+                ${_final} ${key}${element.required != false ? "!" : "?"}:  ${name + DocUtilTs.firstUpper(key)} ;
+                `
+                iniStr.push(` ${element.required != false ? "required" : ""} this.${key}`);
+            }
+            else if (element.type === "enum") {
+                if (element.enum) {
+                    this.enumTemple(name + DocUtilTs.firstUpper(key), element.enum);
+                    str += `
+                    /// ${element.desc}
+                    ${_final}  ${key}${element.required != false ? "!" : "?"}: ${name + DocUtilTs.firstUpper(key)};
+                    `
+                    iniStr.push(` ${element.required != false ? "required" : ""} this.${key}`);
+                }
+            }
+            else if (element.type === "list" && element.child) {
+                let _type = "";
+                if (typeof element.child !== "string") {
+                    this.paramsTemple(name + DocUtilTs.firstUpper(key), element.child);
+                    _type = name + DocUtilTs.firstUpper(key);
+                }
+                else {
+                    _type = element.child;
+                }
+                str += `
+                /// ${element.desc}
+                ${_final}  ${key}${element.required != false ? "!" : "?"}: ${_type}[] ;
+                `
+                iniStr.push(` ${element.required != false ? "required" : ""} this.${key}`);
+            }
+            else {
+                str += `
+                /// ${element.desc}
+                ${_final} ${key}${element.required != false ? "!" : "?"}: ${this.mapType(element.type)} ;
+                `
+                iniStr.push(` ${element.required != false ? "required" : ""} this.${key}`);
+            }
+        }
+
+        this.entity += `
+export  class ${name} {
+        ${str}
+}
+    `
+        return true;
+    }
+}

+ 39 - 0
cmd/start.ts

@@ -0,0 +1,39 @@
+
+// import routes from '../src/routes/route.h5';
+
+// console.log(routes);
+
+// const fs = require("fs");
+import * as fs from 'fs';
+
+let ooo = fs.readFileSync('./src/routes/route.h5.ts', "utf-8");
+
+let flag = false;
+
+let _arr: string[] = [];
+ooo.split("\n").forEach(element => {
+    if (element.indexOf("/// 结束 请勿修改 ------") > -1) {
+        flag = false;
+    }
+    if (flag) {
+        let i = new RegExp('(?<="/).+(?=")').exec(element.trim())?.[0];
+        if (i) {
+            _arr.push(i);
+        }
+    }
+    if (element.indexOf("/// 开始 请勿修改 ------") > -1) {
+        flag = true;
+    }
+});
+
+let configName = fs.readFileSync("./src/app.config.ts", "utf-8");
+let list = configName.split("\n");
+list[0] = `let pages = ${JSON.stringify(_arr)};`;
+
+console.log(list);
+fs.writeFileSync("./src/app.config.ts", list.join('\n'), "utf-8");
+
+// ooo.match(regex)
+// console.log(ooo.match(new RegExp("(?=开始)")))
+
+// console.log(new RegExp("^(?=开始)").exec(ooo))

+ 11 - 0
config/dev.js

@@ -0,0 +1,11 @@
+module.exports = {
+  env: {
+    NODE_ENV: '"development"'
+  },
+  defineConstants: {
+    "ENV": '"DEVELOPMENT"',
+    "HOST": '"http://loan-web-api2.internal.jiebide.xin:881"',
+  },
+  mini: {},
+  h5: {}
+}

+ 95 - 0
config/index.js

@@ -0,0 +1,95 @@
+const path = require("path");
+
+
+const config = {
+  projectName: 'taro-pet',
+  date: '2022-12-17',
+  alias: {
+    "@": path.resolve(__dirname, "../src")
+  },
+  designWidth: 750,
+  deviceRatio: {
+    640: 2.34 / 2,
+    750: 1,
+    828: 1.81 / 2
+  },
+  sourceRoot: 'src',
+  outputRoot: 'dist',
+  plugins: [],
+  sass: {
+    resource: [
+      path.resolve(__dirname, '..', 'src/style/variable.scss'),
+      path.resolve(__dirname, '..', 'src/style/mixin.scss'),
+    ]
+  },
+  defineConstants: {
+  },
+  copy: {
+    patterns: [
+    ],
+    options: {
+    }
+  },
+  framework: 'react',
+  compiler: 'webpack5',
+  cache: {
+    enable: false // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache
+  },
+  mini: {
+    postcss: {
+      pxtransform: {
+        enable: true,
+        config: {
+
+        }
+      },
+      url: {
+        enable: true,
+        config: {
+          limit: 1024 // 设定转换尺寸上限
+        }
+      },
+      cssModules: {
+        enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
+        config: {
+          namingPattern: 'module', // 转换模式,取值为 global/module
+          generateScopedName: '[name]__[local]___[hash:base64:5]'
+        }
+      }
+    }
+  },
+  h5: {
+    publicPath: '/',
+    staticDirectory: 'static',
+    esnextModules: ["@taroify"],
+    postcss: {
+      autoprefixer: {
+        enable: true,
+        config: {
+        }
+      },
+      cssModules: {
+        enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
+        config: {
+          namingPattern: 'module', // 转换模式,取值为 global/module
+          generateScopedName: '[name]__[local]___[hash:base64:5]'
+        }
+      }
+    }
+  },
+  rn: {
+    appName: 'taroDemo',
+    postcss: {
+      cssModules: {
+        enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
+      }
+    }
+  }
+}
+
+module.exports = function (merge) {
+  if (process.env.NODE_ENV === 'development') {
+    return merge({}, config, require('./dev'))
+  }
+  return merge({}, config, require('./prod'))
+}

+ 37 - 0
config/prod.js

@@ -0,0 +1,37 @@
+module.exports = {
+  env: {
+    NODE_ENV: '"production"'
+  },
+  defineConstants: {
+  },
+  mini: {},
+  h5: {
+    /**
+     * WebpackChain 插件配置
+     * @docs https://github.com/neutrinojs/webpack-chain
+     */
+    // webpackChain (chain) {
+    //   /**
+    //    * 如果 h5 端编译后体积过大,可以使用 webpack-bundle-analyzer 插件对打包体积进行分析。
+    //    * @docs https://github.com/webpack-contrib/webpack-bundle-analyzer
+    //    */
+    //   chain.plugin('analyzer')
+    //     .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
+
+    //   /**
+    //    * 如果 h5 端首屏加载时间过长,可以使用 prerender-spa-plugin 插件预加载首页。
+    //    * @docs https://github.com/chrisvfritz/prerender-spa-plugin
+    //    */
+    //   const path = require('path')
+    //   const Prerender = require('prerender-spa-plugin')
+    //   const staticDir = path.join(__dirname, '..', 'dist')
+    //   chain
+    //     .plugin('prerender')
+    //     .use(new Prerender({
+    //       staticDir,
+    //       routes: [ '/pages/index/index' ],
+    //       postProcess: (context) => ({ ...context, outputPath: path.join(staticDir, 'index.html') })
+    //     }))
+    // }
+  }
+}

+ 86 - 0
package.json

@@ -0,0 +1,86 @@
+{
+  "name": "taro-pet",
+  "version": "1.0.0",
+  "private": true,
+  "description": "",
+  "templateInfo": {
+    "name": "default",
+    "typescript": true,
+    "css": "sass"
+  },
+  "scripts": {
+    "api": "ts-node cmd/api_generate/dc_boss.ts",
+    "route": "ts-node cmd/start.ts",
+    "build:weapp": "taro build --type weapp",
+    "build:swan": "taro build --type swan",
+    "build:alipay": "taro build --type alipay",
+    "build:tt": "taro build --type tt",
+    "build:h5": "taro build --type h5",
+    "build:rn": "taro build --type rn",
+    "build:qq": "taro build --type qq",
+    "build:jd": "taro build --type jd",
+    "build:quickapp": "taro build --type quickapp",
+    "dev:weapp": "npm run build:weapp -- --watch",
+    "dev:swan": "npm run build:swan -- --watch",
+    "dev:alipay": "npm run build:alipay -- --watch",
+    "dev:tt": "npm run build:tt -- --watch",
+    "dev:h5": "npm run build:h5 -- --watch",
+    "dev:rn": "npm run build:rn -- --watch",
+    "dev:qq": "npm run build:qq -- --watch",
+    "dev:jd": "npm run build:jd -- --watch",
+    "dev:quickapp": "npm run build:quickapp -- --watch"
+  },
+  "browserslist": [
+    "last 3 versions",
+    "Android >= 4.1",
+    "ios >= 8"
+  ],
+  "author": "",
+  "dependencies": {
+    "@babel/runtime": "^7.7.7",
+    "@taroify/core": "^0.1.0-alpha.1",
+    "@taroify/icons": "^0.1.0-alpha.1",
+    "@tarojs/components": "3.5.10",
+    "@tarojs/helper": "3.5.10",
+    "@tarojs/plugin-framework-react": "3.5.10",
+    "@tarojs/plugin-platform-alipay": "3.5.10",
+    "@tarojs/plugin-platform-jd": "3.5.10",
+    "@tarojs/plugin-platform-qq": "3.5.10",
+    "@tarojs/plugin-platform-swan": "3.5.10",
+    "@tarojs/plugin-platform-tt": "3.5.10",
+    "@tarojs/plugin-platform-weapp": "3.5.10",
+    "@tarojs/react": "3.5.10",
+    "@tarojs/router": "3.5.10",
+    "@tarojs/runtime": "3.5.10",
+    "@tarojs/shared": "3.5.10",
+    "@tarojs/taro": "3.5.10",
+    "@tarojs/taro-h5": "3.5.10",
+    "@types/qs": "^6.9.7",
+    "ahooks": "^3.7.4",
+    "classnames": "^2.3.2",
+    "qs": "^6.11.0",
+    "react": "^18.0.0",
+    "react-dom": "^18.0.0"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.8.0",
+    "@pmmmwh/react-refresh-webpack-plugin": "^0.5.5",
+    "@tarojs/cli": "3.5.10",
+    "@tarojs/webpack5-runner": "3.5.10",
+    "@types/react": "^18.0.0",
+    "@types/webpack-env": "^1.13.6",
+    "@typescript-eslint/eslint-plugin": "^5.20.0",
+    "@typescript-eslint/parser": "^5.20.0",
+    "babel-plugin-import": "^1.13.5",
+    "babel-preset-taro": "3.5.10",
+    "eslint": "^8.12.0",
+    "eslint-config-taro": "3.5.10",
+    "eslint-plugin-import": "^2.12.0",
+    "eslint-plugin-react": "^7.8.2",
+    "eslint-plugin-react-hooks": "^4.2.0",
+    "react-refresh": "^0.11.0",
+    "stylelint": "^14.4.0",
+    "typescript": "^4.1.0",
+    "webpack": "5.69.0"
+  }
+}

+ 15 - 0
project.config.json

@@ -0,0 +1,15 @@
+{
+  "miniprogramRoot": "./dist",
+  "projectname": "taro-pet",
+  "description": "",
+  "appid": "touristappid",
+  "setting": {
+    "urlCheck": true,
+    "es6": false,
+    "enhance": false,
+    "compileHotReLoad": false,
+    "postcss": false,
+    "minified": false
+  },
+  "compileType": "miniprogram"
+}

+ 9 - 0
project.tt.json

@@ -0,0 +1,9 @@
+{
+  "miniprogramRoot": "./",
+  "projectname": "taro-pet",
+  "appid": "testAppId",
+  "setting": {
+    "es6": false,
+    "minified": false
+  }
+}

+ 23 - 0
src/apis/userApi.ts

@@ -0,0 +1,23 @@
+
+import RequestUtil, { AxiosRequestConfigFunc } from "@/utils/request";
+
+
+export class GetCodeUsingPostResponse {
+
+  /// 图片token
+  imgToken!: string;
+
+  /// 验证码
+  verification!: string;
+
+}
+
+
+export default class UserApi {
+
+  /// 获取验证码
+  static getCodeUsingPost(options: AxiosRequestConfigFunc<any, any>): RequestUtil<GetCodeUsingPostResponse> {
+    return new RequestUtil<GetCodeUsingPostResponse>(`/adm/account/verificationCode`, 'POST', options);
+  }
+
+}

+ 18 - 0
src/app.config.ts

@@ -0,0 +1,18 @@
+let pages = ["pages/home/index","pages/user/login/index","pages/user/setting/index","pages/user/mine/index"];
+
+if (process.env.TARO_ENV === 'h5') {
+  pages = [
+    'pages/web/index'
+  ]
+}
+
+
+export default defineAppConfig({
+  pages,
+  window: {
+    backgroundTextStyle: 'light',
+    navigationBarBackgroundColor: '#fff',
+    navigationBarTitleText: 'WeChat',
+    navigationBarTextStyle: 'black'
+  }
+})

+ 23 - 0
src/app.scss

@@ -0,0 +1,23 @@
+html,
+body,
+page {
+    color: #3A3B3C;
+}
+
+.background-image {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 80;
+}
+
+.background-content {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 100;
+}

+ 48 - 0
src/app.tsx

@@ -0,0 +1,48 @@
+// import { Component, PropsWithChildren } from 'react'
+import './app.scss'
+
+// class App extends Component<PropsWithChildren> {
+
+//   componentDidMount () {}
+
+//   componentDidShow () {}
+
+//   componentDidHide () {}
+
+//   render () {
+//     // this.props.children 是将要会渲染的页面
+//     return this.props.children
+//   }
+// }
+
+// export default App
+
+import { PropsWithChildren } from 'react';
+import { useRequest } from 'ahooks';
+import Taro from '@tarojs/taro';
+import AppContext from './context/appContext';
+
+interface IAppProps {
+
+}
+
+const App = (props: PropsWithChildren<IAppProps>) => {
+  const result = useRequest(Taro.getSystemInfo);
+  return (
+    <AppContext.Provider value={{
+      systemInfo: result.data,
+      screenSize: {
+        width: result.data?.screenWidth || 0,
+        height: result.data?.screenHeight || 0,
+      },
+      padding: {
+        top: result.data?.safeArea?.top || 0,
+        bottom: result.data?.safeArea?.bottom || 0,
+      }
+    }} >
+      {props.children}
+    </AppContext.Provider>
+  )
+}
+
+export default App;

+ 0 - 0
src/appConfig.ts


BIN
src/assets/home_logo.png


BIN
src/assets/icon_home_back.png


BIN
src/assets/icon_home_characteristic.png


BIN
src/assets/icon_home_characteristic_b_0.png


BIN
src/assets/icon_home_characteristic_b_1.png


BIN
src/assets/icon_home_characteristic_b_2.png


BIN
src/assets/icon_home_characteristic_b_3.png


BIN
src/assets/icon_home_characteristic_i_0.png


BIN
src/assets/icon_home_characteristic_i_1.png


BIN
src/assets/icon_home_characteristic_i_2.png


BIN
src/assets/icon_home_characteristic_i_3.png


BIN
src/assets/icon_home_process.png


BIN
src/assets/icon_home_process_capital.png


BIN
src/assets/icon_home_process_data.png


BIN
src/assets/icon_home_process_qualifications.png


BIN
src/assets/icon_mine_aggrement.png


BIN
src/assets/icon_mine_avatar.png


BIN
src/assets/icon_mine_back.png


BIN
src/assets/icon_mine_business.png


BIN
src/assets/icon_mine_service.png


BIN
src/assets/icon_mine_setting.png


BIN
src/assets/icon_mine_upgrade.png


BIN
src/assets/logo.png


+ 19 - 0
src/component/button/index.scss

@@ -0,0 +1,19 @@
+.button {
+    background-color: $primary-color;
+    color: #fff;
+    padding: 12px 0;
+    box-shadow: 0px 4px 30px 0px rgba(73, 108, 242, 0.6);
+
+    &.button-fill {
+        width: 100%;
+    }
+
+    &.button-round {
+        border-radius: 64px;
+    }
+
+    &.button-white {
+        background-color: #fff;
+        color: $primary-color;
+    }
+}

+ 29 - 0
src/component/button/index.tsx

@@ -0,0 +1,29 @@
+import { PropsWithChildren } from 'react';
+import './index.scss'
+import { Button as TaroButton, ButtonProps } from '@tarojs/components';
+import classNames from 'classnames';
+
+interface IButtonProps extends ButtonProps {
+    fill?: boolean;
+    round?: boolean;
+    color?: "white"
+}
+
+const Button = (props: PropsWithChildren<IButtonProps>) => {
+    const { fill = false, color, round = true, ...otherProps } = props;
+    return (
+        <TaroButton
+            {...otherProps}
+            className={classNames("button", {
+                "button-fill": fill,
+                "button-round": round,
+                [`button-${color}`]: color,
+                [otherProps.className || "a"]: !!otherProps.className,
+            })}
+        >
+            {props.children}
+        </TaroButton>
+    )
+}
+
+export default Button;

+ 72 - 0
src/component/flex/index.scss

@@ -0,0 +1,72 @@
+.c-flex {
+  &-wrap {
+    flex-wrap: wrap;
+  }
+
+  &.c-flex-flex {
+    display: flex;
+    flex-direction: column;
+  }
+
+  &.c-flex-direction-row {
+    flex-direction: row;
+  }
+
+  &.c-flex-direction-row-reverse {
+    flex-direction: row-reverse;
+  }
+
+  &.c-flex-direction-column-reverse {
+    flex-direction: column-reverse;
+  }
+
+  &.c-flex-justify-content-flex-start {
+    justify-content: flex-start;
+  }
+
+  &.c-flex-justify-content-flex-start {
+    justify-content: flex-start;
+  }
+
+  &.c-flex-justify-content-flex-end {
+    justify-content: flex-end;
+  }
+
+  &.c-flex-justify-content-center {
+    justify-content: center;
+  }
+
+  &.c-flex-justify-content-space-between {
+    justify-content: space-between;
+  }
+
+  &.c-flex-justify-content-space-around {
+    justify-content: space-around;
+  }
+
+  &.c-flex-align-item-flex-start {
+    align-items: flex-start;
+  }
+
+  &.c-flex-align-item-center {
+    align-items: center;
+  }
+
+  &.c-flex-align-item-flex-end {
+    align-items: flex-end;
+  }
+
+  &.c-flex-align-item-baseline {
+    align-items: baseline;
+  }
+
+  &.c-flex-align-item-stretch {
+    align-items: stretch;
+  }
+
+  &.c-flex-align-item-scrollY {
+    overflow-y: scroll;
+    position: relative;
+  }
+
+}

+ 90 - 0
src/component/flex/index.tsx

@@ -0,0 +1,90 @@
+import { View } from '@tarojs/components';
+import { ViewProps } from '@tarojs/components/types/View';
+import classNames from 'classnames';
+import Taro from '@tarojs/taro';
+import React from 'react';
+import './index.scss'
+
+
+export type IGap = number | "default" | "lg" | "sm";
+
+export interface IFlexProps extends ViewProps {
+    /**行间距 */
+    rowGap?: IGap;
+    /**列间距 */
+    columnGap?: IGap;
+    /**交叉轴对齐方式 */
+    alignItem?: 'flex-start' | 'flex-end' | 'center' | 'baseline' | 'stretch';
+    /**主轴对齐方式 */
+    justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around";
+    direction?: "column" | "column-reverse" | "row" | "row-reverse";
+    flex?: number;
+    scrollY?: boolean;
+    display?: "flex" | "block";
+    wrap?: boolean;
+}
+
+const Flex: React.FC<IFlexProps> = (props) => {
+    let { rowGap, display = "flex", columnGap, alignItem, justifyContent, scrollY, wrap, flex, direction = "column", className, style = {}, ...divProps } = props;
+
+    const _classNames = classNames("c-flex", className, {
+        ["c-flex-direction-" + direction]: direction !== "column",
+        ["c-flex-justify-content-" + justifyContent]: justifyContent,
+        ["c-flex-align-item-" + alignItem]: alignItem,
+        ['c-flex-align-item-scrollY']: scrollY,
+        ['c-flex-' + display]: display,
+        "c-flex-wrap": wrap
+    })
+
+    const getGap = (gap?: IGap) => {
+        let _gap: IGap | undefined = gap;
+        if (!gap) {
+            return undefined;
+        }
+        if (_gap === "default") {
+            _gap = 32;
+        }
+        else if (_gap === "lg") {
+            _gap = 40;
+        }
+        else if (_gap === "sm") {
+            _gap = 24;
+        }
+        return _gap;
+    }
+
+
+    const _style = React.useMemo(() => {
+        const _rowGap = getGap(rowGap);
+        const _columnGap = getGap(columnGap);
+        let _flexStyle: React.CSSProperties = {
+            flex,
+            rowGap: _rowGap && Taro.pxTransform(_rowGap),
+            columnGap: _columnGap && Taro.pxTransform(_columnGap),
+            ...(style as React.CSSProperties),
+        };
+        return _flexStyle;
+    }, [rowGap, columnGap])
+
+    // const _gapstyle = React.useMemo(() => {
+    //     let _gapStyle: React.CSSProperties = {};
+    //     const _rowGap = getGap(rowGap);
+    //     const _columnGap = getGap(columnGap);
+    //     if (_rowGap) {
+    //         _gapStyle.marginTop = Taro.pxTransform(_rowGap / 2);
+    //         _gapStyle.marginBottom = Taro.pxTransform(_rowGap / 2);
+    //     }
+    //     if (_columnGap) {
+    //         _gapStyle.marginLeft = Taro.pxTransform(_columnGap / 2);
+    //         _gapStyle.marginRight = Taro.pxTransform(_columnGap / 2);
+    //     }
+    //     return _gapStyle;
+    // }, [rowGap, columnGap])
+    return (
+        <View {...divProps} className={_classNames} style={_style} >
+            {props.children}
+        </View>
+    )
+}
+
+export default Flex;

+ 39 - 0
src/component/label/index.scss

@@ -0,0 +1,39 @@
+.c-text {
+  font-size: $font-size-default;
+  display: block;
+
+  &.c-text-primary {
+    color: $primary-color;
+  }
+
+  &.c-text-danger {
+    color: $danger-color;
+  }
+
+  &.c-text-success {
+    color: #25CC43;
+  }
+
+
+  &.c-text-secondary {
+    color: $text-color-secondary
+  }
+
+  &.c-text-white {
+    color: #ffffff
+  }
+
+  &.c-text-bold {
+    font-weight: bold;
+    // color: $text-bold-color;
+  }
+
+  &.c-text-lg {
+    font-size: $font-size-lg;
+  }
+
+  &.c-text-sm {
+    font-size: $font-size-sm;
+  }
+
+}

+ 26 - 0
src/component/label/index.tsx

@@ -0,0 +1,26 @@
+import './index.scss'
+import { Text as TaroText } from '@tarojs/components';
+import classNames from 'classnames';
+import { TextProps } from '@tarojs/components/types/Text';
+
+export type ILabelType = "primary" | "secondary" | "default" | "danger" | "white" | "success";
+
+interface ILabelProps extends TextProps {
+    type?: ILabelType,
+    size?: "default" | "sm" | "lg";
+    bold?: boolean
+}
+
+const Label: React.FC<ILabelProps> = (props) => {
+    const { type = "default", size = "default", bold, ...textProps } = props;
+    const _classNames = classNames("c-text", {
+        ["c-text-" + type]: type !== "default",
+        ["c-text-" + size]: size !== "default",
+        ["c-text-bold"]: bold,
+    });
+    return (
+        <TaroText {...textProps} className={`${_classNames} ${props.className}`} >{props.children}</TaroText>
+    )
+}
+
+export default Label;

+ 0 - 0
src/component/layout/index.scss


+ 38 - 0
src/component/layout/index.tsx

@@ -0,0 +1,38 @@
+import AppContext from '@/context/appContext';
+import { FixedView } from '@taroify/core';
+import { View, ViewProps } from '@tarojs/components';
+import { PropsWithChildren, useContext } from 'react';
+import './index.scss'
+
+interface ILayoutProps extends ViewProps {
+    safe?: boolean;
+}
+
+const InternalLayout = (props: PropsWithChildren<ILayoutProps>) => {
+    const { safe = false, ...viewProps } = props;
+    const appContext = useContext(AppContext);
+    const safeStyle: React.CSSProperties = {
+
+    }
+    if (safe) {
+        safeStyle.paddingTop = appContext.padding.top;
+        safeStyle.paddingBottom = appContext.padding.bottom; //(appContext.systemInfo?.screenHeight || 0) - (appContext.systemInfo?.safeArea?.bottom || 0);
+    }
+    return (
+        <View  {...viewProps} style={safeStyle} >
+            {props.children}
+            <FixedView style={{ height: 44, zIndex: 110, background: "#fff" }} placeholder position="bottom">固定在底部</FixedView>
+        </View>
+    )
+}
+
+
+type InternalLayoutType = typeof InternalLayout;
+
+interface LayoutInterface extends InternalLayoutType {
+
+}
+
+const Layout = InternalLayout as LayoutInterface;
+
+export default Layout;

+ 0 - 0
src/component/net-image/index.scss


+ 40 - 0
src/component/net-image/index.tsx

@@ -0,0 +1,40 @@
+import { Image, ImageProps } from '@tarojs/components';
+import { PropsWithChildren } from 'react';
+import './index.scss'
+
+interface INetWorkImageProps extends ImageProps {
+    src: string;
+    size?: string | [string, string];
+}
+
+const InternalNetWorkImage = (props: PropsWithChildren<INetWorkImageProps>) => {
+    const { size, style = {}, ...imageProps } = props;
+
+    const _style: React.CSSProperties = { ...(style as React.CSSProperties) };
+    if (size) {
+        if (Array.isArray(size)) {
+            _style.width = size[0];
+            _style.height = size[1];
+        }
+        else {
+            _style.width = size;
+            _style.height = size;
+        }
+    }
+
+
+    return (
+        <Image {...imageProps} src={`http://bet-assets.oss-cn-shanghai.aliyuncs.com/project-imgs/${props.src}`} style={_style} />
+    )
+}
+
+
+type InternalNetWorkImageType = typeof InternalNetWorkImage;
+
+interface NetWorkImageInterface extends InternalNetWorkImageType {
+
+}
+
+const NetWorkImage = InternalNetWorkImage as NetWorkImageInterface;
+
+export default NetWorkImage;

+ 15 - 0
src/component/padding/index.scss

@@ -0,0 +1,15 @@
+.c-padding {
+  padding: $padding-default;
+
+  &.c-padding-list {
+    padding: $padding-list;
+  }
+
+  &.c-padding-card {
+    padding: $padding-card;
+  }
+
+  &.c-padding-none {
+    padding: 0;
+  }
+}

+ 65 - 0
src/component/padding/index.tsx

@@ -0,0 +1,65 @@
+import { View } from '@tarojs/components';
+import './index.scss'
+import classNames from 'classnames';
+import React from 'react';
+import { ViewProps } from '@tarojs/components/types/View';
+import Taro from "@tarojs/taro";
+
+export interface IEdgeInsets {
+    padding: string;
+}
+
+export class EdgeInsets {
+    static zero = { padding: "0" };
+
+    static fromLTRB(left: number, top: number, right: number, bottom: number): IEdgeInsets {
+        return { padding: `${Taro.pxTransform(top, 750)} ${Taro.pxTransform(right, 750)} ${Taro.pxTransform(bottom, 750)} ${Taro.pxTransform(left, 750)}` };
+    }
+
+    static only(edge: { left?: number, top?: number, right?: number, bottom?: number }): IEdgeInsets {
+        return { padding: `${Taro.pxTransform(edge.top ?? 0, 750)} ${Taro.pxTransform(edge.right ?? 0, 750)} ${Taro.pxTransform(edge.bottom ?? 0, 750)} ${Taro.pxTransform(edge.left ?? 0, 750)}` };
+    }
+
+    static symmetric(edge: { horizontal?: number, vertical?: number }): IEdgeInsets {
+        return { padding: `${Taro.pxTransform(edge.vertical ?? 0, 750)} ${Taro.pxTransform(edge.horizontal ?? 0, 750)}` };
+    }
+
+    static merge(edge: { horizontal?: number, vertical?: number }): IEdgeInsets {
+        return { padding: `${Taro.pxTransform(edge.vertical ?? 24, 750)} ${Taro.pxTransform(edge.horizontal ?? 32, 750)}` };
+    }
+
+    static all(edge: number): IEdgeInsets {
+        return { padding: `${Taro.pxTransform(edge, 750)}` };
+    }
+
+
+}
+
+
+export type IPaddingEdgeProps = "default" | "list" | "card" | "none" | IEdgeInsets;
+
+export interface IPaddingProps extends ViewProps {
+    padding?: IPaddingEdgeProps;
+}
+
+const Padding: React.FC<IPaddingProps> = (props) => {
+    const { padding = "default", ...viewProps } = props;
+    const _style = React.useMemo(() => {
+        const style: React.CSSProperties = (props.style as React.CSSProperties) ?? {};
+        if (typeof padding !== "string") {
+            style.padding = padding.padding;
+        }
+        return style;
+    }, [padding])
+    const _classNames = classNames("c-padding", { ["c-padding-" + padding]: typeof padding === "string" && ["list", "card", "none"].includes(padding) });
+    return (
+        <View
+            {...viewProps}
+            style={_style}
+            className={`${_classNames} ${props.className}`} >
+            {props.children}
+        </View>
+    )
+}
+
+export default Padding;

+ 24 - 0
src/component/routes/hooks/useDidShow.ts

@@ -0,0 +1,24 @@
+import Taro, { ENV_TYPE } from "@tarojs/taro";
+import { useContext, useEffect } from "react"
+import RouteContext, { RouteComponentContext } from "../provider/route";
+
+
+/**展示的时候 */
+export const useDidShow = (fun: () => void) => {
+    if (Taro.getEnv() === ENV_TYPE.WEB) {
+        const context = useContext(RouteContext);
+        const routeContext = useContext(RouteComponentContext);
+        useEffect(() => {
+            const filter = context.history.filter(p => p.visible);
+            const find = filter[filter.length - 1];
+            if (find?.url === routeContext.data.url) {
+                fun();
+            }
+        }, [context.history])
+    }
+    else {
+        Taro.useDidShow(() => {
+            fun();
+        });
+    }
+}

+ 18 - 0
src/component/routes/hooks/useParams.ts

@@ -0,0 +1,18 @@
+import Taro, { getCurrentInstance } from "@tarojs/taro";
+import { useContext, useMemo } from "react"
+import { RouteComponentContext } from "../provider/route";
+
+
+export const useParams = <T,>(): T => {
+
+    // return React.useMemo(() => {
+    //     return getCurrentInstance().router?.params as any || {};
+    // }, [])
+    const routeContext = useContext(RouteComponentContext);
+    return useMemo(() => {
+        if (Taro.getEnv() === Taro.ENV_TYPE.WEB) {
+            return (routeContext.data.params || {}) as T;
+        }
+        return (getCurrentInstance().router?.params || {}) as T;
+    }, [])
+}

+ 4 - 0
src/component/routes/index.less

@@ -0,0 +1,4 @@
+.show {
+    transition: all 0.2s;
+    // transition-timing-function: ease;
+}

+ 76 - 0
src/component/routes/index.tsx

@@ -0,0 +1,76 @@
+import { View } from "@tarojs/components";
+import React, { useMemo, useState } from "react";
+import './index.less'
+import RouteUtil from '../../utils/routeUtil';
+// @ts-ignore
+import routes from "../../routes/route";
+import RouteContext, { IHistoryRoutes, RouteComponentContext } from "./provider/route";
+
+export const Router = (props: React.PropsWithChildren<{ url: string }>) => {
+    const [history, setHistory] = useState<IHistoryRoutes[]>([
+        {
+            "url": props.url,
+            "params": {},
+            routeKey: (+new Date()).toString(),
+            visible: true
+        }
+    ]);
+
+    useMemo(() => {
+        RouteUtil.push = (urls: string, option?: { params: any }) => {
+            setHistory([...history, { url: urls, routeKey: (+new Date()).toString(), visible: true, params: option?.params }]);
+        }
+        RouteUtil.pop = () => {
+            history[history.length - 1].visible = false;
+            setHistory([...history]);
+        }
+        RouteUtil.removeLast = () => {
+            history.splice(history.length - 1, 1);
+            setHistory([...history]);
+            console.log("路由栈", history);
+        }
+    }, [history])
+
+    return (
+        <RouteContext.Provider value={{ history }}>
+            {
+                history.map(p => {
+                    let _find = routes[p.url]!;
+                    return (
+                        <RouteComponentContext.Provider key={p.routeKey} value={{ data: p }} >
+                            <RouteComponent component={_find.component} url={p.url} visible={p.visible} />
+                        </RouteComponentContext.Provider>
+                    );
+                })
+            }
+        </RouteContext.Provider>
+    );
+}
+
+interface IRouteProps {
+    component: any;
+    url: string;
+
+}
+
+export const RouteComponent = (props: React.PropsWithChildren<IRouteProps & { visible: boolean }>) => {
+    const [visible, setVisible] = useState(false);
+    React.useEffect(() => {
+        setVisible(props.visible);
+        if (!props.visible) {
+            setTimeout(() => {
+                RouteUtil.removeLast();
+            }, 200);
+        }
+    }, [props.visible]);
+    return (
+        <View onClick={e => { e.stopPropagation(); }} style={{ position: "fixed", left: 0, top: 0, width: "100vw", height: "100vh" }} >
+            <View className="show" style={{
+                position: "fixed", "left": visible ? 0 : document.body.clientWidth, top: 0, width: "100%", height: "100%", background: "#fff",
+                boxShadow: "0 0px 0px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)"
+            }} >
+                {React.createElement(props.component)}
+            </View>
+        </View>
+    )
+}

+ 25 - 0
src/component/routes/provider/route.tsx

@@ -0,0 +1,25 @@
+import React from 'react'
+
+
+export interface IHistoryRoutes {
+    url: string,
+    routeKey: string,
+    params?: {},
+    visible: boolean;
+}
+
+interface IRoute {
+    history: IHistoryRoutes[]
+}
+
+
+const RouteContext = React.createContext<IRoute>(null!);
+
+export default RouteContext;
+
+
+
+
+
+export const RouteComponentContext = React.createContext<{ data: IHistoryRoutes }>(null!);
+

+ 15 - 0
src/component/sizeBox/index.tsx

@@ -0,0 +1,15 @@
+import { View } from '@tarojs/components';
+import { PropsWithChildren } from 'react';
+
+interface ISizeBoxProps {
+    height?: number;
+    width?: number;
+}
+
+const SizeBox = (props: PropsWithChildren<ISizeBoxProps>) => {
+    return (
+        <View style={props} />
+    )
+}
+
+export default SizeBox;

+ 9 - 0
src/config/index.d.ts

@@ -0,0 +1,9 @@
+export type EnvType = "DEVELOPMENT" | "TEST" | "PRODUCTION" | "UAT"
+
+export interface Env {
+    HOST: string,
+    ENV: EnvType
+}
+
+declare const APPConfig: Env;
+export default APPConfig;

+ 4 - 0
src/config/index.js

@@ -0,0 +1,4 @@
+export default {
+    HOST: HOST,
+    ENV: ENV,
+}

+ 17 - 0
src/context/appContext.tsx

@@ -0,0 +1,17 @@
+import React from "react";
+
+interface IAppContextInfo {
+    systemInfo?: Taro.getSystemInfo.Result;
+    screenSize: {
+        width: number,
+        height: number;
+    },
+    padding: {
+        top: number;
+        bottom: number;
+    }
+}
+
+const AppContext = React.createContext<IAppContextInfo>(null as any);
+
+export default AppContext;

+ 17 - 0
src/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+  <meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
+  <meta name="apple-mobile-web-app-capable" content="yes">
+  <meta name="apple-touch-fullscreen" content="yes">
+  <meta name="format-detection" content="telephone=no,address=no">
+  <meta name="apple-mobile-web-app-status-bar-style" content="white">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
+  <title>taro-pet</title>
+  <script><%= htmlWebpackPlugin.options.script %></script>
+</head>
+<body>
+  <div id="app"></div>
+</body>
+</html>

+ 4 - 0
src/pages/home/index.config.ts

@@ -0,0 +1,4 @@
+export default definePageConfig({
+  navigationBarTitleText: '首页',
+  navigationStyle:"custom"
+})

+ 52 - 0
src/pages/home/index.scss

@@ -0,0 +1,52 @@
+.index {
+    .index-back {
+        width: 100%;
+        height: 100%;
+        position: absolute;
+        top: 0;
+        left: 0;
+        z-index: 80;
+    }
+
+    .index-back-content {
+        z-index: 100;
+        color: #fff;
+        position: absolute;
+        top: 0;
+        left: 0;
+        height: 100%;
+        width: 100%;
+    }
+
+    .index-back-se {
+        font-size: 24px;
+        font-weight: 200;
+    }
+    
+    .index-iocn-title{
+        width: 220px;
+        height: 40px;
+    }
+
+    .index-back-amount {
+        font-size: 70px;
+    }
+
+    .index-back-btn {
+        width: 354px;
+        height: 84px;
+        padding: 0;
+    }
+    .index-process-img{
+        width: 104px;
+        height: 104px;
+    }
+
+    .background-content-i{
+        width: 40px;
+        height: 40px;
+    }
+    .background-content-wrap{
+        padding: 24px;
+    }
+}

+ 112 - 0
src/pages/home/index.tsx

@@ -0,0 +1,112 @@
+import Button from '@/component/button';
+import Flex from '@/component/flex';
+import Label from '@/component/label';
+import Layout from '@/component/layout';
+import Padding, { EdgeInsets } from '@/component/padding';
+import SizeBox from '@/component/sizeBox';
+import AppContext from '@/context/appContext';
+import ImageUtil from '@/utils/imgUtils';
+import { Image, ScrollView, View } from '@tarojs/components';
+import Taro, { pxTransform } from '@tarojs/taro';
+import React, { PropsWithChildren, useContext, useMemo } from 'react';
+import './index.scss'
+
+interface IHomeProps {
+
+}
+
+const Home = (props: PropsWithChildren<IHomeProps>) => {
+    const appContext = useContext(AppContext);
+    const { screenWidth } = appContext.systemInfo!;
+    const imgBackStyle = useMemo(() => {
+        return { ...ImageUtil.calculationHeight(332 / 170, (screenWidth - 64 + 16) / 2), position: "relative" } as React.CSSProperties;
+    }, []);
+    const item = (index: number, title: string, desc: string) => {
+        return (
+            <View style={imgBackStyle} >
+                <Image className='background-image' src={require(`../../assets/icon_home_characteristic_b_${index}.png`)} />
+                <Flex rowGap="sm" className='background-content background-content-wrap' >
+                    <Flex columnGap="sm" direction="row" alignItem="center" >
+                        <Image className='background-content-i' src={require(`../../assets/icon_home_characteristic_i_${index}.png`)} />
+                        <Label bold >{title}</Label>
+                    </Flex>
+                    <Label style={{ fontSize: pxTransform(22) }} type="secondary" >{desc}</Label>
+                </Flex>
+            </View>
+        )
+    }
+    return (
+        <Layout safe className='index' >
+            <ScrollView>
+                <Image style={ImageUtil.calculationHeight(750 / 88, appContext.systemInfo!.screenWidth)} src={require('../../assets/home_logo.png')} />
+                <SizeBox height={24} />
+                <Padding padding={EdgeInsets.symmetric({ horizontal: 32 })} >
+                    <View style={{ ...ImageUtil.calculationHeight(686 / 380, appContext.systemInfo!.screenWidth - 32), position: "relative" }} >
+                        <Image src={require("@/assets/icon_home_back.png")} className="index-back" />
+                        <Flex alignItem="center" justifyContent="center" rowGap={24} className='index-back-content' >
+                            <Label className='index-back-se' >可担保贷款额度</Label>
+                            <Label className='index-back-amount' >200,000.00</Label>
+                            <Button openType="getPhoneNumber" onGetPhoneNumber={e => {
+
+                                console.log(333, e);
+                            }} className='index-back-btn' color="white" fill >立即申请</Button>
+                            <Button onClick={() => {
+                                Taro.getUserProfile({
+                                    desc: "12312",
+                                    success: (oo) => {
+                                        console.log(oo);
+                                    }
+                                })
+                            }} >
+                                123123
+                            </Button>
+                        </Flex>
+                    </View>
+                </Padding>
+                <Padding padding={EdgeInsets.symmetric({ vertical: 68 })} >
+                    <Flex alignItem="center" justifyContent='center' >
+                        <Image src={require('@/assets/icon_home_process.png')} className="index-iocn-title" />
+                    </Flex>
+
+                </Padding>
+                <Padding padding={EdgeInsets.symmetric({ horizontal: 32 })}>
+                    <Flex direction="row" justifyContent="space-around" >
+                        <Flex >
+                            <Image src={require('../../assets/icon_home_process_data.png')} className="index-process-img" />
+                            <Label size="sm" bold >填写资料</Label>
+                        </Flex>
+                        <Flex >
+                            <Image src={require('../../assets/icon_home_process_qualifications.png')} className="index-process-img" />
+                            <Label size="sm" bold >资质评估</Label>
+                        </Flex>
+                        <Flex >
+                            <Image src={require('../../assets/icon_home_process_capital.png')} className="index-process-img" />
+                            <Label size="sm" bold >匹配资金</Label>
+                        </Flex>
+                    </Flex>
+                </Padding>
+                <SizeBox height={24} />
+                <Padding padding={EdgeInsets.symmetric({ vertical: 68 })} >
+                    <Flex alignItem="center" justifyContent='center' >
+                        <Image src={require('@/assets/icon_home_characteristic.png')} className="index-iocn-title" />
+                    </Flex>
+                </Padding>
+
+                <Flex rowGap="sm" style={{ padding: "0 16PX" }} >
+                    <Flex direction="row" >
+                        {item(0, "产品丰富", "信用、抵押、质押均可")}
+                        <SizeBox width={16} />
+                        {item(1, "快速便捷", "最快10分钟出结果")}
+                    </Flex>
+                    <Flex direction="row" >
+                        {item(2, "场景多元", "可用于消费、经营等")}
+                        <SizeBox width={16} />
+                        {item(3, "信息保密", "严格保护申请人信息")}
+                    </Flex>
+                </Flex>
+            </ScrollView>
+        </Layout>
+    )
+}
+
+export default Home;

+ 3 - 0
src/pages/index/index.config.ts

@@ -0,0 +1,3 @@
+export default definePageConfig({
+  navigationBarTitleText: '首页'
+})

+ 4 - 0
src/pages/index/index.scss

@@ -0,0 +1,4 @@
+.index {
+   
+
+}

+ 0 - 0
src/pages/index/index.tsx


+ 3 - 0
src/pages/template/index.config.ts

@@ -0,0 +1,3 @@
+export default definePageConfig({
+  navigationBarTitleText: '首页'
+})

+ 4 - 0
src/pages/template/index.scss

@@ -0,0 +1,4 @@
+.index {
+   
+
+}

+ 0 - 0
src/pages/template/index.tsx


+ 4 - 0
src/pages/user/login/index.config.ts

@@ -0,0 +1,4 @@
+export default definePageConfig({
+  navigationBarTitleText: '首页',
+  navigationStyle: "custom"
+})

+ 16 - 0
src/pages/user/login/index.scss

@@ -0,0 +1,16 @@
+.login {
+    .login-back {
+        background: linear-gradient(180deg, rgba(73, 108, 242, 0.2) 0%, rgba(73, 108, 242, 0) 100%);
+        height: 100vh;
+    }
+
+    .login-logo {
+        width: 134px*2;
+        height: 176px*2;
+    }
+
+    .login-aggrement{
+        color: $primary-color;
+    }
+
+}

+ 44 - 0
src/pages/user/login/index.tsx

@@ -0,0 +1,44 @@
+import Button from '@/component/button';
+import Flex from '@/component/flex';
+import Label from '@/component/label';
+import Layout from '@/component/layout';
+import Padding, { EdgeInsets } from '@/component/padding';
+import SizeBox from '@/component/sizeBox';
+import RouteUtil from '@/utils/routeUtil';
+import { Image } from '@tarojs/components';
+import { PropsWithChildren } from 'react';
+import './index.scss'
+
+interface ILoginProps {
+
+}
+
+const Login = (props: PropsWithChildren<ILoginProps>) => {
+    return (
+        <Layout className='login' >
+            <Flex className='login-back' >
+                <Flex flex={2} />
+                <Flex alignItem="center" className='login-back-logo-wrap' >
+                    <Image className='login-logo' src={require("@/assets/logo.png")} />
+                </Flex>
+                <Flex flex={2} />
+                <Padding padding={EdgeInsets.symmetric({ horizontal: 80 })} >
+                    <Flex alignItem='center' rowGap={12} >
+                        <Button onClick={() => {
+                            RouteUtil.push("/pages/home/index");
+                        }} fill >微信登录</Button>
+                        <SizeBox height={16} />
+                        <Label size="sm" >点击微信登录则代表阅读并同意</Label>
+                        <Flex direction="row" >
+                            <Label className='login-aggrement' size="sm" >《用户服务协议》</Label>
+                            <Label className='login-aggrement' size="sm" >《隐私协议》</Label>
+                        </Flex>
+                    </Flex>
+                </Padding>
+                <Flex flex={1} />
+            </Flex>
+        </Layout>
+    )
+}
+
+export default Login;

+ 4 - 0
src/pages/user/mine/index.config.ts

@@ -0,0 +1,4 @@
+export default definePageConfig({
+  navigationBarTitleText: '首页',
+  navigationStyle: "custom",
+})

+ 27 - 0
src/pages/user/mine/index.scss

@@ -0,0 +1,27 @@
+.mine {
+    .mine-avatar {
+        width: 128px;
+        height: 128px;
+    }
+
+    .mine-menu {
+        padding: 24px 16PX;
+
+        .mine-menu-wrap {
+            height: 172px;
+            background-color: #F9F9FF;
+        }
+
+        .mine-menu-icon {
+            width: 60px;
+            height: 60px;
+        }
+    }
+
+    .mine-item-icon {
+        width: 48px;
+        height: 48px;
+        padding-right: 24px;
+    }
+
+}

+ 55 - 0
src/pages/user/mine/index.tsx

@@ -0,0 +1,55 @@
+import Flex from '@/component/flex';
+import Label from '@/component/label';
+import Layout from '@/component/layout';
+import Padding, { EdgeInsets } from '@/component/padding';
+import SizeBox from '@/component/sizeBox';
+import AppContext from '@/context/appContext';
+import ImageUtil from '@/utils/imgUtils';
+import { Image, View } from '@tarojs/components';
+import { PropsWithChildren, useContext } from 'react';
+import './index.scss'
+import { Cell } from "@taroify/core"
+import { Arrow } from "@taroify/icons"
+
+interface IMineProps {
+
+}
+
+const Mine = (props: PropsWithChildren<IMineProps>) => {
+    const { screenSize } = useContext(AppContext);
+    return (
+        <Layout className='mine' >
+            <View style={{ ...ImageUtil.calculationHeight(750 / 328, screenSize.width), position: "relative" }} >
+                <Image src={require('@/assets/icon_mine_back.png')} className="background-image" />
+                <Flex justifyContent="flex-end" className='background-content' >
+                    <Padding padding={EdgeInsets.symmetric({ horizontal: 32 })} >
+                        <Flex columnGap={32} direction="row" alignItem="center" >
+                            <Image src={require('@/assets/icon_mine_avatar.png')} className="mine-avatar" />
+                            <Label bold >点击此处登录</Label>
+                        </Flex>
+                    </Padding>
+                </Flex>
+            </View>
+            <SizeBox height={16} />
+            <Flex direction="row" className='mine-menu' >
+                <Flex columnGap="sm" direction="row" alignItem="center" justifyContent="center" flex={1} className='mine-menu-wrap' >
+                    <Label>商务合作</Label>
+                    <Image src={require('@/assets/icon_mine_business.png')} className="mine-menu-icon" />
+                </Flex>
+                <SizeBox width={16} />
+                <Flex columnGap="sm" direction="row" alignItem="center" justifyContent="center" flex={1} className='mine-menu-wrap' >
+                    <Label>在线客服</Label>
+                    <Image src={require('@/assets/icon_mine_service.png')} className="mine-menu-icon" />
+                </Flex>
+            </Flex>
+            <SizeBox height={16} />
+            <Cell size="large" icon={<Image src={require('@/assets/icon_mine_aggrement.png')} className="mine-item-icon" />} title="用户协议" rightIcon={<Arrow />}  ></Cell>
+            <SizeBox height={8} />
+            <Cell size="large" icon={<Image src={require('@/assets/icon_mine_upgrade.png')} className="mine-item-icon" />} title="检查更新" rightIcon={<Arrow />}  ></Cell>
+            <SizeBox height={8} />
+            <Cell size="large" icon={<Image src={require('@/assets/icon_mine_setting.png')} className="mine-item-icon" />} title="设置" rightIcon={<Arrow />}  ></Cell>
+        </Layout>
+    )
+}
+
+export default Mine;

+ 3 - 0
src/pages/user/setting/index.config.ts

@@ -0,0 +1,3 @@
+export default definePageConfig({
+  navigationBarTitleText: '设置'
+})

+ 4 - 0
src/pages/user/setting/index.scss

@@ -0,0 +1,4 @@
+.index {
+   
+
+}

+ 29 - 0
src/pages/user/setting/index.tsx

@@ -0,0 +1,29 @@
+import Layout from '@/component/layout';
+import SizeBox from '@/component/sizeBox';
+import { Cell, Switch } from '@taroify/core';
+import { PropsWithChildren } from 'react';
+import './index.scss'
+import { Arrow } from "@taroify/icons"
+
+interface ISettingProps {
+
+}
+
+const Setting = (props: PropsWithChildren<ISettingProps>) => {
+    return (
+        <Layout className='' >
+            <SizeBox height={16} />
+            <Cell size="large" title="个性化推荐" bordered={false} rightIcon={<Switch size="24" />}  ></Cell>
+            <SizeBox height={8} />
+            <Cell size="large" title="关于我们" bordered={false} rightIcon={<Arrow />}  ></Cell>
+            <SizeBox height={8} />
+            <Cell size="large" title="清理缓存" bordered={false} rightIcon={<Arrow />}  ></Cell>
+            <SizeBox height={8} />
+            <Cell size="large" title="账户注销" bordered={false} rightIcon={<Arrow />}  ></Cell>
+            <SizeBox height={8} />
+            <Cell size="large" title="安全退出" bordered={false} rightIcon={<Arrow />}  ></Cell>
+        </Layout>
+    )
+}
+
+export default Setting;

+ 13 - 0
src/pages/web/index.tsx

@@ -0,0 +1,13 @@
+import { Router } from '../../component/routes'
+
+interface IWebEntranceProps {
+
+}
+
+const WebEntrance: React.FC<IWebEntranceProps> = () => {
+    return (
+        <Router url="/pages/user/login/index" />
+    )
+}
+
+export default WebEntrance;

+ 6 - 0
src/routes/route.d.ts

@@ -0,0 +1,6 @@
+import { IHistoryRoutes } from "../component/routes/provider/route";
+
+
+declare const routes: Record<string, { component: any }>;
+
+export default routes;

+ 17 - 0
src/routes/route.h5.ts

@@ -0,0 +1,17 @@
+import Home from "@/pages/home";
+import Login from "@/pages/user/login";
+import Mine from "@/pages/user/mine";
+import Setting from "@/pages/user/setting";
+
+const routes = {
+    /// 开始 请勿修改 ------
+    "/pages/home/index": { component: Home },
+    "/pages/user/login/index": { component: Login },
+    "/pages/user/setting/index": { component: Setting },
+    "/pages/user/mine/index": { component: Mine },
+    /// 结束 请勿修改 ------
+}
+
+export type IRoutesUrls = keyof (typeof routes);
+
+export default routes;

+ 2 - 0
src/routes/route.weapp.ts

@@ -0,0 +1,2 @@
+
+export default [];

+ 28 - 0
src/style/mixin.scss

@@ -0,0 +1,28 @@
+@mixin padding($padding: 16px) {
+  padding: $padding;
+}
+
+@mixin padding-horizontal($padding: 16px) {
+  padding-left: $padding;
+  padding-right: $padding;
+}
+
+@mixin padding-vertical($padding: 16px) {
+  padding-top: $padding;
+  padding-bottom: $padding;
+}
+
+@mixin border($color:$border-color, $borderSize:1px) {
+  border: $borderSize solid $color;
+}
+
+
+@mixin input($color:$border-color, $borderSize:1px) {
+  font-size: 32px;
+  color: #4B4B4B;
+
+  ::placeholder {
+    font-size: 30px;
+    color: $text-color-secondary;
+  }
+}

+ 37 - 0
src/style/variable.scss

@@ -0,0 +1,37 @@
+$primary-color: #496CF2;
+
+$text-color-secondary: #575757;
+
+$text-bold-color: #464646;
+
+$text-color-secondary:#B6B6B6;
+
+$divider-color: #F2F5F5;
+
+$danger-color: #FE5F28;
+
+$background-color:#F7F7F7;
+
+
+$border-color: #A1A1A1;
+
+$border-radius: 8px;
+
+
+$default-size: 88px;
+$small-size: 88px;
+$big-size: 88px;
+
+
+$font-size-default: 30px;
+$font-size-lg: 36px;
+$font-size-sm: 26px;
+
+
+$padding-list: 24px 32px;
+
+$padding-card: 24px 32px;
+
+$padding-default: 24px 32px;
+$padding-sm: 24px 32px;
+$padding-large: 24px 32px;

+ 8 - 0
src/utils/imgUtils.ts

@@ -0,0 +1,8 @@
+
+export default class ImageUtil {
+
+    /**计算高度 */
+    public static calculationHeight(ratio: number, width: number) {
+        return { width:  width, height: width / ratio }
+    }
+}

+ 42 - 0
src/utils/modalUtil.ts

@@ -0,0 +1,42 @@
+import { showToast } from "@tarojs/taro";
+
+
+interface Option {
+    /** 提示的内容 */
+    title: string
+    /** 接口调用结束的回调函数(调用成功、失败都会执行) */
+    complete?: (res: TaroGeneral.CallbackResult) => void
+    /** 提示的延迟时间 */
+    duration?: number
+    /** 接口调用失败的回调函数 */
+    fail?: (res: TaroGeneral.CallbackResult) => void
+    /** 图标
+     *
+     * 可选值:
+     * - 'success': 显示成功图标,此时 title 文本最多显示 7 个汉字长度;
+     * - 'error': 显示失败图标,此时 title 文本最多显示 7 个汉字长度;
+     * - 'loading': 显示加载图标,此时 title 文本最多显示 7 个汉字长度;
+     * - 'none': 不显示图标,此时 title 文本最多可显示两行 */
+    icon?: 'success' | 'error' | 'loading' | 'none'
+    /** 自定义图标的本地路径,image 的优先级高于 icon */
+    image?: string
+    /** 是否显示透明蒙层,防止触摸穿透 */
+    mask?: boolean
+    /** 接口调用成功的回调函数 */
+    success?: (res: TaroGeneral.CallbackResult) => void
+}
+
+
+export default class ModalUtil {
+
+
+    static toast(str: string, option: Omit<Option, "title"> = {}) {
+        showToast({
+            title: str || "未知错误",
+            icon: "none",
+            duration: 2000,
+            ...option
+        });
+    }
+
+};

+ 103 - 0
src/utils/request.ts

@@ -0,0 +1,103 @@
+import Taro from "@tarojs/taro";
+import qs from "qs";
+import ModalUtil from "./modalUtil";
+
+
+interface IRequestBaseResult<T> {
+    code?: 0;
+    data: T;
+    msg: string;
+}
+
+interface IRequestOptions {
+    tips?: string | true;
+    success?: string | true;
+    errorTips?: string | true;
+    loading?: string | true;
+    contentType?: "json" | "urlencoded" | "formData";
+    data?: Record<string, any>,
+    params?: Record<string, any>,
+}
+
+export interface AxiosRequestConfigFunc<B, P> extends Omit<IRequestOptions, "data" | "params"> {
+    data?: B,
+    params?: P
+}
+
+export default class RequestUtil<T> {
+    promise: Promise<Taro.request.SuccessCallbackResult<IRequestBaseResult<T>>>;
+
+
+    public constructor(url: string, method: "POST" | "GET" | "PUT" | "DELETE", options: IRequestOptions) {
+        this.promise = this.runRequest(url, method, options);
+    }
+
+    public runRequest(url: string, method: "POST" | "GET" | "PUT" | "DELETE", options: IRequestOptions) {
+        return new Promise<Taro.request.SuccessCallbackResult<IRequestBaseResult<T>>>((resolve, rej) => {
+            if (options.params) {
+                url += "?" + qs.stringify(options.params);
+            }
+            Taro.request({
+                url,
+                method,
+                data: options.data,
+                fail: () => {
+                    options.loading && Taro.hideLoading();
+                    rej();
+                },
+                success: (res) => {
+                    // if (typeof res.data === "string") {
+                    //     try {
+                    //         res.data = JSON.parse(res.data);
+                    //     } catch (error) {
+
+                    //     }
+                    // }
+                    options.loading && Taro.hideLoading();
+                    let _success = this.checkSuccessSync(res);
+
+                    if (_success) {
+                        ModalUtil.toast(typeof (options.success) === "string" ? options.success : res.data.msg);
+                    }
+                    else {
+                        ModalUtil.toast(res.data.msg);
+                    }
+                    // else if (res.data.code !== 0 && (options.tips || options.errorTips)) {
+
+                    // }
+                    // else if (res.data.code === 10001) {
+                    //     // ModalUtil.toast("登录失效");
+                    //     // MemberHelper.clearMemberInfo();
+                    //     // Taro.reLaunch({
+                    //     //     url: "/pages/user/userLogin/index"
+                    //     // })
+                    // }
+                    resolve(res);
+                },
+            })
+        });
+
+    }
+
+
+    private checkSuccessSync(data: Taro.request.SuccessCallbackResult<IRequestBaseResult<T>>) {
+        return data.statusCode >= 200 && data.statusCode < 300 && data.data.code === 0;
+    }
+
+    /**是否正确 */
+    public async checkSuccess() {
+        return this.promise.then(this.checkSuccessSync)
+    }
+
+    public async toData() {
+        return this.promise
+            .then((p) => {
+                if (this.checkSuccessSync(p)) {
+                    return p.data.data;
+                }
+                return null;
+            })
+    }
+
+
+}

+ 26 - 0
src/utils/routeUtil.ts

@@ -0,0 +1,26 @@
+import Taro from "@tarojs/taro";
+import qs from "qs";
+import { IRoutesUrls } from "../routes/route.h5";
+
+export default class RouteUtil {
+
+    /**跳转页面 */
+    public static push<T>(_url: IRoutesUrls, option?: { params: T }) {
+        if (option?.params) {
+            _url += "?" + qs.stringify(option.params, { "encode": false });
+        }
+        Taro.navigateTo({
+            url: _url,
+        });
+    }
+
+    /**返回 */
+    public static pop(stack: number = 1) {
+        Taro.navigateBack({ "delta": stack });
+    }
+
+    /**删除最后一个画面 */
+    public static removeLast() {
+
+    }
+}

Some files were not shown because too many files changed in this diff