Browse Source

wip: 登录接口调试

王家程 11 months ago
parent
commit
15cbdcdc29

+ 1 - 0
.eslintrc

@@ -59,5 +59,6 @@
     "@typescript-eslint/no-unused-vars": [0],
     "@typescript-eslint/no-var-requires": [0],
     "import/no-unresolved": "off",
+    "no-unused-vars": "off"
   },
 }

+ 1 - 0
package.json

@@ -33,6 +33,7 @@
     "dayjs": "^1.11.11",
     "pinia": "^2.1.7",
     "pinia-plugin-persistedstate": "^3.2.1",
+    "qs": "^6.12.1",
     "unocss": "^0.58.3",
     "uview-plus": "^3.2.22",
     "vue": "^3.4.27",

+ 11 - 0
pnpm-lock.yaml

@@ -41,6 +41,9 @@ importers:
       pinia-plugin-persistedstate:
         specifier: ^3.2.1
         version: 3.2.1(pinia@2.1.7(typescript@5.4.5)(vue@3.4.27(typescript@5.4.5)))
+      qs:
+        specifier: ^6.12.1
+        version: 6.12.1
       unocss:
         specifier: ^0.58.3
         version: 0.58.9(postcss@8.4.38)(rollup@4.18.0)(vite@5.2.12(@types/node@20.14.2)(sass@1.77.4)(terser@5.31.0))
@@ -4296,6 +4299,10 @@ packages:
     resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
     engines: {node: '>=0.6'}
 
+  qs@6.12.1:
+    resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==}
+    engines: {node: '>=0.6'}
+
   query-string@4.3.4:
     resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==}
     engines: {node: '>=0.10.0'}
@@ -10511,6 +10518,10 @@ snapshots:
     dependencies:
       side-channel: 1.0.6
 
+  qs@6.12.1:
+    dependencies:
+      side-channel: 1.0.6
+
   query-string@4.3.4:
     dependencies:
       object-assign: 4.1.1

+ 31 - 0
src/api/userApi.ts

@@ -0,0 +1,31 @@
+/*
+ * @Author: wjc
+ * @Date: 2024-06-12 10:05:12
+ * @LastEditors: wjc
+ * @LastEditTime: 2024-06-12 17:24:33
+ * @Description:
+ */
+import { request } from '@/utils/request'
+import { BasicRes } from '@/models/requestTypes'
+import { ILogin, LoginRes, Employees } from '@/models/userTypes'
+
+export function login(data: ILogin) {
+  return request<BasicRes<LoginRes>>({
+    url: 'auth/login',
+    method: 'POST',
+    header: {
+      entcode: data.entCode,
+    },
+    data: {
+      account: data.account,
+      password: data.password,
+    },
+  })
+}
+
+export function getUserInfo(data: string) {
+  return request<BasicRes<Employees>>({
+    url: `auth/employees/${data}`,
+    method: 'GET',
+  })
+}

+ 3 - 1
src/main.ts

@@ -2,7 +2,7 @@
  * @Author: wjc
  * @Date: 2024-05-27 11:49:45
  * @LastEditors: wjc
- * @LastEditTime: 2024-06-11 10:21:38
+ * @LastEditTime: 2024-06-12 11:20:09
  * @Description:
  */
 import { createSSRApp } from 'vue'
@@ -10,6 +10,7 @@ import * as Pinia from 'pinia'
 import uviewPlus from 'uview-plus'
 import 'virtual:uno.css'
 import { setupStores } from '@/stores'
+import { setupInterceptor } from '@/utils/request'
 import '@/static/styles/vars.scss'
 import '@/static/styles/index.scss'
 
@@ -20,6 +21,7 @@ export function createApp() {
 
   app.use(uviewPlus)
   setupStores(app)
+  setupInterceptor(app)
 
   return {
     app,

+ 14 - 0
src/models/requestTypes.ts

@@ -0,0 +1,14 @@
+/*
+ * @Author: wjc
+ * @Date: 2024-06-12 11:46:30
+ * @LastEditors: wjc
+ * @LastEditTime: 2024-06-12 14:24:32
+ * @Description:
+ */
+export type BasicRes<T = unknown> = {
+  data: T
+  code: string
+  msg: string
+  status: number
+  statusText: string
+}

+ 137 - 1
src/models/userTypes.ts

@@ -2,9 +2,145 @@
  * @Author: wjc
  * @Date: 2024-06-05 17:14:01
  * @LastEditors: wjc
- * @LastEditTime: 2024-06-05 17:14:47
+ * @LastEditTime: 2024-06-12 17:08:38
  * @Description:
  */
 export interface UserState {
+  isDialogShowed: boolean
   isInstall: boolean
+  token: string
+  userInfo: Employees
+}
+
+export interface ILogin {
+  account: string
+  password: string
+  entCode: string
+}
+
+export interface LoginData {
+  id: string
+  account: string
+  entCode: string
+  entName: string
+  name: string
+  imgUrl: string
+  positionName: string
+}
+
+export class LoginRes implements LoginData {
+  id: string
+  account: string
+  entCode: string
+  entName: string
+  name: string
+  imgUrl: string
+  positionName: string
+
+  constructor(json: LoginData) {
+    this.id = json.id
+    this.account = json.account
+    this.entCode = json.entCode
+    this.entName = json.entName
+    this.imgUrl = json.imgUrl
+    this.positionName = json.positionName
+  }
+}
+
+export interface Roles {
+  roleId: string
+  roleName: string
+}
+
+export interface IEmployees {
+  id?: string
+  companyId?: string
+  companyName?: string
+  organId?: string
+  organName?: string
+  positionId?: string
+  positionName?: string
+  name?: string
+  sex?: string
+  birthday?: string
+  phone?: string
+  account?: string
+  password?: string
+  identityCard?: string
+  employeeNumber?: string
+  imgUrl?: string
+  onJob?: string
+  onJobDesc?: string
+  hireDate?: string
+  leaveDate?: any
+  loginPermit?: number
+  remark?: any
+  loginCount?: any
+  loginTime?: any
+  wechatBind?: any
+  roles?: Roles[]
+  open?: any
+  cardQrCode?: any
+}
+
+export class Employees implements IEmployees {
+  id?: string
+  companyId?: string
+  companyName?: string
+  organId?: string
+  organName?: string
+  positionId?: string
+  positionName?: string
+  name?: string
+  sex?: string
+  birthday?: string
+  phone?: string
+  account?: string
+  password?: string
+  identityCard?: string
+  employeeNumber?: string
+  imgUrl?: string
+  onJob?: string
+  onJobDesc?: string
+  hireDate?: string
+  leaveDate?: any
+  loginPermit?: number
+  remark?: any
+  loginCount?: any
+  loginTime?: any
+  wechatBind?: any
+  roles?: Roles[]
+  open?: any
+  cardQrCode?: any
+
+  constructor(data: Partial<IEmployees> = {}) {
+    this.id = data.id
+    this.companyId = data.companyId
+    this.companyName = data.companyName
+    this.organId = data.organId
+    this.organName = data.organName
+    this.positionId = data.positionId
+    this.positionName = data.positionName
+    this.name = data.name
+    this.sex = data.sex
+    this.birthday = data.birthday
+    this.phone = data.phone
+    this.account = data.account
+    this.password = data.password
+    this.identityCard = data.identityCard
+    this.employeeNumber = data.employeeNumber
+    this.imgUrl = data.imgUrl
+    this.onJob = data.onJob
+    this.onJobDesc = data.onJobDesc
+    this.hireDate = data.hireDate
+    this.leaveDate = data.leaveDate
+    this.loginPermit = data.loginPermit
+    this.remark = data.remark
+    this.loginCount = data.loginCount
+    this.loginTime = data.loginTime
+    this.wechatBind = data.wechatBind
+    this.roles = data.roles
+    this.open = data.open
+    this.cardQrCode = data.cardQrCode
+  }
 }

+ 8 - 5
src/pages/login/components/privacy.vue

@@ -2,11 +2,11 @@
  * @Author: wjc
  * @Date: 2024-06-06 16:27:16
  * @LastEditors: wjc
- * @LastEditTime: 2024-06-11 17:39:16
+ * @LastEditTime: 2024-06-12 09:47:01
  * @Description: 
 -->
 <template>
-  <up-modal :show="show" class="" :z-index="99">
+  <up-modal :show="show" class="" :z-index="0">
     <view class="relative w-full h-450px">
       <view class="text-16px font-600 text-center mb-30px">绘管家个人信息保护政策</view>
       <web-view
@@ -26,15 +26,18 @@
 <script setup lang="ts">
   defineOptions({ name: 'PrivacyModal' })
 
+  const emit = defineEmits<{
+    (e: 'privacy', data: boolean): void
+  }>()
   const show = ref(true)
 
   const onNotAgree = () => {
+    emit('privacy', false)
     show.value = false
   }
   const onAgree = () => {
-    uni.navigateTo({
-      url: '/pages/privacy/index',
-    })
+    emit('privacy', true)
+    show.value = false
   }
 
   onMounted(() => {})

+ 41 - 14
src/pages/login/index.vue

@@ -2,7 +2,7 @@
  * @Author: wjc
  * @Date: 2024-06-06 14:51:25
  * @LastEditors: wjc
- * @LastEditTime: 2024-06-11 17:33:05
+ * @LastEditTime: 2024-06-12 17:22:09
  * @Description: 
 -->
 <template>
@@ -30,13 +30,14 @@
         </up-form-item>
       </up-form>
       <view class="flex items-center color-gray text-14px mt-24px mb-24px">
-        <up-checkbox
-          shape="circle"
-          name="isCheck"
-          :checked="formState.isCheck"
-          label="我已阅读同意"
-          :label-size="14"
-        ></up-checkbox>
+        <up-checkbox-group v-model="isChecks">
+          <up-checkbox
+            shape="circle"
+            name="isCheck"
+            label="我已阅读同意"
+            :label-size="14"
+          ></up-checkbox>
+        </up-checkbox-group>
         <text class="font-500 color-black" @click="goPrivacy">《绘管家个人信息保护政策》</text>
       </view>
       <up-button type="primary" class="btn-primary" @click="onSubmit">登录</up-button>
@@ -46,23 +47,25 @@
       <view>2016-{{ new Date().getFullYear() }} Ⓒ 海南智慧城科技有限公司</view>
       <view>琼ICP备18001846号-4A</view>
     </view>
-    <PrivacyModal></PrivacyModal>
+    <PrivacyModal @privacy="handlePrivacy"></PrivacyModal>
   </view>
 </template>
 
 <script setup lang="ts">
+  import { useUserStore } from '@/stores/modules/userStore'
   import logo from '@/static/images/logo.png'
   import PrivacyModal from './components/privacy.vue'
 
   defineOptions({ name: 'Login' })
 
+  const userStore = useUserStore()
   const formRef = ref(null)
   const formState = ref({
     entCode: '',
-    account: '',
+    account: '18889757900',
     password: undefined,
-    isCheck: false,
   })
+  const isChecks = ref([])
   const rules = ref({
     entCode: {
       type: 'number',
@@ -77,7 +80,7 @@
       trigger: ['blur', 'change'],
     },
     password: {
-      type: 'number',
+      type: 'string',
       required: true,
       message: '请输入密码',
       trigger: ['blur', 'change'],
@@ -87,23 +90,47 @@
   const goPrivacy = () => {
     uni.navigateTo({ url: '/pages/privacy/index' })
   }
+
   const onSubmit = () => {
     formRef.value
       .validate()
       .then((valid) => {
         if (valid) {
-          console.log(124)
+          if (isChecks.value.length === 0) {
+            uni.showToast({
+              icon: 'none',
+              title: '请先阅读并勾选绘管家个人信息保护政策',
+            })
+          } else {
+            userStore.loginAction(formState.value).then((res) => {
+              if (res) {
+                userStore.getUserInfoAction().then((res) => {
+                  if (res) {
+                    uni.reLaunch({
+                      url: '/pages/index/index',
+                    })
+                  }
+                })
+              }
+            })
+          }
         }
       })
       .catch(() => {
         // 处理验证错误
       })
   }
+
+  const handlePrivacy = (data: boolean) => {
+    if (data) {
+      isChecks.value = ['isCheck']
+    }
+  }
 </script>
 
 <style scoped lang="scss">
   .login-container {
-    @apply h-full p-24px;
+    @apply wh-full p-24px box-border;
     background: url('@/static/images/login/bg.png') no-repeat;
     background-size: contain;
     .header {

+ 2 - 2
src/static/styles/comm.scss

@@ -1,7 +1,7 @@
 .btn-default {
-  @apply rounded-20px text-16px p-12px bg-bg-page;
+  @apply rounded-20px\! text-16px p-12px bg-bg-page;
 }
 
 .btn-primary {
-  @apply rounded-20px text-16px p-12px bg-bg-primary color-white;
+  @apply rounded-20px\! text-16px p-12px bg-bg-primary\! color-white;
 }

+ 43 - 4
src/stores/modules/userStore.ts

@@ -2,18 +2,57 @@
  * @Author: wjc
  * @Date: 2024-06-05 17:13:30
  * @LastEditors: wjc
- * @LastEditTime: 2024-06-06 15:23:42
+ * @LastEditTime: 2024-06-12 17:08:53
  * @Description:
  */
 import { defineStore } from 'pinia'
 
-import type { UserState } from '@/models/userTypes'
+import { UserState, ILogin, LoginRes, Employees } from '@/models/userTypes'
+import { login, getUserInfo } from '@/api/userApi'
 
 export const useUserStore = defineStore('user', {
   state: (): UserState => {
     return {
-      isInstall: true,
+      isDialogShowed: false,
+      isInstall: false,
+      token: '',
+      userInfo: new Employees({}),
     }
   },
-  actions: {},
+  actions: {
+    loginAction(data: ILogin): Promise<LoginRes> {
+      return new Promise((resolve, reject) => {
+        login(data)
+          .then((res) => {
+            if (res && res.data) {
+              this.isDialogShowed = true
+              this.isInstall = true
+              uni.setStorageSync('storage-loginInfo', data)
+              uni.setStorageSync('storage-user-id', res.data.id)
+              resolve(res.data)
+            }
+          })
+          .catch((error) => {
+            reject(error)
+          })
+      })
+    },
+    getUserInfoAction(): Promise<Employees> {
+      return new Promise((resolve, reject) => {
+        const id = uni.getStorageSync('storage-user-id')
+        if (id) {
+          getUserInfo(id)
+            .then((res) => {
+              if (res && res.data) {
+                this.userInfo = res.data
+                resolve(res.data)
+              }
+            })
+            .catch((error) => {
+              reject(error)
+            })
+        }
+      })
+    },
+  },
 })

+ 7 - 7
src/utils/request/checkStatus.ts

@@ -2,15 +2,15 @@
  * @Author: wjc
  * @Date: 2024-06-05 10:36:43
  * @LastEditors: wjc
- * @LastEditTime: 2024-06-05 17:48:00
+ * @LastEditTime: 2024-06-12 16:08:43
  * @Description:
  */
-export function checkStatus(status: number, msg?: string) {
-  let errMessage = ''
+export function checkStatus(err: any) {
+  let errMessage = err.data.responseJSON.message
 
-  switch (status) {
+  switch (err.statusCode) {
     case 400:
-      errMessage = `${msg}`
+      errMessage = `${errMessage}`
       break
     case 401:
       errMessage = '登录超时,请重新登录'
@@ -28,12 +28,12 @@ export function checkStatus(status: number, msg?: string) {
       errMessage = '服务不可用,请稍候再试'
       break
     default:
-      errMessage = `${msg}`
+      errMessage = `${errMessage}`
   }
 
   if (errMessage) {
     uni.showToast({
-      icon: 'error',
+      icon: 'none',
       title: errMessage,
     })
     return false

+ 55 - 13
src/utils/request/index.ts

@@ -2,32 +2,74 @@
  * @Author: wjc
  * @Date: 2024-06-05 10:21:23
  * @LastEditors: wjc
- * @LastEditTime: 2024-06-05 17:46:23
+ * @LastEditTime: 2024-06-12 16:24:04
  * @Description:
  */
+import type { App } from 'vue'
+import qs from 'qs'
+import type { ILogin } from '@/models/userTypes'
+import { useUserStore } from '@/stores/modules/userStore'
 import { checkStatus } from './checkStatus'
 
-export type RequestOptions = UniApp.RequestOptions
+export type IRequestOptions = UniApp.RequestOptions & {
+  query?: Record<string, any>
+}
+
+const interceptor = {
+  //  请求前拦截
+  invoke(options: IRequestOptions) {
+    // api 处理
+    options.url = `${import.meta.env.VITE_APP_BASE_API}${options.url}`
+    // 查询参数处理
+    if (options.query) {
+      const query = qs.stringify(Object.assign({}, options.query), {
+        addQueryPrefix: true,
+      })
+      options.url += query
+    }
+    // 10 秒请求超时
+    options.timeout = 100000
+    // 请求头标识符
+    const sysInfo = uni.getSystemInfoSync()
+    const storageLoginInfo: ILogin = uni.getStorageSync('storage-loginInfo')
+    options.header = {
+      ...options.header,
+      version: sysInfo.appVersion, // 版本号
+      platform: sysInfo.osName ?? 'app', // 所用系统
+    }
+    // entCode
+    if (storageLoginInfo && storageLoginInfo.entCode) {
+      options.header.entcode = storageLoginInfo.entCode
+    }
+    // token
+    const userStore = useUserStore()
+    if (userStore.token) {
+      options.header.Authorization = `Bearer ${userStore.token}`
+    }
+  },
+}
+
+export function setupInterceptor(app: App) {
+  app.use({
+    install() {
+      uni.addInterceptor('request', interceptor)
+    },
+  })
+}
 
-export const request = <T>(options: RequestOptions) => {
+export const request = <T>(options: IRequestOptions) => {
   return new Promise<T>((resolve, reject) => {
     uni.request({
       responseType: 'json',
       ...options,
       success(res) {
-        if (checkStatus(res.statusCode)) {
-          reject(res)
-        } else {
+        if (res.statusCode === 200 || res.statusCode === 201) {
           resolve(res.data as T)
+        } else {
+          checkStatus(res)
+          reject(res)
         }
       },
-      fail(err) {
-        uni.showToast({
-          icon: 'none',
-          title: 'error',
-        })
-        reject(err)
-      },
     })
   })
 }

+ 1 - 1
tsconfig.json

@@ -10,7 +10,7 @@
     "allowJs": true,
     "sourceMap": true,
     "baseUrl": ".",
-    "types": ["@dcloudio/types"],
+    "types": ["@dcloudio/types", "vite/client"],
     "paths": {
       "@/*": ["./src/*"],
       "#/*": ["./types/*"],