mirror of
https://gitee.com/wonderful-code/buildadmin
synced 2024-11-21 22:55:36 +00:00
feat:Axios封装、管理员权限类完善
This commit is contained in:
parent
3470c0bc09
commit
24f9e38385
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
BIN
public/static/images/avatar.png
Normal file
BIN
public/static/images/avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 424 B |
@ -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,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user