登录权限管理

main
king 1 year ago
parent ca0562a0a1
commit c30851cdac
  1. 2
      .env
  2. 1
      .env.playedu
  3. 35
      .idea/deployment.xml
  4. 14
      .idea/webServers.xml
  5. 2
      package.json
  6. 39
      src/api/request.ts
  7. 2
      src/app.config.ts
  8. 12
      src/app.tsx
  9. 4
      src/components/showModel/showModel.module.scss
  10. 8
      src/pages/check/check.tsx
  11. 21
      src/pages/index/components/videoList.tsx
  12. 22
      src/pages/index/index.tsx
  13. 21
      src/pages/login/login.tsx
  14. 50
      src/store/profile.ts

@ -1,2 +1,2 @@
TARO_APP_API=https://yjx.dev.yaojiankang.top TARO_APP_API=https://yjx.dev.yaojiankang.top
#TARO_APP_API=https://playedu.yaojiankang.top TARO_APP_LGOIN=true

@ -0,0 +1 @@
TARO_APP_API=https://playedu.yaojiankang.top

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" autoUpload="Always" serverName="81.69.44.74" confirmBeforeUploading="false">
<option name="confirmBeforeUploading" value="false" />
<serverData>
<paths name="81.69.44.74">
<serverdata>
<mappings>
<mapping deploy="/" local="$PROJECT_DIR$" web="/dist" />
</mappings>
<excludedPaths>
<excludedPath local="true" path="$PROJECT_DIR$/.idea" />
<excludedPath local="true" path="$PROJECT_DIR$/.swc" />
<excludedPath local="true" path="$PROJECT_DIR$/config" />
<excludedPath local="true" path="$PROJECT_DIR$/node_modules" />
<excludedPath local="true" path="$PROJECT_DIR$/src" />
<excludedPath local="true" path="$PROJECT_DIR$/types" />
<excludedPath local="true" path="$PROJECT_DIR$/.editorconfig" />
<excludedPath local="true" path="$PROJECT_DIR$/.env" />
<excludedPath local="true" path="$PROJECT_DIR$/.env.playedu" />
<excludedPath local="true" path="$PROJECT_DIR$/.gitignore" />
<excludedPath local="true" path="$PROJECT_DIR$/babel.config.js" />
<excludedPath local="true" path="$PROJECT_DIR$/package.json" />
<excludedPath local="true" path="$PROJECT_DIR$/pnpm-lock.yaml" />
<excludedPath local="true" path="$PROJECT_DIR$/project.config.json" />
<excludedPath local="true" path="$PROJECT_DIR$/project.tt.json" />
<excludedPath local="true" path="$PROJECT_DIR$/tailwind.config.js" />
<excludedPath local="true" path="$PROJECT_DIR$/tsconfig.json" />
</excludedPaths>
</serverdata>
</paths>
</serverData>
<option name="myAutoUpload" value="ALWAYS" />
</component>
</project>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebServers">
<option name="servers">
<webServer id="5e7bbff3-e86a-4465-b0e5-c1f0541c0000" name="81.69.44.74" url="http://81.69.44.74">
<fileTransfer host="81.69.44.74" port="21">
<advancedOptions>
<advancedOptions dataProtectionLevel="Private" passiveMode="true" shareSSLContext="true" />
</advancedOptions>
</fileTransfer>
</webServer>
</option>
</component>
</project>

@ -14,6 +14,7 @@
"build:alipay": "taro build --type alipay", "build:alipay": "taro build --type alipay",
"build:tt": "taro build --type tt", "build:tt": "taro build --type tt",
"build:h5": "taro build --type h5", "build:h5": "taro build --type h5",
"build:h5Playedu": "taro build --mode playedu --type h5 ",
"build:rn": "taro build --type rn", "build:rn": "taro build --type rn",
"build:qq": "taro build --type qq", "build:qq": "taro build --type qq",
"build:jd": "taro build --type jd", "build:jd": "taro build --type jd",
@ -23,6 +24,7 @@
"dev:alipay": "npm run build:alipay -- --watch", "dev:alipay": "npm run build:alipay -- --watch",
"dev:tt": "npm run build:tt -- --watch", "dev:tt": "npm run build:tt -- --watch",
"dev:h5": "npm run build:h5 -- --watch", "dev:h5": "npm run build:h5 -- --watch",
"dev:h5Playedu": "npm run build:h5 --mode playedu -- --watch ",
"dev:rn": "npm run build:rn -- --watch", "dev:rn": "npm run build:rn -- --watch",
"dev:qq": "npm run build:qq -- --watch", "dev:qq": "npm run build:qq -- --watch",
"dev:jd": "npm run build:jd -- --watch", "dev:jd": "npm run build:jd -- --watch",

@ -44,12 +44,6 @@ export const ERROR_STATUS: Record<number | string, string> = {
'OVERSTEP': '请求越界~' 'OVERSTEP': '请求越界~'
} }
// const whitelist = [
// '/api/v1/auth/login/code',
// '/api/v1/auth/login/checkout',
// '/api/v1/auth/login/wechat'
// ]
export function request<T = unknown>( export function request<T = unknown>(
url: string, url: string,
method: keyof Method, method: keyof Method,
@ -64,21 +58,12 @@ export function request<T = unknown>(
'Content-Type': 'application/json;charset=UTF-8', 'Content-Type': 'application/json;charset=UTF-8',
} }
} }
const token = JSON.parse(Taro.getStorageSync('profile') || '{}')?.token const token = JSON.parse(Taro.getStorageSync('profile') || '{}')?.token
if (token) { if (token) {
option.header ??= {} option.header ??= {}
option.header['Authorization'] = `Bearer ${token}` option.header['Authorization'] = `Bearer ${token}`
} }
// else {
/** 登录页面白名单 */
// if (Taro.getCurrentInstance().router?.path === '/pages/login/login') {
// if (!whitelist.includes(url)) {
// return new Promise((_, reject) => reject())
// }
// } else {
// return new Promise((_, reject) => reject())
// }
// }
if (method === 'GET' && data) { if (method === 'GET' && data) {
let parameter = '' let parameter = ''
Object.entries(data).forEach(([key, value], index) => { Object.entries(data).forEach(([key, value], index) => {
@ -88,7 +73,6 @@ export function request<T = unknown>(
} }
data && (option.data = data) data && (option.data = data)
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
Taro.request<T>({ Taro.request<T>({
...option, ...option,
success(res) { success(res) {
@ -97,16 +81,19 @@ export function request<T = unknown>(
if (data?.code === 0 && res.statusCode === 200) { if (data?.code === 0 && res.statusCode === 200) {
resolve(data.data || []) resolve(data.data || [])
} else if (res.statusCode === 401) { } else if (res.statusCode === 401) {
// Taro.showModal({ Taro.showModal({
// title: "登录过期,需重新登陆", title: "登录过期,需重新登陆",
// showCancel: false, showCancel: false,
// success({confirm}) { success({confirm}) {
// confirm && Taro.reLaunch({url: '/pages/login/login'}) confirm && Taro.reLaunch({url: '/pages/login/login'})
// } }
// }) })
} else { } else {
reject(null) reject(null)
Taro.showToast({title: data.msg || data.message || ERROR_STATUS[res.statusCode] || '请求错误~', icon: 'error'}) Taro.showToast({
title: data.msg || data.message || ERROR_STATUS[res.statusCode] || '请求错误~',
icon: 'error'
})
} }
} catch (e) { } catch (e) {
reject(null) reject(null)
@ -115,7 +102,7 @@ export function request<T = unknown>(
fail(err) { fail(err) {
const errMsg = err?.errMsg const errMsg = err?.errMsg
console.log(err) console.log(err)
Taro.showToast({title: ERROR_STATUS[errMsg] || ERROR_STATUS['DEFAULT'], icon: 'error'}) Taro.showToast({title: ERROR_STATUS[errMsg] || ERROR_STATUS['DEFAULT'], icon: 'error'})
reject(null) reject(null)
} }
}) })

@ -1,8 +1,8 @@
export default defineAppConfig({ export default defineAppConfig({
pages: [ pages: [
'pages/index/index',
'pages/login/login', 'pages/login/login',
'pages/check/check', 'pages/check/check',
'pages/index/index',
'pages/my/my' 'pages/my/my'
], ],
window: { window: {

@ -2,6 +2,8 @@ import Taro, {useDidShow, useDidHide} from '@tarojs/taro'
import './app.scss' import './app.scss'
import {CustomWrapper} from "@tarojs/components"; import {CustomWrapper} from "@tarojs/components";
import unique_ident from "@/hooks/unique_ident"; import unique_ident from "@/hooks/unique_ident";
import {Profile} from '@/store'
function updateApp() { function updateApp() {
if (Taro.canIUse('getUpdateManager.onCheckForUpdate')) { if (Taro.canIUse('getUpdateManager.onCheckForUpdate')) {
@ -10,7 +12,6 @@ function updateApp() {
console.log('新版本', res.hasUpdate) console.log('新版本', res.hasUpdate)
}) })
updateManager.onUpdateReady(() => { updateManager.onUpdateReady(() => {
Taro.showModal({ Taro.showModal({
title: '更新提示', title: '更新提示',
@ -35,15 +36,10 @@ function App(props) {
Taro.useLaunch(() => { Taro.useLaunch(() => {
updateApp() updateApp()
// const token = JSON.parse(Taro.getStorageSync('profile') || '{}')?.token
// if (!token) {
// Taro.reLaunch({url: '/pages/login/login'})
// }
unique_ident.put() unique_ident.put()
unique_ident.del() unique_ident.del()
}) })
Taro.getSystemInfo({ Taro.getSystemInfo({
success(res) { success(res) {
Taro.getApp().globalData = { Taro.getApp().globalData = {
@ -67,7 +63,9 @@ function App(props) {
return ( return (
<CustomWrapper> <CustomWrapper>
{props.children} <Profile.Provider>
{props.children}
</Profile.Provider>
</CustomWrapper> </CustomWrapper>
) )
} }

@ -4,4 +4,8 @@
padding: 20px 0; padding: 20px 0;
width: 100%; width: 100%;
border-top: 1px solid #eee; border-top: 1px solid #eee;
& > * {
background: red;
}
} }

@ -2,7 +2,7 @@ import {FC, useRef, useState} from "react";
import {Button, Form, Image, Input, View} from "@tarojs/components"; import {Button, Form, Image, Input, View} from "@tarojs/components";
import {Profile} from "@/store"; import {Profile} from "@/store";
import {userApi} from "@/api"; import {userApi} from "@/api";
import Taro, {useRouter} from "@tarojs/taro"; import Taro from "@tarojs/taro";
import {regexTel} from "@/utils/regu"; import {regexTel} from "@/utils/regu";
import styles from './check.module.scss' import styles from './check.module.scss'
@ -19,7 +19,7 @@ const Bing: FC = () => {
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const {setUser, setToken, setCompany} = Profile.useContainer() const {setUser, setToken, setCompany} = Profile.useContainer()
const [captchaKey, setCaptchaKey] = useState(uuid()) const [captchaKey, setCaptchaKey] = useState(uuid())
const router = useRouter() const openid = localStorage.getItem('openid')
async function Submit(data) { async function Submit(data) {
setLoading(true) setLoading(true)
@ -33,7 +33,7 @@ const Bing: FC = () => {
const res = await userApi.checkout({ const res = await userApi.checkout({
...value, ...value,
catch_key: captchaKey, catch_key: captchaKey,
openid: router.params.openid, openid,
}) })
if (res) { if (res) {
setCompany(res.company) setCompany(res.company)
@ -52,7 +52,7 @@ const Bing: FC = () => {
<Form className='form' onSubmit={Submit} ref={form}> <Form className='form' onSubmit={Submit} ref={form}>
<View className='item'> <View className='item'>
<View></View> <View></View>
<Input name='phone_number' placeholder={'请输入手机号'} value='18708100736'/> <Input name='phone_number' placeholder={'请输入手机号'}/>
</View> </View>
<View className='item'> <View className='item'>

@ -1,5 +1,5 @@
import {FC, useEffect, useState} from "react"; import {FC, useEffect, useState} from "react";
import Taro, {useReachBottom} from "@tarojs/taro"; import {useReachBottom} from "@tarojs/taro";
import {View} from "@tarojs/components"; import {View} from "@tarojs/components";
import {Courses, CoursesKey, publicApi} from "@/api/public"; import {Courses, CoursesKey, publicApi} from "@/api/public";
import VideoCover from "@/components/videoCover/videoCover"; import VideoCover from "@/components/videoCover/videoCover";
@ -10,10 +10,10 @@ import Empty from "@/components/empty/empty";
interface Props { interface Props {
categoryKey: CoursesKey categoryKey: CoursesKey
ready: boolean
} }
export const VideoList: FC<Props> = ({categoryKey}) => { export const VideoList: FC<Props> = ({categoryKey, ready}) => {
const [init, setInit] = useState(false)
const [data, setData] = useState<Courses>({ const [data, setData] = useState<Courses>({
is_finished: [], is_finished: [],
is_required: [], is_required: [],
@ -68,17 +68,12 @@ export const VideoList: FC<Props> = ({categoryKey}) => {
// getRecords() // getRecords()
// }) // })
Taro.useDidShow(() => {
if (init) {
getData()
}
getRecords()
})
useEffect(() => { useEffect(() => {
setInit(true) if (ready) {
getData() getData().then()
}, [page]) getRecords().then()
}
}, [page, ready])
return ( return (
<View className={'py-2 flex justify-between flex-wrap ' + styles.videoListBox}> <View className={'py-2 flex justify-between flex-wrap ' + styles.videoListBox}>
{data?.[categoryKey]?.length ? data?.[categoryKey]?.map(c => {data?.[categoryKey]?.length ? data?.[categoryKey]?.map(c =>

@ -1,17 +1,17 @@
import {FC, useEffect, useState} from "react"; import {FC, useState} from "react";
import {View} from "@tarojs/components"; import {View} from "@tarojs/components";
import styles from './index.module.scss' import styles from './index.module.scss'
import {Profile} from '@/store'
import {VideoList} from "@/pages/index/components/videoList"; import {VideoList} from "@/pages/index/components/videoList";
import Tabs, {OnChangOpt, TabList} from "@/components/tabs/tabs"; import Tabs, {OnChangOpt, TabList} from "@/components/tabs/tabs";
import {CoursesKey} from "@/api/public"; import {CoursesKey} from "@/api/public";
import Taro, {useRouter} from '@tarojs/taro' import Taro from '@tarojs/taro'
import {Profile} from '@/store'
// import {Search} from "@/pages/index/components/search"; // import {Search} from "@/pages/index/components/search";
const Index: FC = () => { const Index: FC = () => {
const globalData = Taro.getApp().globalData const globalData = Taro.getApp().globalData
const router = useRouter();
const category: TabList[] = [ const category: TabList[] = [
{title: "必修", value: 'is_required'}, {title: "必修", value: 'is_required'},
{title: "选修", value: 'is_not_required'}, {title: "选修", value: 'is_not_required'},
@ -19,28 +19,22 @@ const Index: FC = () => {
{title: "未完成", value: 'is_not_finished'}, {title: "未完成", value: 'is_not_finished'},
] ]
const [categoryKey, setCategoryKey] = useState<CoursesKey>('is_required') const [categoryKey, setCategoryKey] = useState<CoursesKey>('is_required')
const {token} = Profile.useContainer()
function tabChange(data: OnChangOpt) { function tabChange(data: OnChangOpt) {
setCategoryKey(data.tab?.value as CoursesKey) setCategoryKey(data.tab?.value as CoursesKey)
} }
useEffect(() => {
if (router.params.d) {
Taro.setStorageSync("profile", decodeURIComponent(router.params.d))
Taro.reLaunch({url:"/pages/index/index"})
}
}, [])
return ( return (
<Profile.Provider> <>
<View className={styles.content} style={`paddingTop:${globalData.statusBarHeight}px`}> <View className={styles.content} style={`paddingTop:${globalData.statusBarHeight}px`}>
{process.env.TARO_ENV !== "h5" && <View className='text-center font-weight font-34 mt-3'></View>} {process.env.TARO_ENV !== "h5" && <View className='text-center font-weight font-34 mt-3'></View>}
{/*<Search/>*/} {/*<Search/>*/}
<Tabs tabList={category} onChange={tabChange} current={categoryKey}/> <Tabs tabList={category} onChange={tabChange} current={categoryKey}/>
<VideoList categoryKey={categoryKey}/> <VideoList categoryKey={categoryKey} ready={!!token}/>
</View> </View>
</Profile.Provider> </>
) )
} }

@ -103,7 +103,6 @@ const Login: FC = () => {
const params = Taro.getCurrentInstance()?.router?.params as unknown as { data: LoginData } const params = Taro.getCurrentInstance()?.router?.params as unknown as { data: LoginData }
useEffect(() => { useEffect(() => {
console.log(params)
if (params?.data) { if (params?.data) {
if (!params.data?.code) { if (!params.data?.code) {
setUser(params.data.user) setUser(params.data.user)
@ -175,6 +174,13 @@ const Login: FC = () => {
} }
} }
async function TESTLOGIN() {
const res = await loginApi.testLogin()
localStorage.setItem('profile', JSON.stringify({data:res}))
Taro.switchTab({url: '/pages/index/index'})
}
return ( return (
<View className={styles.container}> <View className={styles.container}>
<CustomPageContainer show={!!validateCode} position='bottom' onBeforeLeave={() => setCode(null)}> <CustomPageContainer show={!!validateCode} position='bottom' onBeforeLeave={() => setCode(null)}>
@ -187,7 +193,7 @@ const Login: FC = () => {
<View className={styles.loginTips}> <View className={styles.loginTips}>
<Text>使</Text> <Text>使</Text>
</View> </View>
<MyButton onClick={login} disabled={isLoading}> <MyButton onClick={login}>
<View className={styles.submit}> <View className={styles.submit}>
{isLoading ? <Loading/> : null} {isLoading ? <Loading/> : null}
<View className={styles.navbar}> <View className={styles.navbar}>
@ -201,16 +207,11 @@ const Login: FC = () => {
</View> </View>
</View> </View>
</MyButton> </MyButton>
{process.env.TARO_APP_LGOIN && <MyButton onClick={TESTLOGIN}>线</MyButton>}
</View> </View>
) )
} }
const Index: FC = () => {
return (
<Profile.Provider>
<Login/>
</Profile.Provider>
)
}
export default Index export default Login

@ -3,12 +3,52 @@ import {createContainer} from "unstated-next";
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
function DataKey(data: any) {
return !Array.isArray(data)
&& typeof data === 'object'
&& 'data' in data
&& 'user' in data.data
&& 'token' in data.data
&& 'company' in data.data
}
const whitelist = [
'/pages/check/check',
'/pages/login/login',
]
function useProfile() { function useProfile() {
let data let data
try {
data = JSON.parse(Taro.getStorageSync('profile') || '{}') if (process.env.TARO_ENV === 'h5') {
} catch (e) { try {
console.error(e) const profileCopy = JSON.parse(localStorage.getItem("profileCopy") || '{}')
if (DataKey(profileCopy)) {
data = profileCopy.data || null
localStorage.removeItem("profileCopy")
Taro.switchTab({url: '/pages/index/index'})
}
} catch (e) {
console.error(e)
}
}
if (data == null) {
try {
const cacheData = {data: JSON.parse(Taro.getStorageSync('profile') || '{}')}
if (DataKey(cacheData)) {
data = cacheData.data
}
} catch (e) {
console.error(e)
}
}
if (data?.token == null) {
if (!whitelist.includes(Taro.getCurrentInstance().router?.path?.split('?')?.[0] || '')) {
Taro.reLaunch({url: '/pages/login/login'})
}
} }
const [role, setRole] = useState<UserRole | null>(data?.role || null) const [role, setRole] = useState<UserRole | null>(data?.role || null)
@ -22,7 +62,7 @@ function useProfile() {
setUser(null) setUser(null)
setToken(null) setToken(null)
Taro.removeStorageSync('profile') Taro.removeStorageSync('profile')
// Taro.reLaunch({url: '/pages/login/login'}) Taro.reLaunch({url: '/pages/login/login'})
} }
useEffect(() => { useEffect(() => {

Loading…
Cancel
Save