Ver código fonte

重要学API

托合提如苏力 2 anos atrás
pai
commit
a4f3f9e2b4

+ 2 - 0
.env.development

@@ -0,0 +1,2 @@
+// 自定义环境变量里面绑定有个有前缀的api
+VITE_API_BASE_URL = /api

+ 514 - 1
README.md

@@ -94,5 +94,518 @@ npm run build
 ### 清理不用的文件
 
 > 可以清理的文件名称:`components`文件夹删除 ,并 `assets`文件夹里面文件删除。,并`main.js` 里面的 `css` 引入方法清除就要可以啦。
+
+### V-Router引入
+
+> 引入方法
+
+```sh
+npm install vue-router@4
+```
+
+#### 创建两个组件
+
+> 按视图`views` 文件夹里面分别创建:`Login` 和 `Dashboard` 。然后每个组件单独创建vue文件。
+
+Login页面(名为:`index.vue` )。
+
+```vue
+<template>
+  <div>登录页面</div>
+</template>
+
+<script setup lang="ts">
+
+</script>
+```
+
+Dashboard页面(名为:`index.vue` )。
+
+```vue
+<template>
+  <div>控制台</div>
+</template>
+
+<script setup lang="ts">
+
+</script>
+```
+
+> 我们用的是路由所以,先创建一个路由文件夹(名为:`router` )。该路由里面创建一个主入口(名为:`index.ts` )。
+
+```ts
+// 引入router的组件
+import type { RouteRecordRaw } from "vue-router";
+// 引入两个组件
+import LoginView from "@/views/login/index.vue"
+import DashboardView from "@/views/dashboard/index.vue"
+import {createRouter, createWebHashHistory} from "vue-router";
+
+// 2. 定义一些路由
+// 每个路由都需要映射到一个组件。
+// 我们后面再讨论嵌套路由。
+const routes:Array<RouteRecordRaw> = [
+    { path:'/', name : 'dashboard', component : DashboardView },
+    { path:'/login', name : 'login', component : LoginView }
+]
+
+// 3. 创建路由实例并传递 `routes` 配置
+// 你可以在这里输入更多的配置,但我们在这里
+// 暂时保持简单
+const router = createRouter({
+    // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
+    history: createWebHashHistory(),
+    strict: true,  // 按照严模式匹配
+    routes, // `routes: routes` 的缩写
+    scrollBehavior : () => ({ left:0, top:0 })   //跳转页面之后回到顶部
+})
+
+export default router   // 导出路由
+```
+
+#### 创建并挂载根实例(`main.ts`)
+
+```ts
+import { createApp } from 'vue'
+import App from './App.vue'
+// 引入路由
+import router from "@/views/router/index.ts";
+const app = createApp(App)
+// 挂载根实例
+app.use(router)
+app.mount('#app')
+```
+
+#### 跟应用里面引入路由
+
+```vue
+<template>
+  <router-view></router-view>
+</template>
+
+<script lang="ts" setup></script>
+```
+
+#### 启动系统
+
+> 启动之后进入的是默认页面,也就是说控制台页面。(`Index.vue`页面)。
 >
-> 
+> 如果是想进去Login页面的话网站后面加入`login` 就能进入登录页面。(`Index.vue` 页面)
+
+### 引入 `T Design` 
+
+#### 引入方法
+
+> 官方网站地址:
+>
+> ```
+> https://tdesign.tencent.com/vue-next/overview
+> ```
+>
+> 安装`TDesign`
+>
+> ```sh
+> npm i tdesign-vue-next
+> ```
+
+#### 引入项目中
+
+> `main.ts` 中引入组件
+>
+> ```ts
+> import { createApp } from 'vue'
+> import App from './App.vue'
+> // 引入TDesign
+> import TDesign from 'tdesign-vue-next';
+> // 引入组件库的少量全局样式变量
+> import 'tdesign-vue-next/dist/reset.css';
+> import 'tdesign-vue-next/es/style/index.css';
+> // 引入路由
+> import router from "@/views/router/index.ts";
+> const app = createApp(App)
+> // 挂载根实例
+> app.use(router)
+> // 挂载根实例
+> app.use(TDesign)
+> app.mount('#app')
+> ```
+
+#### 项目中使用
+
+> Login页面使用一下`t-button` 标签,查看是否成功引入了
+
+```vue
+<template>
+  <div>登录页面</div>
+  <t-button>点击我</t-button>
+</template>
+
+<script lang="ts" setup>
+
+</script>
+
+<style scoped>
+
+</style>
+```
+
+#### 安装lass 的编译器和lass luodei
+
+> 安装方法:
+
+```sh
+npm i less less-loader -D
+```
+
+### 登录页面
+
+> 登录页面的装修
+
+```vue
+<template>
+  <img class="wave" src="../../assets/img/wave.png" alt=""/>
+  <div class="container">
+    <div class="bg">
+      <img src="../../assets/img/bg.svg" alt="">
+    </div>
+    <div class="login-container">
+        // 引入 T-Design 的卡片
+      <t-card class="login-cart">
+        <img class="avatar" src="../../assets/img/avatar.svg" alt="">
+        <h2>Vue3-Admin</h2>
+       // 引入 T-Design 的表单
+        <t-form ref="form" class="login-from" :colon="true" :label-width="0">
+          <t-form-item name="username">
+            <t-input clearable placeholder="请输入账户名">
+              <template #prefix-icon>
+                <icon name="user"/>
+              </template>
+            </t-input>
+          </t-form-item>
+
+          <t-form-item name="password">
+            <t-input type="password" clearable placeholder="请输入密码">
+              <template #prefix-icon>
+                <icon name="lock-on"/>
+              </template>
+            </t-input>
+          </t-form-item>
+
+          <t-form-item>
+            <t-button theme="primary" type="submit" block>登录</t-button>
+          </t-form-item>
+        </t-form>
+      </t-card>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+// 引入icon
+import {Icon} from "tdesign-vue-next";
+</script>
+
+<style lang="less" scoped>
+template {
+  overflow: hidden;
+}
+
+.wave {
+  position: fixed;
+  height: 100%;
+  left: 0;
+  bottom: 0;
+  z-index: -1;
+}
+
+.container {
+  width: 100vw;
+  height: 100vh;
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  grid-gap: 7rem;
+  padding: 0 2rem;
+
+  .bg {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+  }
+
+  .bg img {
+    width: 500px;
+  }
+
+  .avatar {
+    width: 100px;
+  }
+
+  .login-container {
+    display: flex;
+    width: 380px;
+    flex-direction: column;
+    align-items: center;
+    text-align: center;
+    justify-content: center;
+
+    .login-cart {
+      width: 100%;
+
+      h2 {
+        font-size: 2.5rem;
+        margin: 25px 0;
+        color: #333;
+      }
+    }
+
+    .login-from {
+      width: 100%;
+    }
+  }
+}
+</style>
+```
+
+>引入`T-Design` 的卡片和表单
+
+```vue
+<t-card class="login-cart">
+        <img class="avatar" src="../../assets/img/avatar.svg" alt="">
+        <h2>Vue3-Admin</h2>
+        <t-form ref="form" class="login-from" :colon="true" :label-width="0">
+          <t-form-item name="username">
+            <t-input clearable placeholder="请输入账户名">
+              <template #prefix-icon>
+                <icon name="user"/>
+              </template>
+            </t-input>
+          </t-form-item>
+
+          <t-form-item name="password">
+            <t-input type="password" clearable placeholder="请输入密码">
+              <template #prefix-icon>
+                <icon name="lock-on"/>
+              </template>
+            </t-input>
+          </t-form-item>
+
+          <t-form-item>
+            <t-button theme="primary" type="submit" block>登录</t-button>
+          </t-form-item>
+        </t-form>
+      </t-card>
+```
+
+#### 验证账号和密码:
+
+>做一个模型,模型就是`type` 关键词来创建。
+
+```vue
+<script lang="ts" setup>
+// 引入icon
+import {Icon} from "tdesign-vue-next";
+// 创建用户和密码的模型
+type LoginFrom = {
+    username:string,
+    password:string
+}
+// 创建对象,reactive 是对象的关键词,<用户和密码的模型>
+const loginFrom = reactive<LoginFrom>({
+    username:'',
+    password:''
+})
+</script>
+```
+
+#### 数据绑定
+
+> 数据绑定:
+>
+> * 使用`:data="loginFrom"` 来绑定数据。数据绑定在 `t-form` 标签里面写入。
+> * 使用`v-model="loginFrom.username"` 来绑定用户数据。该数据 `t-input` 里面写入。
+> * 使用`v-model="loginFrom.password"` 来绑定密码数据。该数据 `t-input` 里面写入。
+>
+> 查看相应,打开网站的检查vue,然后输入在里面检查就可以啦。
+
+#### 验证规则
+
+> 验证规则是用`rules`
+
+```vue
+<script lang="ts" setup>
+    const rules = {
+        username:[
+         { required: true, message: '请输入账号...' },
+        ],
+        password:[
+          { required: true, message: '请输入密码...' },
+        ]
+    }
+         
+</script>
+```
+
+#### 登录功能及Pina全局状态管理
+
+##### API简单封装,API错误处理和全局提示
+
+> 安装API封装组件:`axios`  。
+
+```sh
+npm install axios
+```
+
+> 安装完成后,我们总是API封装 `src` 目录里面创建一个单独 `api` 文件夹,并创建`request.ts` 文件。
+>
+> `request.ts` 文件的作用:封装操作,
+
+* 引入 `axios` 
+
+```ts
+import axios from "axios";
+```
+
+* 定义常量
+
+  > 请求常量
+
+  ```ts
+  const BASE_URL = import.mate.env.VITE_API_BASE_URL;
+  ```
+
+* 创建实例
+
+  ```ts
+  // 创建实例
+  const instanse:AxiosInstance = axios.create({
+  // 添加参数
+      baseURL: BASE_URL,   //路径参数
+      timeout: 60000       // 请求超时设置1分钟
+  })
+  ```
+
+* 总体代码
+
+```ts
+// 引入axios组件
+import axios from "axios";
+import type {AxiosInstance} from "axios"
+/**
+ * 指定常量  环境变量来定义自定义环境,指定环境变量
+ * 指定环境变量前面加前缀名VITE_API不然不能读取
+  */
+const BASE_URL:string = import.meta.env.VITE_API_BASE_URL;
+
+// 创建实例
+const instanse:AxiosInstance = axios.create({
+// 添加参数
+    baseURL: BASE_URL,   //路径参数
+    timeout: 60000       // 请求超时设置1分钟
+})
+
+// 导出参数
+export default instanse
+```
+
+##### 编辑多态化文件
+
+> 多态化环境编辑文件名称:`.env.development` 。
+>
+> 在总根目录里面创建这个文件。
+
+```
+// 自定义环境变量里面绑定有个有前缀的api
+VITE_API_BASE_URL = /api
+```
+
+##### 创建实例化API封装文件
+
+* 创建`token`接口
+
+  > 在api文件夹里面创建`token.ts` 文件。
+
+  ```ts
+  import * as process from "process";
+  import type {AxiosPromise} from "axios";
+  import request from "@/api/request";
+  import type { TokenRequest } from "@/api/types"
+  
+  
+  const createToken = (tokenRequest:TokenRequest):Promise<AxiosPromise<string>> => {
+      return request.post('/token', tokenRequest)
+  }
+  
+  
+  export default {
+      createToken,  // 导出createToken接口
+  };
+  ```
+
+  
+
+* 创建一个专门管理`type` 的文件。文件名称为:`types.ts` 
+
+  > 作用:
+
+  ```ts
+  //创建模型
+  export type TokenRequest = {
+      username: string,
+      password: string
+  }
+  ```
+
+  
+
+* `Index.vue` 的修改
+
+  > `Index.vue` 里面传入`types.ts` 文件,并且修改关键词
+
+  ```vue
+  <script lang="ts" setup>
+  	import type { TokenRequest } from "@/api/token"
+      
+      // 创建对象,reactive 是对象的关键词,<用户和密码的模型>
+  	const loginFrom = reactive<TokenRequest>({
+      	username:'',
+      	password:''
+  	})
+  </script>
+  ```
+
+* 
+
+
+
+
+
+
+
+
+
+## 问题:
+
+### 1. `request.ts` 里面显示的错误提示
+
+![image-20231206220046321](C:\Users\托合提如苏力\AppData\Roaming\Typora\typora-user-images\image-20231206220046321.png)
+
+解决方案:
+
+
+
+
+
+### 2.  `token.ts` 里面显示的错误提示
+
+![image-20231206220229618](C:\Users\托合提如苏力\AppData\Roaming\Typora\typora-user-images\image-20231206220229618.png)
+
+解决方案:
+
+
+
+### 3.   `Index.vue` 里面显示的错误提示
+
+![image-20231206220326349](C:\Users\托合提如苏力\AppData\Roaming\Typora\typora-user-images\image-20231206220326349.png)
+
+解决方案:
+

Diferenças do arquivo suprimidas por serem muito extensas
+ 739 - 3
package-lock.json


+ 6 - 1
package.json

@@ -12,7 +12,10 @@
     "format": "prettier --write src/"
   },
   "dependencies": {
-    "vue": "^3.3.4"
+    "axios": "^1.6.2",
+    "tdesign-vue-next": "^1.7.0",
+    "vue": "^3.3.4",
+    "vue-router": "^4.2.5"
   },
   "devDependencies": {
     "@rushstack/eslint-patch": "^1.3.3",
@@ -24,6 +27,8 @@
     "@vue/tsconfig": "^0.4.0",
     "eslint": "^8.49.0",
     "eslint-plugin-vue": "^9.17.0",
+    "less": "^4.2.0",
+    "less-loader": "^11.1.3",
     "npm-run-all2": "^6.1.1",
     "prettier": "^3.0.3",
     "typescript": "~5.2.0",

+ 3 - 1
src/App.vue

@@ -1,3 +1,5 @@
-<template>初始化项目</template>
+<template>
+  <router-view></router-view>
+</template>
 
 <script lang="ts" setup></script>

+ 18 - 0
src/api/request.ts

@@ -0,0 +1,18 @@
+// 引入axios组件
+import axios from "axios";
+import type {AxiosInstance} from "axios"
+/**
+ * 指定常量  环境变量来定义自定义环境,指定环境变量
+ * 指定环境变量前面加前缀名VITE_API不然不能读取
+  */
+const BASE_URL:string = import.meta.env.VITE_API_BASE_URL;
+
+// 创建实例
+const instanse:AxiosInstance = axios.create({
+// 添加参数
+    baseURL: BASE_URL,   // 路径参数
+    timeout: 60000       // 请求超时设置1分钟
+})
+
+// 导出参数
+export default instanse

+ 14 - 0
src/api/token.ts

@@ -0,0 +1,14 @@
+import * as process from "process";
+import type {AxiosPromise} from "axios";
+import request from "@/api/request";
+import type { TokenRequest } from "@/api/types"
+
+
+const createToken = (tokenRequest:TokenRequest):Promise<AxiosPromise<string>> => {
+    return request.post('/token', tokenRequest)
+}
+
+
+export default {
+    createToken,  // 导出createToken接口
+};

+ 5 - 0
src/api/types.ts

@@ -0,0 +1,5 @@
+//创建模型
+export type TokenRequest = {
+    username: string,
+    password: string
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/img/avatar.svg


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/img/bg.svg


BIN
src/assets/img/wave.png


+ 13 - 1
src/main.ts

@@ -1,4 +1,16 @@
 import { createApp } from 'vue'
 import App from './App.vue'
+// 引入TDesign
+import TDesign from 'tdesign-vue-next';
+// 引入组件库的少量全局样式变量
+import 'tdesign-vue-next/dist/reset.css';
+import 'tdesign-vue-next/es/style/index.css';
 
-createApp(App).mount('#app')
+// 引入路由
+import router from "@/views/router/Index";
+const app = createApp(App)
+// 挂载根实例
+app.use(router)
+// 挂载根实例
+app.use(TDesign)
+app.mount('#app')

+ 7 - 0
src/views/dashboard/index.vue

@@ -0,0 +1,7 @@
+<template>
+  <div>控制台</div>
+</template>
+
+<script setup lang="ts">
+
+</script>

+ 124 - 0
src/views/login/Index.vue

@@ -0,0 +1,124 @@
+<template>
+  <img class="wave" src="../../assets/img/wave.png" alt=""/>
+  <div class="container">
+    <!--左边的背景图-->
+    <div class="bg">
+      <img src="../../assets/img/bg.svg" alt="">
+    </div>
+    <div class="login-container">
+      <!--引入的卡片区域-->
+      <t-card class="login-cart">
+        <img class="avatar" src="../../assets/img/avatar.svg" alt="">
+        <h2>Vue3-Admin</h2>
+        <!--引入的表单区域-->
+        <t-form ref="form" class="login-from" :data="loginFrom" :rules="rules" :colon="true" :label-width="0">
+          <!--用户区域-->
+          <t-form-item name="username">
+            <t-input clearable v-model="loginFrom.username" placeholder="请输入账户名">
+              <template #prefix-icon>
+                <icon name="user"/>
+              </template>
+            </t-input>
+          </t-form-item>
+          <!--密码区域-->
+          <t-form-item name="password">
+            <t-input type="password" clearable placeholder="请输入密码">
+              <template #prefix-icon>
+                <icon name="lock-on"/>
+              </template>
+            </t-input>
+          </t-form-item>
+          <!--登录按钮-->
+          <t-form-item>
+            <t-button theme="primary" type="submit" block>登录</t-button>
+          </t-form-item>
+        </t-form>
+      </t-card>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import {Icon} from "tdesign-vue-next";
+import {reactive} from "vue";
+import type { TokenRequest } from "@/api/types"
+
+
+// 验证规则,内容区域为空的时候提示
+const rules = {
+  username: [
+    {required: true, message: '请输入账号...'},
+  ],
+  password: [
+    {required: true, message: '请输入密码...'},
+  ]
+}
+
+//创建对象
+const loginFrom = reactive<TokenRequest>({
+  username: '',
+  password: '',
+})
+</script>
+
+<style lang="less" scoped>
+template {
+  overflow: hidden;
+}
+// 左边的背景图的属性
+.wave {
+  position: fixed;
+  height: 100%;
+  left: 0;
+  bottom: 0;
+  z-index: -1;
+}
+// 总体布局属性
+.container {
+  width: 100vw;
+  height: 100vh;
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  grid-gap: 7rem;
+  padding: 0 2rem;
+  // bg 是左边的图片大小属性
+  .bg {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+  }
+  // img 是左边的图片大小属性
+  .bg img {
+    width: 500px;
+  }
+  // login-container 是右边的所有内容的总属性
+  .login-container {
+    display: flex;
+    width: 380px;
+    flex-direction: column;
+    align-items: center;
+    text-align: center;
+    justify-content: center;
+    }
+
+  .login-cart {
+    width: 100%;
+    // 网站名称的属性
+    h2 {
+      font-size: 2.5rem;
+      margin: 25px 0;
+      color: #333;
+    }
+    // 头像的属性
+    .avatar {
+      width: 100px;
+    }
+    // 输入内容 t-from 的属性
+    .login-from {
+      width: 100%;
+      margin-top: 3.6rem;
+      text-align: left;
+    }
+  }
+}
+</style>

+ 27 - 0
src/views/router/index.ts

@@ -0,0 +1,27 @@
+// 引入router的组件
+import type { RouteRecordRaw } from "vue-router";
+// 引入两个组件
+import LoginView from "@/views/login/Index.vue"
+import DashboardView from "@/views/dashboard/Index.vue"
+import {createRouter, createWebHashHistory} from "vue-router";
+
+// 2. 定义一些路由
+// 每个路由都需要映射到一个组件。
+// 我们后面再讨论嵌套路由。
+const routes:Array<RouteRecordRaw> = [
+    { path:'/', name : 'dashboard', component : DashboardView },
+    { path:'/login', name : 'login', component : LoginView }
+]
+
+// 3. 创建路由实例并传递 `routes` 配置
+// 你可以在这里输入更多的配置,但我们在这里
+// 暂时保持简单
+const router = createRouter({
+    // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
+    history: createWebHashHistory(),
+    strict: true,  // 按照严模式匹配
+    routes, // `routes: routes` 的缩写
+    scrollBehavior : () => ({ left:0, top:0 })   //跳转页面之后回到顶部
+})
+
+export default router   // 导出路由

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff