feat: 添加pinia状态管理库和Tabbar组件
- 添加pinia状态管理库和Tabbar组件 - 导入新的组件和模块 - 更新页面布局和样式 - 删除无用的文件和代码
This commit is contained in:
		
							
								
								
									
										6
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -7,9 +7,15 @@ export {} | |||||||
|  |  | ||||||
| declare module 'vue' { | declare module 'vue' { | ||||||
|   export interface GlobalComponents { |   export interface GlobalComponents { | ||||||
|  |     PageWrapper: typeof import('./src/components/page-wrapper.vue')['default'] | ||||||
|     Tabbar: typeof import('./src/components/Tabbar.vue')['default'] |     Tabbar: typeof import('./src/components/Tabbar.vue')['default'] | ||||||
|     WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default'] |     WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default'] | ||||||
|  |     WdCell: typeof import('wot-design-uni/components/wd-cell/wd-cell.vue')['default'] | ||||||
|  |     WdCellGroup: typeof import('wot-design-uni/components/wd-cell-group/wd-cell-group.vue')['default'] | ||||||
|  |     WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.vue')['default'] | ||||||
|  |     WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default'] | ||||||
|     WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default'] |     WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default'] | ||||||
|     WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default'] |     WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default'] | ||||||
|  |     WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default'] | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| import { ref } from 'vue'; | import { ref } from 'vue'; | ||||||
| import { useRouter, useRoute } from 'uni-mini-router' | import { useRouter, useRoute } from 'uni-mini-router' | ||||||
| import { onMounted, computed, watch } from 'vue'; | import { onMounted, computed, watch } from 'vue'; | ||||||
|  | import { useTabbar } from '@/stores/useTabbar'; | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   currentName: { |   currentName: { | ||||||
| @ -10,18 +11,12 @@ const props = defineProps({ | |||||||
|   } |   } | ||||||
| }) | }) | ||||||
|  |  | ||||||
| const route = useRoute() |  | ||||||
| const router = useRouter() | const router = useRouter() | ||||||
|  | const tab = useTabbar() | ||||||
|  |  | ||||||
| const activeTab = ref('home') | // onMounted(() => { | ||||||
|  | //   tab.activeTab = props.currentName | ||||||
| onMounted(() => { | // }) | ||||||
|   activeTab.value = props.currentName |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| watch(activeTab, (val) => { |  | ||||||
|   router.pushTab({ name: val }) |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| const nameLabelIconMap = { | const nameLabelIconMap = { | ||||||
|   home: { |   home: { | ||||||
| @ -49,8 +44,8 @@ const tabList = computed(() => router.routes.map((route: { name: keyof typeof na | |||||||
|  |  | ||||||
| <template> | <template> | ||||||
|   <div> |   <div> | ||||||
|     <wd-tabbar v-model="activeTab" fixed safe-area-inset-bottom bordered placeholder> |     <wd-tabbar v-model="tab.activeTab" fixed safe-area-inset-bottom bordered placeholder> | ||||||
|       <wd-tabbar-item v-for="(tab, i) in tabList" :name="tab.name" :title="tab.title" :icon="tab.icon" :key="i" /> |       <wd-tabbar-item v-for="(tab, i) in tabList" :name="tab.name" :title="tab.title" :icon="tab.icon" :key="i" @tap="router.pushTab({ name: tab.name })" /> | ||||||
|     </wd-tabbar> |     </wd-tabbar> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								src/components/page-wrapper.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/components/page-wrapper.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | <script lang="ts" setup> | ||||||
|  | import TabBar from '@/components/Tabbar.vue'; | ||||||
|  | import { useUser } from '@/stores/useUser'; | ||||||
|  | import { useRouter } from 'uni-mini-router'; | ||||||
|  | import { onMounted } from 'vue'; | ||||||
|  |  | ||||||
|  | const router = useRouter() | ||||||
|  | const user = useUser() | ||||||
|  |  | ||||||
|  | onMounted(() => { | ||||||
|  |   if (!user.userinfo) { | ||||||
|  |     router.replaceAll('/pages/login/index') | ||||||
|  |   } | ||||||
|  | }) | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <slot></slot> | ||||||
|  |     <wd-toast /> | ||||||
|  |     <tab-bar current-name="home" /> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <style scoped> | ||||||
|  |  | ||||||
|  | </style> | ||||||
							
								
								
									
										10
									
								
								src/composables/useConfig.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/composables/useConfig.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | import { defineStore } from "pinia"; | ||||||
|  | import { ref } from "vue"; | ||||||
|  |  | ||||||
|  | export const useConfig = defineStore('config', () => { | ||||||
|  |   const BASE_URL = ref<string>("https://ppmp.fenshenzhike.com/api"); | ||||||
|  |  | ||||||
|  |   return { | ||||||
|  |     BASE_URL | ||||||
|  |   } | ||||||
|  | }) | ||||||
| @ -13,6 +13,13 @@ | |||||||
| 			"style": { | 			"style": { | ||||||
| 				"navigationBarTitleText": "我的" | 				"navigationBarTitleText": "我的" | ||||||
| 			} | 			} | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"name": "login", | ||||||
|  | 			"path": "pages/login/index", | ||||||
|  | 			"style": { | ||||||
|  | 				"navigationBarTitleText": "登录" | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	], | 	], | ||||||
| 	"tabBar": { | 	"tabBar": { | ||||||
|  | |||||||
| @ -1,30 +1,18 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="content"> |   <page-wrapper> | ||||||
|     <img class="logo" src="/static/logo.png" /> |     <div class="content"> | ||||||
|     <div class="flex flex-col items-center gap-4"> |       <img class="logo" src="/static/logo.png" /> | ||||||
|       <p class="title text-red-500"> |       <div class="flex flex-col items-center gap-4"> | ||||||
|         {{ title }} |         <p class="title text-red-500"> | ||||||
|       </p> |           Welcome | ||||||
|       <WdButton @click="onClick">Increment</WdButton> |         </p> | ||||||
|       <Tabbar current-name="home" /> |       </div> | ||||||
|     </div> |     </div> | ||||||
|  |   </page-wrapper> | ||||||
|   </div> |  | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { useUserStore } from '@/stores/user'; | import pageWrapper from '@/components/page-wrapper.vue'; | ||||||
| import { computed } from 'vue'; |  | ||||||
|  |  | ||||||
| import Tabbar from '@/components/Tabbar.vue'; |  | ||||||
|  |  | ||||||
| const user = useUserStore() |  | ||||||
|  |  | ||||||
| const onClick = () => { |  | ||||||
|   user.count++ |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const title = computed(() => `Counter: ${user.count}`) |  | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style> | <style> | ||||||
|  | |||||||
							
								
								
									
										69
									
								
								src/pages/login/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/pages/login/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | |||||||
|  | <script lang="ts" setup> | ||||||
|  | import { useConfig } from '@/composables/useConfig'; | ||||||
|  | import { reactive, ref } from 'vue'; | ||||||
|  | import { useToast } from 'wot-design-uni'; | ||||||
|  |  | ||||||
|  | const toast = useToast() | ||||||
|  | const config = useConfig() | ||||||
|  |  | ||||||
|  | const model = reactive<{ | ||||||
|  |   email: string | ||||||
|  |   password: string | ||||||
|  |   remember: boolean | ||||||
|  | }>({ | ||||||
|  |   email: '', | ||||||
|  |   password: '', | ||||||
|  |   remember: false | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | const form = ref() | ||||||
|  |  | ||||||
|  | const handleSubmit = () => { | ||||||
|  |   form.value.validate() | ||||||
|  |     .then(({ valid, errors }: { valid: boolean; errors: any }) => { | ||||||
|  |       if (valid) { | ||||||
|  |         toast.loading({ | ||||||
|  |           msg: '登录中...' | ||||||
|  |         }) | ||||||
|  |         fetch(`${config.BASE_URL}/login`, { | ||||||
|  |           method: 'POST', | ||||||
|  |           headers: { 'content-type': 'application/x-www-form-urlencoded' }, | ||||||
|  |           body: new URLSearchParams({ email: 'root@cyqsd.cn', password: 'Abc123456', remember: 'false' }) | ||||||
|  |         }) | ||||||
|  |           .then(res => res.json()) | ||||||
|  |           .then(res => { | ||||||
|  |             toast.info({ | ||||||
|  |               msg: res.token | ||||||
|  |             }) | ||||||
|  |           }) | ||||||
|  |           .catch(err => { | ||||||
|  |             toast.error({ | ||||||
|  |               msg: err || '登录失败,未知错误' | ||||||
|  |             }) | ||||||
|  |           }) | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |     .catch((error: any) => { | ||||||
|  |       console.log(error, 'error') | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <wd-form ref="form" class="p-4" :model="model"> | ||||||
|  |       <wd-cell-group border> | ||||||
|  |         <wd-input label="邮箱" label-width="100px" prop="email" clearable v-model="model.email" placeholder="请输入邮箱" | ||||||
|  |           :rules="[{ required: true, message: '请填写邮箱' }]" /> | ||||||
|  |         <wd-input label="密码" label-width="100px" prop="password" show-password clearable v-model="model.password" | ||||||
|  |           placeholder="请输入密码" :rules="[{ required: true, message: '请填写密码' }]" /> | ||||||
|  |       </wd-cell-group> | ||||||
|  |       <view class="p-4"> | ||||||
|  |         <wd-button type="primary" size="large" @click="handleSubmit" block>登录</wd-button> | ||||||
|  |       </view> | ||||||
|  |     </wd-form> | ||||||
|  |     <wd-toast /> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <style scoped></style> | ||||||
| @ -1,12 +1,21 @@ | |||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import Tabbar from '@/components/Tabbar.vue'; | import pageWrapper from '@/components/page-wrapper.vue'; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
|   <div> |   <page-wrapper> | ||||||
|     <h1>我的页面</h1> |     <div class="p-4 flex flex-col gap-4"> | ||||||
|     <Tabbar current-name="my" /> |       <WdCellGroup :border="true"> | ||||||
|   </div> |         <WdCell title="用户名" value="test1" /> | ||||||
|  |         <WdCell title="单位" value="重庆眩生花科技有限公司" /> | ||||||
|  |         <WdCell title="角色" value="普通管理员" /> | ||||||
|  |         <WdCell title="手机" value="15023333333" /> | ||||||
|  |       </WdCellGroup> | ||||||
|  |       <div class="px-4"> | ||||||
|  |         <wd-button plain hairline type="error">退出账号</wd-button> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </page-wrapper> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <style scoped> | <style scoped> | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 200 KiB | 
							
								
								
									
										10
									
								
								src/stores/useTabbar.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/stores/useTabbar.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | import { defineStore } from "pinia"; | ||||||
|  | import { ref } from "vue"; | ||||||
|  |  | ||||||
|  | export const useTabbar = defineStore('tabbar', () => { | ||||||
|  |   const activeTab = ref('home') | ||||||
|  |  | ||||||
|  |   return { | ||||||
|  |     activeTab | ||||||
|  |   } | ||||||
|  | }) | ||||||
							
								
								
									
										11
									
								
								src/stores/useUser.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/stores/useUser.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | import type { User } from "@/types/api/user"; | ||||||
|  | import { defineStore } from "pinia"; | ||||||
|  | import { ref } from "vue"; | ||||||
|  |  | ||||||
|  | export const useUser = defineStore("user", () => { | ||||||
|  |   const userinfo = ref<User | null>(null); | ||||||
|  |  | ||||||
|  |   return { | ||||||
|  |     userinfo, | ||||||
|  |   }; | ||||||
|  | }); | ||||||
| @ -1,10 +0,0 @@ | |||||||
| import { defineStore } from "pinia"; |  | ||||||
| import { ref } from "vue"; |  | ||||||
|  |  | ||||||
| export const useUserStore = defineStore("user", () => { |  | ||||||
|   const count = ref(0); |  | ||||||
|  |  | ||||||
|   return { |  | ||||||
|     count, |  | ||||||
|   }; |  | ||||||
| }); |  | ||||||
							
								
								
									
										2
									
								
								src/type.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/type.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | //type.d.ts | ||||||
|  | declare const ROUTES: []; | ||||||
							
								
								
									
										43
									
								
								src/types/api/user.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/types/api/user.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | export interface User { | ||||||
|  |   id: number; | ||||||
|  |   username: string; | ||||||
|  |   email: string; | ||||||
|  |   avatar: string; | ||||||
|  |   department_id: null; | ||||||
|  |   creator_id: number; | ||||||
|  |   status: number; | ||||||
|  |   login_ip: string; | ||||||
|  |   login_at: number; | ||||||
|  |   created_at: string; | ||||||
|  |   updated_at: string; | ||||||
|  |   deleted_at: Date; | ||||||
|  |   permissions: Permission[]; | ||||||
|  |   roles: any[]; | ||||||
|  |   jobs: any[]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface Permission { | ||||||
|  |   id: number; | ||||||
|  |   parent_id: number; | ||||||
|  |   permission_name: string; | ||||||
|  |   route: string; | ||||||
|  |   icon: string; | ||||||
|  |   module: PermissionModule; | ||||||
|  |   permission_mark: string; | ||||||
|  |   component: string; | ||||||
|  |   redirect: null | string; | ||||||
|  |   keepalive: number; | ||||||
|  |   type: number; | ||||||
|  |   hidden: boolean; | ||||||
|  |   sort: number; | ||||||
|  |   active_menu: string; | ||||||
|  |   creator_id: number; | ||||||
|  |   created_at: string; | ||||||
|  |   updated_at: string; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export enum PermissionModule { | ||||||
|  |   Lesson = "lesson", | ||||||
|  |   Permissions = "permissions", | ||||||
|  |   User = "user", | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user