Kaynağa Gözat

feat: new home page for textbook

MetaPunkGames 8 ay önce
ebeveyn
işleme
455bd2343c
32 değiştirilmiş dosya ile 1569 ekleme ve 116 silme
  1. 49 104
      angular.json
  2. 6 0
      ionic.config.json
  3. 288 5
      package-lock.json
  4. 5 1
      package.json
  5. BIN
      projects/textbook/public/favicon.ico
  6. BIN
      projects/textbook/public/icon/left-arrow.png
  7. BIN
      projects/textbook/public/icon/right-arrow.png
  8. BIN
      projects/textbook/public/img/banner-lab.png
  9. BIN
      projects/textbook/public/img/book.ico
  10. BIN
      projects/textbook/public/img/book.png
  11. 1 0
      projects/textbook/public/img/book.svg
  12. 18 0
      projects/textbook/public/img/logo-authing.svg
  13. 8 0
      projects/textbook/src/app/app.component.ts
  14. 12 3
      projects/textbook/src/app/app.config.ts
  15. 1 1
      projects/textbook/src/app/app.routes.ts
  16. 1 1
      projects/textbook/src/index.html
  17. 10 0
      projects/textbook/src/modules/textbook/page-home/footer/footer.component.html
  18. 29 0
      projects/textbook/src/modules/textbook/page-home/footer/footer.component.scss
  19. 23 0
      projects/textbook/src/modules/textbook/page-home/footer/footer.component.spec.ts
  20. 11 0
      projects/textbook/src/modules/textbook/page-home/footer/footer.component.ts
  21. 66 0
      projects/textbook/src/modules/textbook/page-home/header/header.component.html
  22. 142 0
      projects/textbook/src/modules/textbook/page-home/header/header.component.scss
  23. 23 0
      projects/textbook/src/modules/textbook/page-home/header/header.component.spec.ts
  24. 231 0
      projects/textbook/src/modules/textbook/page-home/header/header.component.ts
  25. 242 0
      projects/textbook/src/modules/textbook/page-home/page-home.component.html
  26. 319 0
      projects/textbook/src/modules/textbook/page-home/page-home.component.scss
  27. 23 0
      projects/textbook/src/modules/textbook/page-home/page-home.component.spec.ts
  28. 18 0
      projects/textbook/src/modules/textbook/page-home/page-home.component.ts
  29. 11 0
      projects/textbook/src/modules/textbook/textbook-routing.module.ts
  30. 13 0
      projects/textbook/src/modules/textbook/textbook.module.ts
  31. 17 0
      projects/textbook/src/styles.scss
  32. 2 1
      src/app/app.config.ts

+ 49 - 104
angular.json

@@ -3,107 +3,6 @@
   "version": 1,
   "newProjectRoot": "projects",
   "projects": {
-    "edu-textbook": {
-      "projectType": "application",
-      "schematics": {
-        "@schematics/angular:component": {
-          "style": "scss"
-        }
-      },
-      "root": "",
-      "sourceRoot": "src",
-      "prefix": "app",
-      "architect": {
-        "build": {
-          "builder": "@angular-devkit/build-angular:application",
-          "options": {
-            "outputPath": "dist/edu-textbook",
-            "index": "src/index.html",
-            "browser": "src/main.ts",
-            "polyfills": [
-              "zone.js"
-            ],
-            "tsConfig": "tsconfig.app.json",
-            "inlineStyleLanguage": "scss",
-            "assets": [
-              {
-                "glob": "**/*",
-                "input": "public"
-              },
-              {
-                "glob": "**/*",
-                "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
-                "output": "/assets/"
-              }
-            ],
-            "styles": [
-              "src/theme.less",
-              "src/styles.scss"
-            ],
-            "scripts": []
-          },
-          "configurations": {
-            "production": {
-              "budgets": [
-                {
-                  "type": "initial",
-                  "maximumWarning": "500kB",
-                  "maximumError": "1MB"
-                },
-                {
-                  "type": "anyComponentStyle",
-                  "maximumWarning": "2kB",
-                  "maximumError": "4kB"
-                }
-              ],
-              "outputHashing": "all"
-            },
-            "development": {
-              "optimization": false,
-              "extractLicenses": false,
-              "sourceMap": true
-            }
-          },
-          "defaultConfiguration": "production"
-        },
-        "serve": {
-          "builder": "@angular-devkit/build-angular:dev-server",
-          "configurations": {
-            "production": {
-              "buildTarget": "edu-textbook:build:production"
-            },
-            "development": {
-              "buildTarget": "edu-textbook:build:development"
-            }
-          },
-          "defaultConfiguration": "development"
-        },
-        "extract-i18n": {
-          "builder": "@angular-devkit/build-angular:extract-i18n"
-        },
-        "test": {
-          "builder": "@angular-devkit/build-angular:karma",
-          "options": {
-            "polyfills": [
-              "zone.js",
-              "zone.js/testing"
-            ],
-            "tsConfig": "tsconfig.spec.json",
-            "inlineStyleLanguage": "scss",
-            "assets": [
-              {
-                "glob": "**/*",
-                "input": "public"
-              }
-            ],
-            "styles": [
-              "src/styles.scss"
-            ],
-            "scripts": []
-          }
-        }
-      }
-    },
     "textbook": {
       "projectType": "application",
       "schematics": {
@@ -130,11 +29,46 @@
               {
                 "glob": "**/*",
                 "input": "projects/textbook/public"
+              },
+              {
+                "glob": "**/*",
+                "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
+                "output": "/assets/"
               }
             ],
             "styles": [
               "projects/textbook/src/styles.scss",
-              "node_modules/ng-zorro-antd/ng-zorro-antd.min.css"
+              "node_modules/ng-zorro-antd/ng-zorro-antd.min.css",
+              {
+                "input": "node_modules/@ionic/angular/css/core.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/normalize.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/structure.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/typography.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/display.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/padding.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/float-elements.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/text-alignment.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/text-transformation.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/flex-utils.css"
+              }
             ],
             "scripts": []
           },
@@ -202,6 +136,17 @@
     }
   },
   "cli": {
-    "analytics": "2bc1f0cc-3633-48b2-a456-d6ad82ce77e6"
+    "analytics": "2bc1f0cc-3633-48b2-a456-d6ad82ce77e6",
+    "schematicCollections": [
+      "@ionic/angular-toolkit"
+    ]
+  },
+  "schematics": {
+    "@ionic/angular-toolkit:component": {
+      "styleext": "scss"
+    },
+    "@ionic/angular-toolkit:page": {
+      "styleext": "scss"
+    }
   }
-}
+}

+ 6 - 0
ionic.config.json

@@ -0,0 +1,6 @@
+{
+  "name": "ionic-app",
+  "app_id": "",
+  "type": "angular-standalone",
+  "integrations": {}
+}

+ 288 - 5
package-lock.json

@@ -16,7 +16,10 @@
         "@angular/platform-browser": "^18.0.0",
         "@angular/platform-browser-dynamic": "^18.0.0",
         "@angular/router": "^18.0.0",
+        "@ionic/angular": "^8.2.2",
+        "@types/parse": "^3.0.9",
         "ng-zorro-antd": "^18.0.0",
+        "parse": "^5.1.0",
         "rxjs": "~7.8.0",
         "tslib": "^2.3.0",
         "zone.js": "~0.14.3"
@@ -25,6 +28,7 @@
         "@angular-devkit/build-angular": "^18.0.4",
         "@angular/cli": "^18.0.4",
         "@angular/compiler-cli": "^18.0.0",
+        "@ionic/angular-toolkit": "latest",
         "@types/jasmine": "~5.1.0",
         "jasmine-core": "~5.1.0",
         "karma": "~6.4.0",
@@ -2431,6 +2435,18 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/@babel/runtime-corejs3": {
+      "version": "7.23.2",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime-corejs3/-/runtime-corejs3-7.23.2.tgz",
+      "integrity": "sha512-54cIh74Z1rp4oIjsHjqN+WM4fMyCBYe+LpZ9jWm51CZ1fbH3SkAzQD/3XLoNkjbJ7YEmjobLXyvQrFypRHOrXw==",
+      "dependencies": {
+        "core-js-pure": "^3.30.2",
+        "regenerator-runtime": "^0.14.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
     "node_modules/@babel/template": {
       "version": "7.24.7",
       "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.24.7.tgz",
@@ -2910,6 +2926,163 @@
         "node": ">=18"
       }
     },
+    "node_modules/@ionic/angular": {
+      "version": "8.2.2",
+      "resolved": "https://registry.npmmirror.com/@ionic/angular/-/angular-8.2.2.tgz",
+      "integrity": "sha512-c8siqeWN5iWvu7LlechiIYSWRAlvjL2dEKjB19xspAzZv+9aXrT9YWPz+DTeS2eTO6CnwvHJpG0tPlVxgjpr1g==",
+      "dependencies": {
+        "@ionic/core": "8.2.2",
+        "ionicons": "^7.0.0",
+        "jsonc-parser": "^3.0.0",
+        "tslib": "^2.3.0"
+      },
+      "peerDependencies": {
+        "@angular/core": ">=16.0.0",
+        "@angular/forms": ">=16.0.0",
+        "@angular/router": ">=16.0.0",
+        "rxjs": ">=7.5.0",
+        "zone.js": ">=0.13.0"
+      }
+    },
+    "node_modules/@ionic/angular-toolkit": {
+      "version": "11.0.1",
+      "resolved": "https://registry.npmmirror.com/@ionic/angular-toolkit/-/angular-toolkit-11.0.1.tgz",
+      "integrity": "sha512-dxx2RDbxDYM2nWRPIirKMJySHtqJ1u02T25PGbNb99W2Wlcmu1cza3+2/PQ8ga18yMz/dQqaGyEmPDf3ZSVO0w==",
+      "dev": true,
+      "dependencies": {
+        "@angular-devkit/core": "^17.0.0",
+        "@angular-devkit/schematics": "^17.0.0",
+        "@schematics/angular": "^17.0.0"
+      }
+    },
+    "node_modules/@ionic/angular-toolkit/node_modules/@angular-devkit/core": {
+      "version": "17.3.8",
+      "resolved": "https://registry.npmmirror.com/@angular-devkit/core/-/core-17.3.8.tgz",
+      "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==",
+      "dev": true,
+      "dependencies": {
+        "ajv": "8.12.0",
+        "ajv-formats": "2.1.1",
+        "jsonc-parser": "3.2.1",
+        "picomatch": "4.0.1",
+        "rxjs": "7.8.1",
+        "source-map": "0.7.4"
+      },
+      "engines": {
+        "node": "^18.13.0 || >=20.9.0",
+        "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
+        "yarn": ">= 1.13.0"
+      },
+      "peerDependencies": {
+        "chokidar": "^3.5.2"
+      },
+      "peerDependenciesMeta": {
+        "chokidar": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@ionic/angular-toolkit/node_modules/@angular-devkit/schematics": {
+      "version": "17.3.8",
+      "resolved": "https://registry.npmmirror.com/@angular-devkit/schematics/-/schematics-17.3.8.tgz",
+      "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==",
+      "dev": true,
+      "dependencies": {
+        "@angular-devkit/core": "17.3.8",
+        "jsonc-parser": "3.2.1",
+        "magic-string": "0.30.8",
+        "ora": "5.4.1",
+        "rxjs": "7.8.1"
+      },
+      "engines": {
+        "node": "^18.13.0 || >=20.9.0",
+        "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
+        "yarn": ">= 1.13.0"
+      }
+    },
+    "node_modules/@ionic/angular-toolkit/node_modules/@schematics/angular": {
+      "version": "17.3.8",
+      "resolved": "https://registry.npmmirror.com/@schematics/angular/-/angular-17.3.8.tgz",
+      "integrity": "sha512-2g4OmSyE9YGq50Uj7fNI26P/TSAFJ7ZuirwTF2O7Xc4XRQ29/tYIIqhezpNlTb6rlYblcQuMcUZBrMfWJHcqJw==",
+      "dev": true,
+      "dependencies": {
+        "@angular-devkit/core": "17.3.8",
+        "@angular-devkit/schematics": "17.3.8",
+        "jsonc-parser": "3.2.1"
+      },
+      "engines": {
+        "node": "^18.13.0 || >=20.9.0",
+        "npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
+        "yarn": ">= 1.13.0"
+      }
+    },
+    "node_modules/@ionic/angular-toolkit/node_modules/ajv": {
+      "version": "8.12.0",
+      "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz",
+      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+      "dev": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/@ionic/angular-toolkit/node_modules/ajv-formats": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz",
+      "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+      "dev": true,
+      "dependencies": {
+        "ajv": "^8.0.0"
+      },
+      "peerDependencies": {
+        "ajv": "^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "ajv": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@ionic/angular-toolkit/node_modules/magic-string": {
+      "version": "0.30.8",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.8.tgz",
+      "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.4.15"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@ionic/angular-toolkit/node_modules/picomatch": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.1.tgz",
+      "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/@ionic/core": {
+      "version": "8.2.2",
+      "resolved": "https://registry.npmmirror.com/@ionic/core/-/core-8.2.2.tgz",
+      "integrity": "sha512-gpWemL5IJjGDJPz6dltHnFyqioRl0sugs2PUXrwPaYwMnTDoRZ6iojYFovCIr5YJN99rHZprOthdcsYR/viGyQ==",
+      "dependencies": {
+        "@stencil/core": "^4.17.2",
+        "ionicons": "^7.2.2",
+        "tslib": "^2.1.0"
+      }
+    },
     "node_modules/@isaacs/cliui": {
       "version": "8.0.2",
       "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -3935,6 +4108,18 @@
       "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
       "dev": true
     },
+    "node_modules/@stencil/core": {
+      "version": "4.18.3",
+      "resolved": "https://registry.npmmirror.com/@stencil/core/-/core-4.18.3.tgz",
+      "integrity": "sha512-8yoG5AFQYEPocVtuoc5kvRS0Hku0MoDWDUpADRaXPVHsOFLmxR16LJENj25ucCz5GEfeTGQ/tCE8JAypPmr/fQ==",
+      "bin": {
+        "stencil": "bin/stencil"
+      },
+      "engines": {
+        "node": ">=16.0.0",
+        "npm": ">=7.10.0"
+      }
+    },
     "node_modules/@tufjs/canonical-json": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz",
@@ -4121,7 +4306,6 @@
       "version": "20.14.6",
       "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.14.6.tgz",
       "integrity": "sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==",
-      "dev": true,
       "dependencies": {
         "undici-types": "~5.26.4"
       }
@@ -4135,6 +4319,14 @@
         "@types/node": "*"
       }
     },
+    "node_modules/@types/parse": {
+      "version": "3.0.9",
+      "resolved": "https://registry.npmmirror.com/@types/parse/-/parse-3.0.9.tgz",
+      "integrity": "sha512-DGTHygc7krgmNAK8h42giwmAofCd9uv2++RD+zw6OmWI7AEnlTYZwEuWsx22SA2CSMQrZW8P2INHLpQbnQFUng==",
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
     "node_modules/@types/qs": {
       "version": "6.9.15",
       "resolved": "https://registry.npmmirror.com/@types/qs/-/qs-6.9.15.tgz",
@@ -5536,6 +5728,16 @@
         "url": "https://opencollective.com/core-js"
       }
     },
+    "node_modules/core-js-pure": {
+      "version": "3.37.1",
+      "resolved": "https://registry.npmmirror.com/core-js-pure/-/core-js-pure-3.37.1.tgz",
+      "integrity": "sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA==",
+      "hasInstallScript": true,
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
     "node_modules/core-util-is": {
       "version": "1.0.3",
       "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -5713,6 +5915,12 @@
         "node": ">= 8"
       }
     },
+    "node_modules/crypto-js": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
+      "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
+      "optional": true
+    },
     "node_modules/css-loader": {
       "version": "7.1.1",
       "resolved": "https://registry.npmmirror.com/css-loader/-/css-loader-7.1.1.tgz",
@@ -7275,6 +7483,11 @@
         "postcss": "^8.1.0"
       }
     },
+    "node_modules/idb-keyval": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmmirror.com/idb-keyval/-/idb-keyval-6.2.1.tgz",
+      "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg=="
+    },
     "node_modules/ieee754": {
       "version": "1.2.1",
       "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
@@ -7466,6 +7679,14 @@
         "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
+    "node_modules/ionicons": {
+      "version": "7.4.0",
+      "resolved": "https://registry.npmmirror.com/ionicons/-/ionicons-7.4.0.tgz",
+      "integrity": "sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ==",
+      "dependencies": {
+        "@stencil/core": "^4.0.3"
+      }
+    },
     "node_modules/ip-address": {
       "version": "9.0.5",
       "resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-9.0.5.tgz",
@@ -7980,8 +8201,7 @@
     "node_modules/jsonc-parser": {
       "version": "3.2.1",
       "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
-      "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
-      "dev": true
+      "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA=="
     },
     "node_modules/jsonfile": {
       "version": "4.0.0",
@@ -9745,6 +9965,25 @@
         "node": ">=6"
       }
     },
+    "node_modules/parse": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmmirror.com/parse/-/parse-5.1.0.tgz",
+      "integrity": "sha512-46gVRe1JHsh21Ht0/Ko6PeMDl6wELLMYxnZPFD6iZm2EWsWnzi2txNGE6PvnIv+G7yOufZIOD0BCZLYOFl3toA==",
+      "dependencies": {
+        "@babel/runtime-corejs3": "7.23.2",
+        "idb-keyval": "6.2.1",
+        "react-native-crypto-js": "1.0.0",
+        "uuid": "9.0.1",
+        "ws": "8.16.0",
+        "xmlhttprequest": "1.8.0"
+      },
+      "engines": {
+        "node": ">=18 <21"
+      },
+      "optionalDependencies": {
+        "crypto-js": "4.2.0"
+      }
+    },
     "node_modules/parse-json": {
       "version": "5.2.0",
       "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz",
@@ -9778,6 +10017,38 @@
         "node": ">= 0.10"
       }
     },
+    "node_modules/parse/node_modules/uuid": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz",
+      "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+      "funding": [
+        "https://github.com/sponsors/broofa",
+        "https://github.com/sponsors/ctavan"
+      ],
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
+    "node_modules/parse/node_modules/ws": {
+      "version": "8.16.0",
+      "resolved": "https://registry.npmmirror.com/ws/-/ws-8.16.0.tgz",
+      "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": ">=5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/parse5": {
       "version": "7.1.2",
       "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.1.2.tgz",
@@ -10312,6 +10583,11 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/react-native-crypto-js": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/react-native-crypto-js/-/react-native-crypto-js-1.0.0.tgz",
+      "integrity": "sha512-FNbLuG/HAdapQoybeZSoes1PWdOj0w242gb+e1R0hicf3Gyj/Mf8M9NaED2AnXVOX01b2FXomwUiw1xP1K+8sA=="
+    },
     "node_modules/readable-stream": {
       "version": "3.6.2",
       "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
@@ -11838,8 +12114,7 @@
     "node_modules/undici-types": {
       "version": "5.26.5",
       "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz",
-      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
-      "dev": true
+      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
     },
     "node_modules/unicode-canonical-property-names-ecmascript": {
       "version": "2.0.0",
@@ -13055,6 +13330,14 @@
         }
       }
     },
+    "node_modules/xmlhttprequest": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmmirror.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
+      "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/y18n": {
       "version": "5.0.8",
       "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",

+ 5 - 1
package.json

@@ -18,7 +18,10 @@
     "@angular/platform-browser": "^18.0.0",
     "@angular/platform-browser-dynamic": "^18.0.0",
     "@angular/router": "^18.0.0",
+    "@ionic/angular": "^8.2.2",
+    "@types/parse": "^3.0.9",
     "ng-zorro-antd": "^18.0.0",
+    "parse": "latest",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",
     "zone.js": "~0.14.3"
@@ -27,6 +30,7 @@
     "@angular-devkit/build-angular": "^18.0.4",
     "@angular/cli": "^18.0.4",
     "@angular/compiler-cli": "^18.0.0",
+    "@ionic/angular-toolkit": "latest",
     "@types/jasmine": "~5.1.0",
     "jasmine-core": "~5.1.0",
     "karma": "~6.4.0",
@@ -36,4 +40,4 @@
     "karma-jasmine-html-reporter": "~2.1.0",
     "typescript": "~5.4.2"
   }
-}
+}

BIN
projects/textbook/public/favicon.ico


BIN
projects/textbook/public/icon/left-arrow.png


BIN
projects/textbook/public/icon/right-arrow.png


BIN
projects/textbook/public/img/banner-lab.png


BIN
projects/textbook/public/img/book.ico


BIN
projects/textbook/public/img/book.png


+ 1 - 0
projects/textbook/public/img/book.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1718874967505" class="icon" viewBox="0 0 1316 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7097" xmlns:xlink="http://www.w3.org/1999/xlink" width="257.03125" height="200"><path d="M201.363749 0.219429h-0.073143a46.884571 46.884571 0 0 0-46.811429 47.104v706.486857c0 25.892571 21.065143 47.030857 47.104 47.104 109.714286 0.219429 293.376 23.113143 420.132572 155.721143V217.307429c0-8.777143-2.194286-17.042286-6.509715-23.844572C511.270034 25.965714 311.297463 0.438857 201.363749 0.219429zM1162.16832 753.810286V47.323429a46.884571 46.884571 0 0 0-46.811429-47.104h-0.146285c-109.933714 0.219429-309.833143 25.673143-413.842286 193.243428a45.129143 45.129143 0 0 0-6.509714 23.844572V956.708571c126.756571-132.608 310.491429-155.501714 420.132571-155.794285 26.038857 0 47.177143-21.211429 47.177143-47.030857z" fill="#4384F5" p-id="7098"></path><path d="M1269.468891 163.108571h-34.157714v590.701715c0 66.121143-53.906286 120.027429-120.173714 120.246857-92.964571 0.219429-246.345143 18.358857-354.962286 121.197714 187.830857-46.08 385.901714-16.091429 498.761143 9.581714a47.030857 47.030857 0 0 0 57.636571-45.860571V210.212571a47.177143 47.177143 0 0 0-47.104-47.104zM81.263177 753.810286V163.108571H47.105463A47.177143 47.177143 0 0 0 0.001463 210.212571v748.763429a46.957714 46.957714 0 0 0 57.636571 45.933714c112.859429-25.819429 310.857143-55.661714 498.761143-9.654857-108.617143-102.838857-261.997714-121.051429-354.962286-121.270857a120.539429 120.539429 0 0 1-120.173714-120.173714z" fill="#4384F5" p-id="7099"></path></svg>

+ 18 - 0
projects/textbook/public/img/logo-authing.svg

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="3483px" height="1935px" viewBox="0 0 3483 1935" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>svg横版</title>
+    <g id="svg横版" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="编组备份-4" transform="translate(742.000000, 708.500000)" fill="#396AFF">
+            <path d="M649.652831,286.751044 L689.540611,158.531551 L729.425777,286.751044 L649.652831,286.751044 Z M705.900271,105.937594 L673.178337,105.937594 L655.979786,105.937594 L555.310379,414.999284 L609.757211,414.999284 L634.427371,335.696744 L744.653851,335.696744 L769.321396,414.999284 L823.768228,414.999284 L723.098822,105.937594 L705.900271,105.937594 Z" id="Fill-1"></path>
+            <polygon id="Fill-2" points="1151.41355 129.498903 1102.46524 129.498903 1102.46524 177.529925 1067.36253 177.529925 1067.36253 226.478239 1102.46524 226.478239 1102.46524 412.839861 1151.41355 412.839861 1151.41355 226.478239 1186.51626 226.478239 1186.51626 177.529925 1151.41355 177.529925"></polygon>
+            <polygon id="Fill-3" points="1463.06639 412.838293 1512.01209 412.838293 1512.01209 183.557389 1463.06639 183.557389"></polygon>
+            <path d="M988.984336,313.684899 L988.984336,320.558047 C988.984336,349.237107 965.65222,372.569224 936.97316,372.569224 C908.2941,372.569224 884.961983,349.237107 884.961983,320.558047 L884.961983,313.684899 L885.225933,177.363977 L836.280233,177.363977 L836.544183,313.684899 L836.544183,320.558047 C836.544183,375.935237 881.59597,420.987025 936.97316,420.987025 C992.347736,420.987025 1037.39952,375.935237 1037.39952,320.558047 L1037.39952,313.684899 L1037.66609,177.363977 L988.717773,177.363977 L988.984336,313.684899 Z" id="Fill-4"></path>
+            <path d="M1894.52762,362.996732 C1864.70129,362.996732 1840.52244,335.783769 1840.52244,288.779799 C1840.52244,244.023322 1864.70129,214.562866 1894.52762,214.562866 C1924.35656,214.562866 1949.01365,243.87436 1949.01365,288.779799 C1949.01365,337.218506 1924.35656,362.996732 1894.52762,362.996732 L1894.52762,362.996732 Z M1997.95935,330.19117 L1997.95935,177.706589 L1949.01365,177.706589 L1949.01365,202.894194 C1931.55376,183.474284 1907.88191,172.485087 1882.00176,172.485087 C1829.03148,172.485087 1786.0939,218.650167 1786.0939,288.779799 C1786.0939,362.434859 1829.03148,405.074511 1882.00176,405.074511 C1907.88191,405.074511 1931.55376,395.405063 1949.01365,376.690761 L1949.01365,401.781672 L1949.05546,401.781672 L1949.05546,415.318899 C1949.05546,443.707875 1925.95593,466.807403 1897.56434,466.807403 C1869.17275,466.807403 1846.07584,443.707875 1846.07584,415.318899 L1796.61792,415.318899 C1796.61792,470.980945 1841.89968,516.265322 1897.56434,516.265322 C1953.229,516.265322 1998.51338,470.980945 1998.51338,415.318899 L1998.51338,330.19117 L1997.95935,330.19117 Z" id="Fill-6"></path>
+            <path d="M1487.53977,95.1984959 C1469.83422,95.1984959 1455.47901,109.553706 1455.47901,127.261863 C1455.47901,144.967406 1469.83422,159.322616 1487.53977,159.322616 C1505.24792,159.322616 1519.60313,144.967406 1519.60313,127.261863 C1519.60313,109.553706 1505.24792,95.1984959 1487.53977,95.1984959" id="Fill-8"></path>
+            <path d="M1679.51986,169.563084 L1668.45749,169.563084 C1642.3343,169.563084 1603.15213,188.387147 1603.15213,224.454188 L1603.15213,188.083997 L1554.20643,188.083997 L1554.20643,412.161693 L1603.15213,412.161693 L1603.15213,271.850163 C1603.15213,240.983717 1628.17771,215.960754 1659.04415,215.960754 C1686.71968,215.960754 1709.15541,238.396487 1709.15541,266.072015 L1709.15541,412.838555 L1763.31216,412.838555 L1763.31216,253.355384 C1763.31216,207.077929 1725.7947,169.563084 1679.51986,169.563084" id="Fill-10"></path>
+            <path d="M1341.18875,169.563084 L1330.12638,169.563084 C1306.38658,169.563084 1275.95395,181.111541 1267.72447,207.757404 L1267.72447,88.9982891 L1218.77615,88.9982891 L1218.77615,411.111121 L1267.72447,411.111121 L1267.72447,254.16814 C1275.12813,231.975451 1296.03243,215.960754 1320.71043,215.960754 C1348.38857,215.960754 1370.8243,238.396487 1370.8243,266.072015 L1370.8243,412.838555 L1424.98105,412.838555 L1424.98105,253.355384 C1424.98105,207.077929 1387.46359,169.563084 1341.18875,169.563084" id="Fill-12"></path>
+            <path d="M222.727626,464.784136 C117.100667,409.132543 45.0763467,298.284082 45.0763467,170.595102 C45.0763467,167.367597 45.1547476,164.158385 45.2462153,160.954401 L222.756373,52.7088509 L400.21165,160.954401 C400.300504,164.158385 400.381519,167.367597 400.381519,170.595102 C400.381519,298.284082 328.354585,409.132543 222.727626,464.784136 M445.208557,136.1588 L445.208557,136.1588 L222.756373,0.47031162 L0.246695214,136.1588 C0.131707184,140.178154 0.0350127044,144.200122 0.0350127044,148.24561 C0.0350127044,308.308948 90.3189097,447.258915 222.727626,517.022675 C355.136342,447.258915 445.420239,308.308948 445.420239,148.24561 C445.420239,144.200122 445.323545,140.178154 445.208557,136.1588" id="Fill-14"></path>
+            <path d="M262.461478,116.791941 L223.078078,189.929555 L268.487896,272.728776 L223.057171,344.324505 L177.629059,272.728776 L223.038878,189.929555 L184.483914,116.38687 L85.6961295,181.454414 L85.6961295,189.148159 C85.6961295,288.814034 141.755407,375.285032 224.196598,418.523145 C306.640402,374.919161 362.69968,288.448163 362.69968,189.148159 C362.69968,186.587062 362.69968,184.020738 362.69968,181.454414 L262.461478,116.791941 Z" id="Fill-16"></path>
+        </g>
+    </g>
+</svg>

+ 8 - 0
projects/textbook/src/app/app.component.ts

@@ -1,5 +1,6 @@
 import { Component } from '@angular/core';
 import { RouterOutlet } from '@angular/router';
+import Parse from "parse";
 
 @Component({
   selector: 'app-root',
@@ -10,4 +11,11 @@ import { RouterOutlet } from '@angular/router';
 })
 export class AppComponent {
   title = 'textbook';
+  constructor(){
+    this.initParseService();
+  }
+  initParseService(){
+    Parse.initialize("edu-textbook");
+    (Parse as any).serverURL = ("http://localhost:61337/parse");
+  }
 }

+ 12 - 3
projects/textbook/src/app/app.config.ts

@@ -1,8 +1,17 @@
-import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
+
+import { ApplicationConfig, provideZoneChangeDetection, importProvidersFrom } from '@angular/core';
 import { provideRouter } from '@angular/router';
 
 import { routes } from './app.routes';
+import { zh_CN, provideNzI18n } from 'ng-zorro-antd/i18n';
+import { registerLocaleData } from '@angular/common';
+import zh from '@angular/common/locales/zh';
+import { FormsModule } from '@angular/forms';
+import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
+import { provideHttpClient } from '@angular/common/http';
+import { provideIonicAngular } from '@ionic/angular/standalone';
 
+registerLocaleData(zh);
 export const appConfig: ApplicationConfig = {
-  providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)]
-};
+  providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideNzI18n(zh_CN), importProvidersFrom(FormsModule), provideAnimationsAsync(), provideHttpClient(), provideIonicAngular({})]
+};

+ 1 - 1
projects/textbook/src/app/app.routes.ts

@@ -3,7 +3,7 @@ import { Routes } from '@angular/router';
 import { CompUserComponent } from './comp-user/comp-user.component';
 
 export const routes: Routes = [
-  { path: '', redirectTo: '/user/login', pathMatch: 'full' }, // 默认跳转到 '/home'
+  { path: '',loadComponent:()=>import('../modules/textbook/page-home/page-home.component').then(m=>m.PageHomeComponent) }, // 默认跳转到 '/home'
   {
     path: 'user', // 用户登录/注册
     component: CompUserComponent,

+ 1 - 1
projects/textbook/src/index.html

@@ -2,7 +2,7 @@
 <html lang="en">
 <head>
   <meta charset="utf-8">
-  <title>Textbook</title>
+  <title>国家级规划教材遴选系统 - 本科</title>
   <base href="/">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <link rel="icon" type="image/x-icon" href="favicon.ico">

+ 10 - 0
projects/textbook/src/modules/textbook/page-home/footer/footer.component.html

@@ -0,0 +1,10 @@
+<!--页面底部内容-->
+<div class="footer">
+    <div class="link-box">
+        <div class="link-item"><a href="https://www.chsi.com.cn/">学信网</a></div>
+        <div class="link-item"><a href="#">帮助中心</a></div>
+        <div class="link-item"><a href="#">联系我们</a></div>
+        <!--版权所有-->
+        <div class="link-item">Copyright © 2024 蒸汽记忆 Rights Reserved</div>
+    </div>
+</div>

+ 29 - 0
projects/textbook/src/modules/textbook/page-home/footer/footer.component.scss

@@ -0,0 +1,29 @@
+//页面底部内容样式
+.footer{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 70px;
+    min-width: 1100px;
+
+    .link-box{
+        display: flex;
+        flex-direction: row;
+        justify-content: space-evenly;
+
+    .link-item{
+        padding: 10px;
+        color: grey;
+    }
+
+    .link-item a{
+        text-decoration: none;
+        color: grey;
+    }
+
+    .link-item a:hover{
+        text-decoration: underline;
+        color: grey;
+    }
+    }
+}

+ 23 - 0
projects/textbook/src/modules/textbook/page-home/footer/footer.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FooterComponent } from './footer.component';
+
+describe('FooterComponent', () => {
+  let component: FooterComponent;
+  let fixture: ComponentFixture<FooterComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ FooterComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(FooterComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 11 - 0
projects/textbook/src/modules/textbook/page-home/footer/footer.component.ts

@@ -0,0 +1,11 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-footer',
+  templateUrl: './footer.component.html',
+  styleUrls: ['./footer.component.scss'],
+  standalone:true,
+})
+export class FooterComponent {
+
+}

+ 66 - 0
projects/textbook/src/modules/textbook/page-home/header/header.component.html

@@ -0,0 +1,66 @@
+<!-- <fm-modal-user-login #loginModal></fm-modal-user-login> -->
+
+<!--页面顶部内容-->
+<div class="header">
+
+    <!--logo标识-->
+    <div class="logo-box">
+        <div class="logo-content" routerLink="/startup/home">
+            <img class="logo-img" src="/img/book.png" alt="feima-contest-logo">
+            <div class="logo-font">国家级规划教材遴选系统 - 本科</div>
+          </div>
+    </div>
+
+    <!--首页内容快速切换选项-->
+    <div class="quick-jump-box">
+
+        <div class="quick-jump-item" href="#submit">教材填报</div>
+        <div class="quick-jump-item" href="#review">遴选计划</div>
+        <div class="quick-jump-item" href="#contact">联系我们</div>
+        <!-- <div class="quick-jump-item">单项奖设置</div> -->
+        <!-- (click)="showModalSet()" -->
+        <!-- <nz-modal [(nzVisible)]="isVisibleSet" nzTitle="注意事项" nzOkText="确认"
+        nzCancelText="取消" (nzOnCancel)="handleCancelSet()" (nzOnOk)="handleOkSet()">
+            <ng-container *nzModalContent>
+              <p>请检查是否在个人页面的设置中完善个人信息,如未完善请先点击“<strong>取消</strong>”按钮退出弹框完善个人信息。已完善信息可直接点击“<strong>确认</strong>”按钮开始填写参赛信息。</p>
+            </ng-container>
+        </nz-modal> -->
+        <!-- routerLink="/startup/login"   routerLink="/startup/projectCreate"-->
+    </div>
+
+    <!-- <ng-template #rightAvatar> -->
+    <!--未登录-->
+    <!--管理及登录入口-->
+    <div *ngIf="!user?.id" class="login-manage-box"> 
+        <!--管理入口按钮-->
+        <div class="manage-box">
+            <button class="manage-button" routerLink="/user/login">管理入口</button>
+        </div>
+        <!--登录按钮-->
+        <div class="login-box">
+            <!-- <button class="login-button" (click)="loginModal.authServ.isModalShow = true">登录</button> -->
+            <button class="login-button" routerLink="/user/login">登录</button>
+        </div>
+    </div>
+    <!-- 已登录 -->
+    <!-- 展开列表 -->
+    <!-- <a nz-button nzType="default" style="margin-left: 5%; color:none; display: flex; flex-direction: row; align-items: center; cursor: pointer;" 
+    nz-dropdown [nzDropdownMenu]="menu" [nzPlacement]="'bottomRight'"
+    *ngIf="user?.id" class="login-box" [title]="user?.get('mobile')" > -->
+        <!-- 直接显示  -->
+        <!-- <app-comp-user-avatar *ngIf="user?.id" [user]="user" (click)="openUserMenu()" routerLink="/startup/userhome"></app-comp-user-avatar> -->
+
+        <!-- <div class="login-content" style="margin-left: 10px; display: flex; flex-direction: column; " routerLink="/startup/userhome">
+            <div class="login-item" style="display: flex; justify-content: center;">{{user?.get('mobile')}}</div>
+            <div class="login-item" style="display: flex; justify-content: center;">个人中心</div>
+        </div>
+
+        <div class="quit-box">
+            <button class="quit-button" (click)="logout()">退出</button>
+        </div> -->
+    <!-- </a> -->
+    <!-- </ng-template> -->
+
+    
+</div>
+

+ 142 - 0
projects/textbook/src/modules/textbook/page-home/header/header.component.scss

@@ -0,0 +1,142 @@
+//页面顶部内容样式
+.header{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    position: relative;
+    top: 0;
+    height: 90px;
+    width: 100%;
+    min-width: 1100px;
+    border-bottom: 1px solid #f5f5f5;
+
+    //logo标识样式
+    .logo-box{
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+        width: 35%;
+
+        .logo-content{
+            display: flex;
+            cursor: pointer;
+        
+            .logo-img{
+                padding-right: 5px;
+                width: 50px;
+                object-fit: contain;
+            }
+    
+            .logo-font{
+                display: flex;
+                align-items: center;
+                font-size: 25px;
+                font-weight: bold;
+                font-style: italic;
+                color: #143383;
+            }
+        }
+    }
+
+    //首页内容快速切换选项样式
+    .quick-jump-box{
+        display: flex;
+        flex-direction: row;
+        justify-content: space-evenly;
+        width: 35%;
+    
+    .quick-jump-item{
+        font-size: 18px;
+        font-weight: bold;
+        border-bottom: 2px solid #fff;
+        box-sizing: border-box;
+        cursor: pointer;
+    }
+
+    .quick-jump-item:hover{
+        color: #143383;
+        border-bottom: 2px solid rgb(30, 93, 253);
+        box-sizing: border-box;
+    }
+
+    }
+
+    //管理及登录入口样式
+    .login-manage-box{
+        display: flex;
+        flex-direction: row;
+        width: 30%;
+
+    //管理入口按钮
+    .manage-box{
+        margin-left: 30%;
+        display: flex;
+
+        .manage-button{
+            border: none;
+            letter-spacing: 1px;
+            font-size: 16px;
+            color: #645bff;
+            background-color: white;
+            cursor: pointer;
+        }
+
+        .manage-button:hover{
+            border: none;
+            font-size: 16px;
+            color: #000;
+            background-color: white;
+        }
+    }
+    //登录按钮
+    .login-box{
+        margin-left: 5%;
+        display: flex;
+
+        .login-button {
+            padding: 10px;
+            letter-spacing: 1px;
+            border-radius: 10px;
+            border: none;
+            font-size: 16px;
+            color: #fff;
+            background-color: #143383;
+            transition: 0.5s;
+            cursor: pointer;
+           }
+           
+        .login-button:hover {
+            color: #fff;
+            background-color: #645bff;
+            transition: 0.5s;
+           }
+    }
+    
+}
+//退出按钮
+.quit-box{
+    margin-left: 5%;
+    display: flex;
+
+    .quit-button {
+        margin-left: 10%;
+        padding: 10px;
+        letter-spacing: 1px;
+        border-radius: 10px;
+        border: none;
+        min-width: 100px;
+        font-size: 16px;
+        color: #fff;
+        background-color: #143383;
+        transition: 0.5s;
+        cursor: pointer;
+       }
+       
+    .quit-button:hover {
+        color: #fff;
+        background-color: #645bff;
+        transition: 0.5s;
+       }
+}
+}

+ 23 - 0
projects/textbook/src/modules/textbook/page-home/header/header.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HeaderComponent } from './header.component';
+
+describe('HeaderComponent', () => {
+  let component: HeaderComponent;
+  let fixture: ComponentFixture<HeaderComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ HeaderComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(HeaderComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 231 - 0
projects/textbook/src/modules/textbook/page-home/header/header.component.ts

@@ -0,0 +1,231 @@
+import { Component, HostListener, ViewChild, ElementRef } from '@angular/core';
+import { IonMenu, IonNav, NavController, Platform } from '@ionic/angular';
+import { NzModalModule } from 'ng-zorro-antd/modal';
+import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
+// import { AuthService } from 'ng-fmode-admin';
+// import { FormGroup, FormBuilder, Validators, AbstractControl } from '@angular/forms';
+import Parse from "parse";
+// import { AccountService } from '../../modules/account/account.service';
+import { HttpClient } from '@angular/common/http';
+import { NzMessageService } from "ng-zorro-antd/message";
+import { Router, RouterModule } from '@angular/router';
+import { NzButtonModule } from 'ng-zorro-antd/button';
+import { CommonModule } from '@angular/common';
+@Component({
+  selector: 'app-header',
+  templateUrl: './header.component.html',
+  styleUrls: ['./header.component.scss'],
+  imports:[
+    CommonModule,RouterModule,
+    NzButtonModule,NzModalModule,NzDropDownModule,
+  ],
+  standalone:true,
+})
+export class HeaderComponent {
+  @ViewChild(IonMenu) menu:IonMenu|undefined=undefined
+  @ViewChild(IonMenu) userMenu:IonMenu|undefined=undefined
+  @ViewChild("canvas") canvas: ElementRef|undefined=undefined; //本地校验码绘画
+
+  //点击登录弹框设置
+  isLoginShow = false;
+
+  isVisible:boolean = false //分享弹窗
+  imgUrl:string = ""
+
+  openUserMenu(){
+    console.log("openUserMenu")
+    if(this.navMenuType=="mobile"){
+      console.log("mobile");
+      this.userMenu?.toggle();
+    }
+  }
+  user:Parse.User|undefined|null
+  mobileWidth = 915;
+  get leftMenuMode():string{
+    let clientWidth = document.body.clientWidth;
+    if(clientWidth>=915){
+      return "horizontal";
+    }else{
+
+      return "inline";
+    }
+  }
+  get navMenuType():string{
+    let clientWidth = document.body.clientWidth;
+    if(clientWidth>=915){
+      return "pc";
+    }else{
+
+      return "mobile";
+    }
+  }
+  get clientWidth():number {
+    let clientWidth = document.body.clientWidth;
+    return clientWidth
+  }
+  goFeima(){
+    window.open("https://www.fmode.cn","_blank")
+  }
+  isCapacitor:boolean = false
+  constructor(
+    // public authServ:AuthService,
+    // public accServ:AccountService,
+    private navCtrl:NavController,
+    private platform:Platform,
+    private http : HttpClient,
+    private message: NzMessageService,
+    public router:Router,
+    ){
+    // this.accServ.getBilling();
+    this.isCapacitor = this.platform.is("capacitor")
+    this.getCode()
+  }
+  setRoot(path:string){
+    if(this.menu?.close){
+      this.menu?.close();
+    }
+    this.navCtrl.navigateRoot(path);
+  }
+  async ngOnInit() {
+    this.user = await Parse.User.currentAsync()
+  }
+  logout(){
+    // this.authServ.logout(null,"../")
+  }
+
+  //海报
+  bannerUrl:string = 'https://file-cloud.fmode.cn/UP2cStyjuk/20231113/r1r7em033605088.jpg@3000w_1l_0o_100sh'
+  codeUrl:string|undefined = undefined
+  async getCode(){
+    let uid = (await Parse.User.currentAsync())?.id
+    let qrCodeUrl = `https://ai.fmode.cn/?invite=${uid}`;
+    let params = {
+      qrCode: qrCodeUrl,
+      darkColor: "#ffffff",
+      lightColor: "#000000"
+    }
+    this.http.get('https://server.fmode.cn/api/common/qrcode',{params})
+    .subscribe((res:any)=>{
+      // console.log(res);
+      this.codeUrl = res.data
+    })
+  }
+  
+  onShowModal(){
+    this.isVisible = true
+    this.drawPoster()
+  }
+  handleOk(){
+    this.onClose()
+  }
+  onClose(){
+    this.isVisible = false
+  }
+  //绘画海报
+  async drawPoster(){
+    let canvas:any = document.createElement('canvas')
+    canvas.height = '360'
+    canvas.width = '200'
+    // if(!canvas){
+    //   setTimeout(() => {
+    //     this.drawPoster()
+    //   }, 500);
+    //   return
+    // }
+    let ctx = canvas.getContext('2d');
+    //定义图片
+    ctx.drawImage(await this.compileImage(this.bannerUrl), 0, 0, 340, 540);
+    //绘制二维码
+    ctx.drawImage(await this.compileImage(this.codeUrl), 60 ,180, 80, 80);
+    let tempSrc = canvas.toDataURL("image/png");
+    this.imgUrl = tempSrc;
+    document.body.removeChild(canvas);
+  }
+  compileImage(url?:string): Promise<any>{
+    return new Promise((res)=>{
+      if(!url) {res(false);return}
+      let img = new Image();
+      img.src = url;
+      img.setAttribute('crossOrigin', 'anonymous');
+      img.onload = function() {
+        res (img)
+      }
+    })
+  }
+
+  /**
+   * 返回当前元素的文本内容
+  */
+  copyText(){
+    let uid = Parse.User.current()?.id
+    let text = `https://ai.fmode.cn/?invite=${uid}`;
+    let textareaC = document.createElement('textarea');
+    textareaC.setAttribute('readonly', 'readonly'); //设置只读属性防止手机上弹出软键盘
+    textareaC.value = text;
+    // textareaC.style.display = 'none'
+    document.body.appendChild(textareaC); //将textarea添加为body子元素
+    textareaC.select();
+    const res = document.execCommand('copy');
+    document.body.removeChild(textareaC);//移除DOM元素
+    console.log("复制成功");
+    this.message.success("复制成功");
+    window.location.href = 'weixin://';
+    return res;
+  }
+  /* 下载海报 */
+  downImg(){
+    let dlLink:any = document.createElement('a');
+    if ('download' in dlLink) {
+      dlLink.style.visibility = 'hidden';
+      dlLink.href = this.imgUrl;
+      dlLink.download = '分享海报';
+      document.body.appendChild(dlLink);
+      dlLink.click();
+      document.body.removeChild(dlLink);
+    } else {
+      location.href = this.imgUrl;
+    }
+  }
+
+  //登录逻辑引用
+  /**是否展示登录组件 */
+  isLoading:boolean=false
+
+  async goLogin(){
+    // let data:any
+    if(!Parse.User.current()?.getSessionToken()){
+      this.router.navigate(['startup/login'])
+      this.isLoading = true
+      setTimeout(() => {
+        this.goLogin()
+      }, 500);
+      return
+    }
+    this.isLoading = false
+   
+  }
+
+  // createBasicMessage(): void {
+  //   this.message.info('请先进行登录');
+  // }
+
+  //报名参赛提示框:提示完善个人信息
+  // isVisibleSet = false;
+
+
+  // showModalSet(): void {
+  //   this.goLogin();
+  //   this.isVisibleSet = true;
+  // }
+
+  // handleOkSet(): void {
+  //   // console.log('Button ok clicked!');
+  //   this.router.navigate(['startup/projectCreate'])
+  //   this.isVisibleSet = false;
+  // }
+
+  // handleCancelSet(): void {
+  //   // console.log('Button cancel clicked!');
+  //   this.isVisibleSet = false;
+  // }
+}

+ 242 - 0
projects/textbook/src/modules/textbook/page-home/page-home.component.html

@@ -0,0 +1,242 @@
+<ng-container>
+    <app-header></app-header>
+</ng-container>
+<div class="content">
+
+<!--图片盒子-->
+<div class="landscape-box">
+    <!-- Created by ai.fmode.cn imagine -->
+    <img class="landscape" src="/img/banner-lab.png" alt="feima-contest-background">
+
+    <div class="landscape-text">
+        <div class="landscape-title">《“十四五”普通高等教育本科国家级规划教材建设实施方案》</div>
+        <div class="landscape-desc">到2025年,教育部“十四五”本科规划教材重点立项建设1000种左右,遴选5000种左右,加快自主知识体系与教材体系建设,着力打造中国特色、世界水平的高质量教材体系,为高等教育强国建设提供坚实支撑。
+            <br>(一)深入推进新时代党的创新理论进教材
+            <br>(二)重点建设一批关键领域核心教材
+            <br>(三)培育和打造一批经典传承教材
+            <br>(四)探索建设一批示范性新形态教材
+            <br>“十四五”规划教材建设实行国家、省、校三级联动,有效衔接,全面建成国家、省、校三级本科规划教材体系。教育部采取重点立项与统一推荐遴选相结合方式,对“十四五”期间完成的新编或修订教材,开展“十四五”国家级规划教材认定工作。教材编写工作强化科教协同、产学合作,鼓励和支持打破部门、校际、学科专业和校内校外壁垒。
+    
+        </div>
+    </div>
+</div>
+
+<!--角色入口-->
+<div class="track-box" id="submit">
+
+    <div class="track-card">
+        <div class="button-card">
+        <button>
+            <span>教材创建</span>
+        </button>
+        </div>
+        
+        <div class="track-one-explain">作者、教师、主编</div>
+    </div>
+
+    <div class="track-card">
+        <div class="button-card">
+        <button>
+            <span>教材查看</span>
+        </button>
+        </div>
+        
+        <div class="track-one-explain">省属高校联系人</div>
+    </div>
+
+    <div class="track-card">
+        <div class="button-card">
+        <button>
+            <span>教材报送</span>
+        </button>
+        </div>
+        
+        <div class="track-one-explain">省级教育行政部门、出版单位联系人</div>
+    </div>
+
+
+    <div class="track-card">
+        <div class="button-card">
+        <button>
+            <span>教材公示</span>
+        </button>
+        </div>
+        
+        <div class="track-one-explain">省级教育行政部门报送人</div>
+    </div>
+</div>
+
+<!--模块标题:遴选计划-->
+<div class="module-title" id="review">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <div class="module-font">遴选计划</div>
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+</div>
+
+<!--遴选计划时间轴-->
+<div class="contest-plan-box">
+    <!-- <img class="contest-plan" src="https://file-cloud.fmode.cn/E4KpGvTEto/20231103/81nvch031047190.png" alt="contest-plan"> -->
+    <div class="box">
+        <div class="firstLine">
+            <ion-row>
+                <ion-col size='1.7'></ion-col>
+                <ion-col size='1.7'>
+                    <p class="text">提交</p>
+                    <div class="crossLine"></div>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <p class="date" style="margin-bottom: -2em;">2024.3.16 - 3.31</p>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <p class="text">评审</p>
+                    <div class="crossLine"></div>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <p class="date" style="margin-bottom: -2em;">2024.05</p>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <p class="text">公示</p>
+                    <div class="crossLine"></div>
+                </ion-col>
+                <ion-col size='1.7'></ion-col>
+            </ion-row>
+        </div>
+        <div class="seconfLine">
+            <ion-row>
+                <ion-col size='1.7'>
+                    <div class="wrap">
+                        <div class="line"></div>
+                        <div class="ball">
+                            <div class="outer" style="background-color: unset;"></div>
+                            <div class="inner" style="background-color: unset;"></div>
+                        </div>
+                    </div>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <div></div>
+                    <div class="wrap">
+                        <div class="line"></div>
+                        <div class="ball">
+                            <div class="outer"></div>
+                            <div class="inner"></div>
+                        </div>
+                    </div>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <div class="wrap">
+                        <div class="line"></div>
+                        <div class="ball">
+                            <div class="outer"></div>
+                            <div class="inner"></div>
+                        </div>
+                    </div>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <div class="wrap">
+                        <div class="line"></div>
+                        <div class="ball">
+                            <div class="outer"></div>
+                            <div class="inner"></div>
+                        </div>
+                    </div>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <div class="wrap">
+                        <div class="line"></div>
+                        <div class="ball">
+                            <div class="outer"></div>
+                            <div class="inner"></div>
+                        </div>
+                    </div>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <div class="wrap">
+                        <div class="line"></div>
+                        <div class="ball">
+                            <div class="outer"></div>
+                            <div class="inner"></div>
+                        </div>
+                    </div>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <div class="wrap">
+                        <div class="line"></div>
+                        <div class="ball">
+                            <div class="outer" style="background-color: unset;"></div>
+                            <div class="inner" style="background-color: unset;"></div>
+                        </div>
+                    </div>
+                </ion-col>
+            </ion-row>
+        </div>
+        <div class="thirdLine">
+            <ion-row>
+                <ion-col size='1.7'></ion-col>
+                <ion-col size='1.7'>
+                    <p class="date" style="margin-bottom: 2em;">2024.2.27 - 3.15</p>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <div class="crossLine"></div>
+                    <p class="text" style="margin-bottom: unset;margin-top: 1em;">初审</p>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <p class="date" style="margin-bottom: 2em;">2024.04</p>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <div class="crossLine"></div>
+                    <p class="text" style="margin-bottom: unset;margin-top: 1em;">报送</p>
+                </ion-col>
+                <ion-col size='1.7'>
+                    <p class="date" style="margin-bottom: 2em;">2024.06</p>
+                </ion-col>
+                <ion-col size='1.7'></ion-col>
+            </ion-row>
+        </div>
+    </div>
+</div>
+
+<!--模块标题:技术支持单位-->
+<div class="module-title">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <div class="module-font">技术支持</div>
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+</div>
+
+<!--技术支持单位展示盒子-->
+<div class="support-company-box">
+    <img class="company-icon" src="/img/logo-authing.svg" alt="contest-plan">
+</div>
+
+<!--模块标题:联系我们-->
+<div class="module-title" id="contact">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <img class="left-arrow" src="/icon/left-arrow.png" alt="left-arrow">
+    <div class="module-font">联系我们</div>
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+    <img class="right-arrow" src="/icon/right-arrow.png" alt="right-arrow">
+</div>
+
+<!--联系详情页-->
+<div class="contact-box">
+    <div class="contact-content">
+        <div class="contact-item">咨询: 教育部高等教育司教学条件处 刘某 010-66096925 gaojs_jxtj&#64;moe.edu.cn</div>
+        <div class="contact-item">咨询: 中国高等教育学会秘书处 赵某 010-59893293 gjxhjc&#64;hie.edu.cn</div>
+        <div class="contact-item">工作时间: 周一至周五 9:00-18:00</div>
+    </div>
+
+    <div class="erweima-box">
+        <img class="contact-erweima" src="https://files.authing.co/authing-website/wechat-code.jpg" alt="wx-erweima">
+    </div>
+</div>
+
+</div>

+ 319 - 0
projects/textbook/src/modules/textbook/page-home/page-home.component.scss

@@ -0,0 +1,319 @@
+.content{
+    margin: 0;
+    padding: 0;
+    width: auto;
+    min-width: 1100px;
+    height:calc(100% - 90px);
+    overflow-y: scroll;
+
+//图片盒子样式
+.landscape-box {
+    position: relative;
+    width: 100%;
+    height: 600px;
+    }
+
+    .landscape {
+        width: 100%;
+        height: 100%;
+        object-fit: cover;
+    }
+    .landscape-text{
+        position: absolute;
+        padding: 10px;
+        top: 12%;
+        left: 10%;
+        width:80%;
+        display: flex;
+        flex-direction: column;
+        text-align: left;
+        background-color: rgba(0, 0, 0, 0.4);
+        .landscape-title {
+            color: #fff;
+            font-size: 2rem;
+            font-family: FZZongYi-M05S;
+            font-weight: 600;
+        }
+        
+        .landscape-desc {
+            margin-top:20px;
+            margin-left:20px;
+            width: 60%;
+            font-size: 1rem;
+            color: #fff;
+            font-family: FZZhengHeiS-EB-GB;
+            font-style: italic;
+        }
+        
+}
+    //屏幕大小比例校准
+    @media (max-width: 1300px) {
+        .landscape-desc {
+            width: 50%;
+        }
+    }
+    
+    @media (min-width: 1500px) {
+        .landscape-desc {
+            width: 40%;
+        }
+    }
+
+
+//赛道盒子样式
+.track-box{
+    margin: 2% 5%;
+    display: flex;
+    flex-wrap:wrap;
+    flex-direction: row;
+    justify-content: space-evenly;
+
+    //码争赛道盒子样式
+    .track-card{
+        display: flex;
+        flex-direction: column;
+        justify-content: space-evenly;
+        position: relative;
+        width: 45%;
+        height: 180px;
+        margin-bottom: 10px;
+        background: #fff;
+        border: 1px solid var(--color-secondary-blue);
+        border-radius: 5px;
+        box-shadow: 4px 4px 4px rgba(78,120,203,0.75);
+
+    .button-card{
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+
+        //参考链接:https://uiverse.io/abrahamcalsin/sour-donkey-65
+        button {
+            position: relative;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            border-radius: 20px;
+            background: var(--color-primary-purple);
+            font-family: "Montserrat", sans-serif;
+            overflow: hidden;
+            border: none;
+            cursor: pointer;
+           }
+           
+           button:after {
+            content: " ";
+            width: 0%;
+            height: 100%;
+            background: #FFD401;
+            position: absolute;
+            transition: all 0.4s ease-in-out;
+            right: 0;
+           }
+           
+           button:hover::after {
+            right: auto;
+            left: 0;
+            width: 100%;
+           }
+           
+           button span {
+            text-align: center;
+            text-decoration: none;
+            width: 100%;
+            padding: 12px 19px;
+            color: #fff;
+            font-size: 18px;
+            font-weight: bold;
+            font-style: italic;
+            letter-spacing: 2px;
+            z-index: 20;
+            transition: all 0.3s ease-in-out;
+           }
+           
+           button:hover span {
+            color: var(--color-primary-purple);
+            animation: scaleUp 0.3s ease-in-out;
+           }
+           
+           @keyframes scaleUp {
+            0% {
+             transform: scale(1);
+            }
+           
+            50% {
+             transform: scale(0.95);
+            }
+           
+            100% {
+             transform: scale(1);
+            }
+           }
+    }
+
+    .track-one-explain{
+        display: flex;
+        justify-content: center;
+        font-size: 15px;
+        font-weight: bold;
+    }
+    }
+
+}
+
+//模块标题统一样式
+.module-title{
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    height: 10%;
+    background-color: #f2f6fa;
+
+    .right-arrow{
+        width: 14px;
+        object-fit: contain;
+    }
+
+    .module-font{
+        padding: 1%;
+        font-size: 30px;
+        font-weight: bold;
+        font-style: italic;
+        color: #000;
+    }
+
+    .left-arrow{
+        width: 14px;
+        object-fit: contain;
+    }
+}
+
+//比赛计划详情样式
+.contest-plan-box{
+    display: flex;
+    justify-content: center;
+    .box{
+        width: 80%;
+        .crossLine{
+            height: 2px;
+            width: 25%;
+            background-color: var(--color-primary-purple);
+            margin-top: 5px;
+            transform: rotate(90deg);
+        }
+        .text{
+            font-size: x-large;
+            font-weight: bold;
+            color: var(--color-primary-purple);
+        }
+        .date{
+            font-size: medium;
+            font-weight: bold;
+        }
+        ion-row{
+            ion-col{
+                display: flex;
+                justify-content: center;
+                flex-direction: column;
+                align-items: center;
+            }
+        }
+        .firstLine{
+            width: 100%;
+        }
+        .seconfLine{
+            width: 100%;
+            margin: 1rem 0;
+            .wrap{
+                position: relative;
+                width: 100%;
+                display: flex;
+                justify-content: center;
+                .line{
+                    height: 2px;
+                    width: 100%;
+                    background-color: var(--color-primary-purple);
+                    position: absolute;
+                    margin-top: 3px;
+                }
+                .ball{
+                    align-items: center;
+                    display: flex;
+                    justify-content: center;
+                    position: relative;
+                    width: 17px;
+                    .outer{
+                        border-radius: 50%;
+                        height: 17px;
+                        left: 0;
+                        opacity: .2;
+                        position: absolute;
+                        width: 17px;
+                        background-color: rgba(255, 0, 0, 0.486);
+                      
+                        transition: background-color 0.3s, width 0.3s, height 0.3s , margin-left 0.3s;
+                      }
+                      
+                      .outer:hover {
+                        background-color: rgba(255, 0, 0, 0.486);
+                        margin-left: -0.5rem;
+                        width: 34px;
+                        height: 34px;
+                    }
+                    .inner{
+                        border-radius: 50%;
+                        height: 9px;
+                        width: 9px;
+                        background-color: red;
+                    }
+                }
+            }
+        }
+    }
+}
+
+//技术支持单位展示样式
+.support-company-box{
+    display: flex;
+    justify-content: center;
+
+    .company-icon{
+        width: 160px;
+        object-fit: contain;
+    }
+}
+
+//联系详情页样式
+.contact-box{
+    padding: 1% 0;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+
+    .contact-content{
+        display: flex;
+        flex-direction: column;
+
+        .contact-item{
+            padding: 1% 0;
+            font-size: 16px;
+            font-weight: 600;
+        }
+    }
+
+    .erweima-box{
+        padding-left: 5%;
+        display: flex;
+        align-items: center;
+
+        .contact-erweima{
+            width: 100px;
+            object-fit: contain;
+        }
+    }
+}
+
+}

+ 23 - 0
projects/textbook/src/modules/textbook/page-home/page-home.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PageHomeComponent } from './page-home.component';
+
+describe('PageHomeComponent', () => {
+  let component: PageHomeComponent;
+  let fixture: ComponentFixture<PageHomeComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ PageHomeComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(PageHomeComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 18 - 0
projects/textbook/src/modules/textbook/page-home/page-home.component.ts

@@ -0,0 +1,18 @@
+import { Component } from '@angular/core';
+import { IonicModule } from '@ionic/angular';
+import { FooterComponent } from './footer/footer.component';
+import { HeaderComponent } from './header/header.component';
+
+@Component({
+  selector: 'app-page-home',
+  templateUrl: './page-home.component.html',
+  styleUrls: ['./page-home.component.scss'],
+  standalone:true,
+  imports:[
+    HeaderComponent,FooterComponent,
+    IonicModule
+  ]
+})
+export class PageHomeComponent {
+  constructor(){}
+}

+ 11 - 0
projects/textbook/src/modules/textbook/textbook-routing.module.ts

@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+const routes: Routes = [
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule]
+})
+export class TextbookRoutingModule { }

+ 13 - 0
projects/textbook/src/modules/textbook/textbook.module.ts

@@ -0,0 +1,13 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { TextbookRoutingModule } from './textbook-routing.module';
+
+@NgModule({
+  declarations: [],
+  imports: [
+    CommonModule,
+    TextbookRoutingModule
+  ]
+})
+export class TextbookModule { }

+ 17 - 0
projects/textbook/src/styles.scss

@@ -1 +1,18 @@
 /* You can add global styles to this file, and also import other style files */
+:root{
+    --color-primary-blue:#143383;
+    --color-secondary-blue:#645bff;
+    --color-primary-purple:#143383;
+}
+// --color-primary-purle:#7F30C5;
+/**
+ * Ionic Dark Theme
+ * -----------------------------------------------------
+ * For more info, please see:
+ * https://ionicframework.com/docs/theming/dark-mode
+ */
+
+//  @import "@ionic/angular/css/palettes/dark.always.css";
+ /* @import "@ionic/angular/css/palettes/dark.class.css"; */
+ /* @import "@ionic/angular/css/palettes/dark.system.css"; */
+ 

+ 2 - 1
src/app/app.config.ts

@@ -8,9 +8,10 @@ import zh from '@angular/common/locales/zh';
 import { FormsModule } from '@angular/forms';
 import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
 import { provideHttpClient } from '@angular/common/http';
+import { provideIonicAngular } from '@ionic/angular/standalone';
 
 registerLocaleData(zh);
 
 export const appConfig: ApplicationConfig = {
-  providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideNzI18n(zh_CN), importProvidersFrom(FormsModule), provideAnimationsAsync(), provideHttpClient()]
+  providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideNzI18n(zh_CN), importProvidersFrom(FormsModule), provideAnimationsAsync(), provideHttpClient(), provideIonicAngular({})]
 };