feat:Axios封装、管理员权限类完善

This commit is contained in:
妙码生花 2022-02-27 03:34:16 +08:00
parent 3470c0bc09
commit 24f9e38385
6 changed files with 246 additions and 44 deletions

View File

@ -111,21 +111,21 @@ class Auth
*/
public function login($username, $password, $keeptime = 0)
{
$this->admin = Admin::where('username', $username)->find();
if (!$this->admin) {
$this->model = Admin::where('username', $username)->find();
if (!$this->model) {
$this->setError('Username is incorrect');
return false;
}
if ($this->admin['status'] == '0') {
if ($this->model['status'] == '0') {
$this->setError('Administrator disabled');
return false;
}
$adminLoginRetry = Config::get('buildadmin.admin_login_retry');
if ($adminLoginRetry && $this->admin->loginfailure >= $adminLoginRetry && time() - $this->admin->lastlogintime < 86400) {
if ($adminLoginRetry && $this->model->loginfailure >= $adminLoginRetry && time() - $this->model->lastlogintime < 86400) {
$this->setError('Please try again after 1 day');
return false;
}
if ($this->admin->password != $this->admin->encryptPassword($password, $this->admin->salt)) {
if ($this->model->password != Admin::encryptPassword($password, $this->model->salt)) {
$this->loginFailed();
$this->setError('Password is incorrect');
return false;
@ -146,15 +146,15 @@ class Auth
}
Db::startTrans();
try {
$this->admin->loginfailure = 0;
$this->admin->lastlogintime = time();
$this->admin->lastloginip = request()->ip();
$this->admin->save();
$this->model->loginfailure = 0;
$this->model->lastlogintime = time();
$this->model->lastloginip = request()->ip();
$this->model->save();
$this->logined = true;
if (!$this->token) {
$this->token = Random::uuid();
Token::set($this->_token, 'admin', $this->admin->id, $this->keeptime);
Token::set($this->token, 'admin', $this->model->id, $this->keeptime);
}
Db::commit();
} catch (Exception $e) {
@ -176,13 +176,13 @@ class Auth
}
Db::startTrans();
try {
$this->admin->loginfailure++;
$this->admin->lastlogintime = time();
$this->admin->lastloginip = request()->ip();
$this->admin->save();
$this->model->loginfailure++;
$this->model->lastlogintime = time();
$this->model->lastloginip = request()->ip();
$this->model->save();
$this->token = '';
$this->admin = null;
$this->model = null;
$this->logined = false;
Db::commit();
} catch (Exception $e) {
@ -242,6 +242,9 @@ class Auth
*/
public function getInfo()
{
if (!$this->model) {
return [];
}
$info = $this->model->toArray();
$info = array_intersect_key($info, array_flip($this->getAllowFields()));
$info['token'] = $this->getToken();

View File

@ -17,13 +17,13 @@ class Admin extends Model
*/
public function resetPassword($uid, $NewPassword)
{
$passwd = $this->encryptPassword($NewPassword);
$passwd = self::encryptPassword($NewPassword);
$ret = $this->where(['id' => $uid])->update(['password' => $passwd]);
return $ret;
}
// 密码加密
protected function encryptPassword($password, $salt = '', $encrypt = 'md5')
public static function encryptPassword($password, $salt = '', $encrypt = 'md5')
{
return $encrypt($encrypt($password) . $salt);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

View File

@ -1,9 +1,14 @@
import Axios from '/@/utils/axios'
import createAxios from '/@/utils/axios'
export function login(params: object, method: 'get' | 'post') {
return Axios.request({
url: '/index.php/admin/index/login',
data: params,
method: method,
})
export function login(method: 'get' | 'post', params: object = {}) {
return createAxios(
{
url: '/index.php/admin/index/login',
data: params,
method: method,
},
{
showCodeMessage: true,
}
)
}

View File

@ -1,24 +1,220 @@
import axios from 'axios'
import type { AxiosRequestConfig } from 'axios'
import { computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Local } from '/@/utils/storage'
import { ElMessage, ElLoading, LoadingOptions } from 'element-plus'
import { store } from '/@/store/index'
import { isProd } from '/@/utils/vite'
const lang = computed(() => store.state.config.defaultLang)
const pendingMap = new Map()
const loadingInstance: LoadingInstance = {
target: null,
count: 0,
}
export const getUrl = (): string => {
const value: string = import.meta.env.VITE_AXIOS_BASE_URL as string
return value == 'getCurrentDomain' ? window.location.protocol + '//' + window.location.host : value
}
const lang = computed(() => store.state.config.defaultLang)
function createAxios(config: AxiosRequestConfig, options: Options = {}, loading: LoadingOptions = {}) {
const Axios = axios.create({
baseURL: getUrl(),
timeout: 1000 * 10,
headers: {
'Content-Type': 'application/json',
'think-lang': lang.value,
},
})
const Axios = axios.create({
baseURL: getUrl(),
timeout: 50000,
headers: {
'Content-Type': 'application/json',
'think-lang': lang.value,
},
})
options = Object.assign(
{
CancelDuplicateRequest: true, // 是否开启取消重复请求, 默认为 true
loading: false, // 是否开启loading层效果, 默认为false
reductDataFormat: true, // 是否开启简洁的数据结构响应, 默认为true
showErrorMessage: true, // 是否开启接口错误信息展示,默认为true
showCodeMessage: true, // 是否开启code不为1时的信息提示, 默认为false
},
options
)
export default Axios
// 请求拦截
Axios.interceptors.request.use(
(config) => {
removePending(config)
options.CancelDuplicateRequest && addPending(config)
// 创建loading实例
if (options.loading) {
loadingInstance.count++
if (loadingInstance.count === 1) {
loadingInstance.target = ElLoading.service(loading)
}
}
// 自动携带token - 待完善
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截
Axios.interceptors.response.use(
(response) => {
removePending(response.config)
options.loading && closeLoading(options) // 关闭loading
if (options.showCodeMessage && response.data && response.data.code !== 1) {
ElMessage({
type: 'error',
message: response.data.msg,
})
// code不等于1, 页面then内的具体逻辑就不执行了
return Promise.reject(response.data)
}
return options.reductDataFormat ? response.data : response
},
(error) => {
error.config && removePending(error.config)
options.loading && closeLoading(options) // 关闭loading
options.showErrorMessage && httpErrorStatusHandle(error) // 处理错误状态码
return Promise.reject(error) // 错误继续返回给到具体页面
}
)
return Axios(config)
}
export default createAxios
/**
*
* @param {*} error
*/
function httpErrorStatusHandle(error: any) {
// 处理被取消的请求
if (axios.isCancel(error)) return console.error('因为请求重复被自动取消:' + error.message)
let message = ''
if (error && error.response) {
switch (error.response.status) {
case 302:
message = '接口重定向了!'
break
case 400:
message = '参数不正确!'
break
case 401:
message = '您未登录,或者登录已经超时,请先登录!'
break
case 403:
message = '您没有权限操作!'
break
case 404:
message = `请求地址出错: ${error.response.config.url}`
break
case 408:
message = '请求超时!'
break
case 409:
message = '系统已存在相同数据!'
break
case 500:
message = '服务器内部错误!'
break
case 501:
message = '服务未实现!'
break
case 502:
message = '网关错误!'
break
case 503:
message = '服务不可用!'
break
case 504:
message = '服务暂时无法访问,请稍后再试!'
break
case 505:
message = 'HTTP版本不受支持'
break
default:
message = '异常问题,请联系网站管理员!'
break
}
}
if (error.message.includes('timeout')) message = '网络请求超时!'
if (error.message.includes('Network')) message = window.navigator.onLine ? '服务端异常!' : '您断网了!'
ElMessage({
type: 'error',
message,
})
}
/**
* Loading层实例
*/
function closeLoading(options: Options) {
if (options.loading && loadingInstance.count > 0) loadingInstance.count--
if (loadingInstance.count === 0) {
loadingInstance.target.close()
loadingInstance.target = null
}
}
/**
* cancel回调,
*/
function addPending(config: AxiosRequestConfig) {
const pendingKey = getPendingKey(config)
config.cancelToken =
config.cancelToken ||
new axios.CancelToken((cancel) => {
if (!pendingMap.has(pendingKey)) {
pendingMap.set(pendingKey, cancel)
}
})
}
/**
*
*/
function removePending(config: AxiosRequestConfig) {
const pendingKey = getPendingKey(config)
if (pendingMap.has(pendingKey)) {
const cancelToken = pendingMap.get(pendingKey)
cancelToken(pendingKey)
pendingMap.delete(pendingKey)
}
}
/**
* key
*/
function getPendingKey(config: AxiosRequestConfig) {
let { url, method, params, data } = config
if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象
return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&')
}
interface LoadingInstance {
target: any
count: number
}
interface Options {
// 是否开启取消重复请求, 默认为 true
CancelDuplicateRequest?: boolean
// 是否开启loading层效果, 默认为false
loading?: boolean
// 是否开启简洁的数据结构响应, 默认为true
reductDataFormat?: boolean
// 是否开启接口错误信息展示,默认为true
showErrorMessage?: boolean
// 是否开启code不为0时的信息提示, 默认为true
showCodeMessage?: boolean
}
/*
* @橙某人提供的思路和分享
* axios封装详细解释请参考https://juejin.cn/post/6968630178163458084?share_token=7831c9e0-bea0-469e-8028-b587e13681a8#heading-27
*/

View File

@ -50,7 +50,7 @@
</template>
</el-input>
</el-form-item>
<el-form-item prop="captcha">
<el-form-item v-if="state.showCaptcha" prop="captcha">
<el-row class="w100" :gutter="15">
<el-col :span="16">
<el-input
@ -99,6 +99,7 @@ import { randomStr } from '/@/utils/common'
const store = useStore()
const state = reactive({
showCaptcha: false,
captchaId: randomStr(),
})
@ -173,10 +174,8 @@ onMounted(() => {
vm.ctx.$refs.captcha.focus()
}
login({}, 'get').then((res) => {
if (res.data.code == 302) {
console.log('登录过了~')
}
login('get').then((res) => {
state.showCaptcha = res.data.captcha
})
})
@ -194,7 +193,7 @@ const onSubmit = (formEl: InstanceType<typeof ElForm> | undefined) => {
if (valid) {
form.loading = true
form.captcha_id = state.captchaId
login(form, 'post')
login('post', form)
.then((res) => {
form.loading = false
console.log(res)
@ -203,7 +202,6 @@ const onSubmit = (formEl: InstanceType<typeof ElForm> | undefined) => {
form.loading = false
console.log(err)
})
console.log(form)
} else {
console.log('error submit!')
return false