浏览代码

update: 登录接口对接

xyh 2 年之前
父节点
当前提交
8794eadcf9

+ 2 - 0
src/apis/index.js

@@ -0,0 +1,2 @@
+export * from './user';
+export * from './client';

+ 10 - 4
src/apis/request.js

@@ -3,7 +3,7 @@ import {
   showToast,
   uploadFile as miniUpload,
 } from '@tarojs/taro';
-import {NETWORK_URL} from 'utils/constants';
+import {NETWORK_URL} from '@utils';
 
 function request({url, data, method, skipError}) {
   const pr = new Promise(function (res) {
@@ -16,18 +16,24 @@ function request({url, data, method, skipError}) {
         'Cache-Control': 'no-cache',
       },
       success(data) {
-        const result = data.data;
-        if (result.code === '500' && !skipError)
+        let result = data.data;
+        if (!result.code) {
+          result = {code: '500', msg: '请求失败,请稍后再试'};
+        }
+
+        if (result.code === '500' && !skipError) {
           showToast({
             title: result.msg,
             duration: 2000,
             mask: false,
             icon: 'none',
           });
+        }
 
         res(result);
       },
-      fail() {
+      fail(err) {
+        if (err.errMsg === 'request:fail abort') return;
         !skipError &&
           showToast({
             title: '请求失败,请稍后再试',

+ 10 - 0
src/apis/user.js

@@ -0,0 +1,10 @@
+import {post} from './request';
+
+/**
+ * 用户登录
+ *
+ * data: userName password
+ */
+export function login(data) {
+  return post({url: '/user/login', data});
+}

+ 81 - 0
src/hooks/use-navigate/index.js

@@ -0,0 +1,81 @@
+import {useCallback, useMemo} from 'react';
+import {trim} from 'lodash-es';
+import {
+  reLaunch,
+  navigateBack,
+  navigateTo,
+  redirectTo,
+  switchTab,
+  showToast,
+} from '@tarojs/taro';
+import {useStore} from 'zustand';
+import {userStore} from '@stores';
+
+export function useNavigate() {
+  const formatParams = useCallback(function (name, params) {
+    if (!params) return name;
+
+    let result = name + '?';
+
+    for (const key in params) {
+      result += `${key}=${params[key].toString()}&`;
+    }
+
+    return trim(result, '&');
+  }, []);
+
+  const token = useStore(userStore, state => state.token);
+
+  const actions = useMemo(() => {
+    function push(name, params) {
+      navigateTo({url: formatParams(name, params)});
+    }
+
+    function pop(dep = 1) {
+      navigateBack({delta: dep});
+    }
+
+    function redirect(name, params) {
+      redirectTo({url: formatParams(name, params)});
+    }
+
+    function redirectToTab(name) {
+      switchTab({url: name});
+    }
+
+    function launchTo(url) {
+      reLaunch({url});
+    }
+
+    function navigate(name, params) {
+      if (typeof name === 'string') {
+        push(name, params);
+        return;
+      }
+      if (name <= 0) {
+        throw new Error('delat回退数量必须大于0');
+      }
+
+      pop(name);
+    }
+
+    function navigateWithLogin(name, params) {
+      if (!token) {
+        return showToast({title: '请登录', mask: true, icon: 'error'});
+      }
+      push(name, params);
+    }
+
+    return {
+      push,
+      pop,
+      redirect,
+      redirectToTab,
+      launchTo,
+      navigate,
+      navigateWithLogin,
+    };
+  }, [formatParams, token]);
+
+  return actions;
+}

+ 25 - 5
src/pages/index/index.jsx

@@ -1,4 +1,4 @@
-import {View, Image, Text, Navigator} from '@tarojs/components';
+import {View, Image, Text} from '@tarojs/components';
 import classNames from 'classnames';
 import sendIcon from '@assets/sending.svg';
 import complateIcon from '@assets/complate.svg';
@@ -7,6 +7,9 @@ import face from '@assets/face.svg';
 import Login from './login';
 import {useBoolean} from 'ahooks';
 import {DELIVER_GOODS_PATH, ORDER_PATH, RECEIVE_GOODS_PATH} from '@routes';
+import {useNavigate} from '@hooks';
+import {useStore} from 'zustand';
+import {userStore} from '@stores';
 
 const btnList = [
   {
@@ -24,6 +27,15 @@ const btnList = [
 
 export default function App() {
   const [visible, {toggle, setFalse}] = useBoolean();
+  const {navigateWithLogin, navigate} = useNavigate();
+
+  function navigateTo(name, needLogin) {
+    return function () {
+      needLogin ? navigateWithLogin(name) : navigate(name);
+    };
+  }
+
+  const userName = useStore(userStore, state => state.userName);
 
   return (
     <>
@@ -33,7 +45,10 @@ export default function App() {
           'bg-gradient-to-br from-[#DEF6FE] to-[#F4F6F8]',
         )}
       >
-        <View className='flex items-center' onClick={toggle}>
+        <View
+          className='flex items-center'
+          onClick={userName ? void 0 : toggle}
+        >
           <Image
             className='w-14 h-14 rounded-full'
             src={face}
@@ -41,7 +56,9 @@ export default function App() {
           />
 
           <View className='flex-1 ps-4'>
-            <Text className='block text-base text-[#333]'>登录</Text>
+            <Text className='block text-base text-[#333]'>
+              {userName ? userName : '登录'}
+            </Text>
           </View>
         </View>
 
@@ -61,7 +78,10 @@ export default function App() {
               <View className='mt-3 grid grid-cols-4 grid-rows-1 gap-4'>
                 {el.children.map(function (item) {
                   return (
-                    <Navigator url={item.url} key={item.title}>
+                    <View
+                      onClick={navigateTo(item.url, item.url === ORDER_PATH)}
+                      key={item.title}
+                    >
                       <Image
                         src={item.icon}
                         className='w-8 h-8 mx-auto'
@@ -70,7 +90,7 @@ export default function App() {
                       <Text className='block text-center text-sm mt-2 text-[#666]'>
                         {item.title}
                       </Text>
-                    </Navigator>
+                    </View>
                   );
                 })}
               </View>

+ 7 - 1
src/pages/index/login/field/index.jsx

@@ -1,6 +1,10 @@
 import {Input, Text, View} from '@tarojs/components';
 
-export default function Field({label, password}) {
+export default function Field({label, password, value, onChange}) {
+  function onInputChnage(e) {
+    onChange(e.detail.value);
+  }
+
   return (
     <View className='mt-3 first:mt-0'>
       <Text className='block text-lg font-semibold'>{label}</Text>
@@ -8,6 +12,8 @@ export default function Field({label, password}) {
         placeholder={`请输入${label}`}
         className='mt-1 border-0 border-b border-solid border-gray-200 py-2'
         password={password}
+        value={value}
+        onChange={onInputChnage}
       />
     </View>
   );

+ 58 - 0
src/pages/index/login/hooks.js

@@ -0,0 +1,58 @@
+import {login} from '@apis';
+import {useMutation} from '@tanstack/react-query';
+import {useEffect, useState} from 'react';
+import {showToast, setStorageSync} from '@tarojs/taro';
+import {USER_TOKEN_STORAGE} from '@utils';
+import {useStore} from 'zustand';
+import {userStore} from '@stores';
+
+export function useFields(visible) {
+  const [files, setFields] = useState({userName: '', password: ''});
+
+  function onChange(key) {
+    return function (val) {
+      setFields(prev => ({...prev, [key]: val}));
+    };
+  }
+
+  useEffect(
+    function () {
+      visible && setFields({userName: '', password: ''});
+    },
+    [visible],
+  );
+
+  return [files, onChange];
+}
+
+export function useLogin(userName, password, {onClose}) {
+  const setUser = useStore(userStore, state => state.init);
+  const {isLoading, mutate} = useMutation({
+    mutationFn: login,
+    onSuccess(data) {
+      if (data.code === '200') {
+        const userData = {
+          token: data.data.token,
+          userName: data.data.userName,
+        };
+
+        onClose();
+        showToast({title: '登录成功', icon: 'success'});
+        setStorageSync(USER_TOKEN_STORAGE, userData);
+        setUser(userData);
+      }
+    },
+  });
+
+  function onClick() {
+    if (!userName) {
+      return showToast({title: '请输入用户名', mask: true, icon: 'error'});
+    }
+    if (!password) {
+      return showToast({title: '请输入密码', mask: true, icon: 'error'});
+    }
+    mutate({userName, password});
+  }
+
+  return [isLoading, onClick];
+}

+ 18 - 2
src/pages/index/login/index.jsx

@@ -1,8 +1,12 @@
 import {Popup, Button} from '@antmjs/vantui';
 import {View} from '@tarojs/components';
 import Field from './field';
+import {useFields, useLogin} from './hooks';
 
 export default function Login({visible, onClose}) {
+  const [{userName, password}, onChange] = useFields(visible);
+  const [isLoading, onClick] = useLogin(userName, password, {onClose});
+
   return (
     <Popup
       show={visible}
@@ -14,15 +18,27 @@ export default function Login({visible, onClose}) {
       style={{height: '60vh'}}
     >
       <View className='pt-9 pb-5 flex flex-col h-full'>
-        <Field label='用户名' />
-        <Field label='密码' password />
+        <Field
+          label='用户名'
+          value={userName}
+          onChange={onChange('userName')}
+        />
+        <Field
+          label='密码'
+          password
+          value={password}
+          onChange={onChange('password')}
+        />
 
         <View className='mt-auto'>
           <Button
+            loading={isLoading}
+            disabled={isLoading}
             className='py-4 !border-none !text-base !h-12 '
             block
             color='#58C6EA'
             round
+            onClick={onClick}
           >
             登录
           </Button>

+ 1 - 0
src/stores/index.js

@@ -0,0 +1 @@
+export * from './user';

+ 21 - 0
src/stores/user.js

@@ -0,0 +1,21 @@
+import {getStorageSync} from '@tarojs/taro';
+import {USER_TOKEN_STORAGE} from '@utils';
+import {createStore} from 'zustand';
+
+export const userStore = createStore(function (set) {
+  const storage = getStorageSync(USER_TOKEN_STORAGE);
+  let token = '',
+    userName = '';
+
+  if (storage) {
+    ({token, userName} = storage);
+  }
+
+  return {
+    token,
+    userName,
+    init(data) {
+      set(data, true);
+    },
+  };
+});

+ 4 - 1
src/utils/constants.js

@@ -1 +1,4 @@
-export const NETWORK_URL = '';
+/** 请求地址 */
+export const NETWORK_URL = 'https://3f0974b6.r8.vip.cpolar.cn';
+/** token存储 */
+export const USER_TOKEN_STORAGE = 'userToken';

+ 1 - 0
src/utils/index.js

@@ -1 +1,2 @@
 export * from './resolving';
+export * from './constants';