mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-13 12:02:51 +00:00
no message
This commit is contained in:
parent
63c6e12aca
commit
7b49d66a8e
@ -267,9 +267,20 @@ class UsersController extends AbstractController
|
||||
return Base::retSuccess('请求成功', $captcha);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/users/logout 06. 退出登录
|
||||
*
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup users
|
||||
* @apiName logout
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
$user = User::auth();
|
||||
UserDevice::forget();
|
||||
return Base::retSuccess('退出成功');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2504,6 +2515,6 @@ class UsersController extends AbstractController
|
||||
}
|
||||
UserDevice::forget($userDevice->id);
|
||||
//
|
||||
return Base::retSuccess('删除成功');
|
||||
return Base::retSuccess('操作成功');
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,8 +444,9 @@ class User extends AbstractModel
|
||||
{
|
||||
$user = self::authInfo();
|
||||
if (!$user) {
|
||||
if (Base::token()) {
|
||||
UserDevice::forget();
|
||||
$token = Base::token();
|
||||
if ($token) {
|
||||
UserDevice::forget($token);
|
||||
throw new ApiException('身份已失效,请重新登录', [], -1);
|
||||
} else {
|
||||
throw new ApiException('请登录后继续...', [], -1);
|
||||
|
||||
@ -838,7 +838,7 @@ export default {
|
||||
case 'logout':
|
||||
$A.modalConfirm({
|
||||
title: '退出登录',
|
||||
content: '你确定要登出系统?',
|
||||
content: '你确定要登出系统吗?',
|
||||
onOk: () => {
|
||||
this.$store.dispatch("logout", false)
|
||||
}
|
||||
|
||||
212
resources/assets/js/pages/manage/setting/device.vue
Normal file
212
resources/assets/js/pages/manage/setting/device.vue
Normal file
@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div class="setting-device">
|
||||
<ul>
|
||||
<li v-for="device in devices" :key="device.id">
|
||||
<div class="icon">
|
||||
<span :class="getIcon(device.detail)"></span>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="title">
|
||||
<span class="name">{{ getName(device.detail) }}</span>
|
||||
<span class="device">{{ device.detail.os }}</span>
|
||||
</div>
|
||||
<div class="time">
|
||||
<EPopover placement="bottom-start" trigger="click">
|
||||
<div class="time-popover">
|
||||
<p>{{$L('登录时间')}}: {{device.created_at}}</p>
|
||||
<p>{{$L('更新时间')}}: {{device.updated_at}}</p>
|
||||
<p>{{$L('过期时间')}}: {{device.expired_at}}</p>
|
||||
</div>
|
||||
<span slot="reference">{{ device.updated_at }}</span>
|
||||
</EPopover>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span v-if="device.is_current" class="current">{{$L('当前设备')}}</span>
|
||||
<Button v-else @click="onLogout(device)">{{$L('退出登录')}}</Button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setting-device {
|
||||
> ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
> li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 24px;
|
||||
border-radius: 12px;
|
||||
background: rgba(79, 89, 102, .04);
|
||||
|
||||
.icon {
|
||||
align-self: flex-start;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 24px;
|
||||
|
||||
> span {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
justify-content: flex-start;
|
||||
color: #262626;
|
||||
|
||||
.name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.device {
|
||||
&:before {
|
||||
content: "(";
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: #8a939d;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.current {
|
||||
color: #595959;
|
||||
}
|
||||
|
||||
.ivu-btn {
|
||||
background: #d9d9dd;
|
||||
border-color: #d9d9dd;
|
||||
color: #262626;
|
||||
box-shadow: none;
|
||||
height: 36px;
|
||||
padding: 0 12px;
|
||||
border-radius: 12px;
|
||||
&:hover {
|
||||
background: rgba(217, 217, 221, 0.8);
|
||||
border-color: rgba(217, 217, 221, 0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.time-popover {
|
||||
> p {
|
||||
line-height: 26px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SettingDevice',
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
devices: []
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.getDeviceList();
|
||||
},
|
||||
|
||||
methods: {
|
||||
getDeviceList() {
|
||||
this.loadIng++;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/device/list',
|
||||
}).then(({data}) => {
|
||||
this.devices = data.list
|
||||
if (typeof this.$parent.updateDeviceNum === "function") {
|
||||
this.$parent.updateDeviceNum(this.devices.length);
|
||||
}
|
||||
}).catch(() => {
|
||||
this.devices = []
|
||||
}).finally(() => {
|
||||
this.loadIng--;
|
||||
})
|
||||
},
|
||||
|
||||
getIcon({app_type}) {
|
||||
if (/ios/i.test(app_type)) {
|
||||
return 'apple';
|
||||
}
|
||||
else if (/android/i.test(app_type)) {
|
||||
return 'android';
|
||||
}
|
||||
else if (/mac/i.test(app_type)) {
|
||||
return 'macos';
|
||||
}
|
||||
else if (/win/i.test(app_type)) {
|
||||
return 'window';
|
||||
}
|
||||
return 'web';
|
||||
},
|
||||
|
||||
getName({app_type, browser}) {
|
||||
if (/web/i.test(app_type)) {
|
||||
return browser + " " + this.$L("浏览器")
|
||||
}
|
||||
return app_type + " " + this.$L("客户端")
|
||||
},
|
||||
|
||||
onLogout(device) {
|
||||
$A.modalConfirm({
|
||||
title: '退出登录',
|
||||
content: '是否在该设备上退出登录?',
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/device/logout',
|
||||
data: {
|
||||
id: device.id
|
||||
}
|
||||
}).then(({msg}) => {
|
||||
resolve(msg);
|
||||
this.getDeviceList();
|
||||
}).catch(({msg}) => {
|
||||
reject(msg);
|
||||
});
|
||||
})
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@ -17,7 +17,11 @@
|
||||
:key="key"
|
||||
:class="classNameRoute(item.path, item.divided)"
|
||||
@click="toggleRoute(item.path)">
|
||||
<template v-if="item.path === 'version'">
|
||||
<template v-if="item.path === 'device'">
|
||||
<AutoTip>{{$L(item.name)}}</AutoTip>
|
||||
<span v-if="deviceNum > 0" class="op-8">{{deviceNum}}</span>
|
||||
</template>
|
||||
<template v-else-if="item.path === 'version'">
|
||||
<AutoTip disabled>{{$L(item.name)}}</AutoTip>
|
||||
<Badge v-if="!!clientNewVersion" :text="clientNewVersion"/>
|
||||
</template>
|
||||
@ -51,6 +55,7 @@ export default {
|
||||
components: {MobileNavTitle},
|
||||
data() {
|
||||
return {
|
||||
deviceNum: 0,
|
||||
version: window.systemInfo.version
|
||||
}
|
||||
},
|
||||
@ -61,6 +66,10 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.getDeviceNum();
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['userInfo', 'userIsAdmin', 'clientNewVersion', 'systemConfig']),
|
||||
|
||||
@ -97,7 +106,8 @@ export default {
|
||||
menu.push(...[
|
||||
{path: 'version', name: '更新日志', divided: true},
|
||||
{path: 'version-show', name: '版本'},
|
||||
{path: 'clearCache', name: '清除缓存', divided: true},
|
||||
{path: 'device', name: '登录设备', divided: true},
|
||||
{path: 'clearCache', name: '清除缓存'},
|
||||
{path: 'logout', name: '退出登录'},
|
||||
])
|
||||
return menu;
|
||||
@ -224,6 +234,20 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
getDeviceNum() {
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/device/count',
|
||||
}).then(({data}) => {
|
||||
this.updateDeviceNum(data.count)
|
||||
}).catch(() => {
|
||||
this.updateDeviceNum(0)
|
||||
})
|
||||
},
|
||||
|
||||
updateDeviceNum(num) {
|
||||
this.deviceNum = num
|
||||
},
|
||||
|
||||
getServerVersion() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (/^\d+\.\d+\.\d+$/.test(this.systemConfig.server_version)) {
|
||||
|
||||
5
resources/assets/js/routes.js
vendored
5
resources/assets/js/routes.js
vendored
@ -94,6 +94,11 @@ export default [
|
||||
path: 'system',
|
||||
component: () => import('./pages/manage/setting/system.vue'),
|
||||
},
|
||||
{
|
||||
name: 'manage-setting-device',
|
||||
path: 'device',
|
||||
component: () => import('./pages/manage/setting/device.vue'),
|
||||
},
|
||||
{
|
||||
name: 'manage-setting-version',
|
||||
path: 'version',
|
||||
|
||||
5
resources/assets/js/store/actions.js
vendored
5
resources/assets/js/store/actions.js
vendored
@ -985,6 +985,11 @@ export default {
|
||||
* @param appendFrom
|
||||
*/
|
||||
logout({state, dispatch}, appendFrom = true) {
|
||||
try {
|
||||
dispatch("call", "users/logout")
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
dispatch("handleClearCache", {}).then(() => {
|
||||
let from = ["/", "/login"].includes(window.location.pathname) ? "" : encodeURIComponent(window.location.href);
|
||||
if (appendFrom === false) {
|
||||
|
||||
30
resources/assets/sass/pages/page-setting.scss
vendored
30
resources/assets/sass/pages/page-setting.scss
vendored
@ -82,6 +82,14 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.common-auto-tip {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.op-8 {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.ivu-badge {
|
||||
transform: scale(0.8);
|
||||
transform-origin: right center;
|
||||
@ -334,6 +342,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
.setting-device {
|
||||
.icon {
|
||||
> span {
|
||||
&.android {
|
||||
background-image: url("../images/device/android.svg");
|
||||
}
|
||||
&.apple {
|
||||
background-image: url("../images/device/apple.svg");
|
||||
}
|
||||
&.macos {
|
||||
background-image: url("../images/device/macos.svg");
|
||||
}
|
||||
&.window {
|
||||
background-image: url("../images/device/window.svg");
|
||||
}
|
||||
&.web {
|
||||
background-image: url("../images/device/web.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.window-portrait {
|
||||
.page-setting {
|
||||
background-color: #f8f8f8;
|
||||
|
||||
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1024"><path d="M270.1 741.7c0 23.4 19.1 42.5 42.6 42.5h48.7v120.4c0 30.5 24.5 55.4 54.6 55.4c30.2 0 54.6-24.8 54.6-55.4V784.1h85v120.4c0 30.5 24.5 55.4 54.6 55.4c30.2 0 54.6-24.8 54.6-55.4V784.1h48.7c23.5 0 42.6-19.1 42.6-42.5V346.4h-486v395.3zm357.1-600.1l44.9-65c2.6-3.8 2-8.9-1.5-11.4c-3.5-2.4-8.5-1.2-11.1 2.6l-46.6 67.6c-30.7-12.1-64.9-18.8-100.8-18.8c-35.9 0-70.1 6.7-100.8 18.8l-46.6-67.5c-2.6-3.8-7.6-5.1-11.1-2.6c-3.5 2.4-4.1 7.4-1.5 11.4l44.9 65c-71.4 33.2-121.4 96.1-127.8 169.6h486c-6.6-73.6-56.7-136.5-128-169.7zM409.5 244.1a26.9 26.9 0 1 1 26.9-26.9a26.97 26.97 0 0 1-26.9 26.9zm208.4 0a26.9 26.9 0 1 1 26.9-26.9a26.97 26.97 0 0 1-26.9 26.9zm223.4 100.7c-30.2 0-54.6 24.8-54.6 55.4v216.4c0 30.5 24.5 55.4 54.6 55.4c30.2 0 54.6-24.8 54.6-55.4V400.1c.1-30.6-24.3-55.3-54.6-55.3zm-658.6 0c-30.2 0-54.6 24.8-54.6 55.4v216.4c0 30.5 24.5 55.4 54.6 55.4c30.2 0 54.6-24.8 54.6-55.4V400.1c0-30.6-24.5-55.3-54.6-55.3z" fill="currentColor"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
1
resources/assets/statics/public/images/device/apple.svg
Normal file
1
resources/assets/statics/public/images/device/apple.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512"><path d="M349.13 136.86c-40.32 0-57.36 19.24-85.44 19.24c-28.79 0-50.75-19.1-85.69-19.1c-34.2 0-70.67 20.88-93.83 56.45c-32.52 50.16-27 144.63 25.67 225.11c18.84 28.81 44 61.12 77 61.47h.6c28.68 0 37.2-18.78 76.67-19h.6c38.88 0 46.68 18.89 75.24 18.89h.6c33-.35 59.51-36.15 78.35-64.85c13.56-20.64 18.6-31 29-54.35c-76.19-28.92-88.43-136.93-13.08-178.34c-23-28.8-55.32-45.48-85.79-45.48z" fill="currentColor"></path><path d="M340.25 32c-24 1.63-52 16.91-68.4 36.86c-14.88 18.08-27.12 44.9-22.32 70.91h1.92c25.56 0 51.72-15.39 67-35.11c14.72-18.77 25.88-45.37 21.8-72.66z" fill="currentColor"></path></svg>
|
||||
|
After Width: | Height: | Size: 710 B |
1
resources/assets/statics/public/images/device/macos.svg
Normal file
1
resources/assets/statics/public/images/device/macos.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none"><path d="M4.25 3A2.25 2.25 0 0 0 2 5.25v10.5A2.25 2.25 0 0 0 4.25 18H9.5v1.25c0 .69-.56 1.25-1.25 1.25h-.5a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-.5c-.69 0-1.25-.56-1.25-1.25V18h5.25A2.25 2.25 0 0 0 22 15.75V5.25A2.25 2.25 0 0 0 19.75 3H4.25zM13 18v1.25c0 .45.108.875.3 1.25h-2.6c.192-.375.3-.8.3-1.25V18h2zm-9.5-3.5h17v1.25a.75.75 0 0 1-.75.75H4.25a.75.75 0 0 1-.75-.75V14.5z" fill="currentColor"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 537 B |
1
resources/assets/statics/public/images/device/web.svg
Normal file
1
resources/assets/statics/public/images/device/web.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32"><g fill="none"><path d="M11 16c0-1.393.078-2.734.222-4h9.556c.144 1.266.222 2.607.222 4c0 1.393-.078 2.734-.222 4h-9.556A35.485 35.485 0 0 1 11 16zm-1.79 4A37.618 37.618 0 0 1 9 16c0-1.379.073-2.72.21-4H2.58A14.002 14.002 0 0 0 2 16c0 1.39.203 2.733.58 4h6.63zm-5.863 2h6.138c.314 1.86.771 3.547 1.344 4.978c.369.922.793 1.758 1.272 2.472A14.036 14.036 0 0 1 3.347 22zm8.168 0h8.97c-.29 1.6-.69 3.032-1.17 4.235c-.516 1.288-1.104 2.262-1.706 2.9c-.6.634-1.144.865-1.609.865c-.465 0-1.009-.231-1.609-.866c-.602-.637-1.19-1.611-1.705-2.899c-.481-1.203-.881-2.636-1.171-4.235zm11 0c-.314 1.86-.771 3.547-1.344 4.978c-.369.922-.793 1.758-1.272 2.472A14.036 14.036 0 0 0 28.653 22h-6.138zm6.905-2c.377-1.267.58-2.61.58-4c0-1.39-.203-2.733-.58-4h-6.63c.137 1.28.21 2.621.21 4s-.073 2.72-.21 4h6.63zM19.314 5.765c.481 1.203.881 2.636 1.171 4.235h-8.97c.29-1.6.69-3.032 1.17-4.235c.516-1.288 1.104-2.263 1.706-2.9c.598-.631 1.14-.863 1.604-.865h.008c.464 0 1.007.233 1.606.866c.602.636 1.19 1.611 1.705 2.899zM22.515 10h6.138a14.036 14.036 0 0 0-8.754-7.45c.479.714.903 1.55 1.272 2.472c.573 1.431 1.03 3.118 1.344 4.978zM3.347 10h6.138c.314-1.86.771-3.547 1.344-4.978c.369-.922.793-1.758 1.272-2.472A14.036 14.036 0 0 0 3.347 10z" fill="currentColor"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
resources/assets/statics/public/images/device/window.svg
Normal file
1
resources/assets/statics/public/images/device/window.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512"><path d="M480 265H232v179l248 36V265z" fill="currentColor"></path><path d="M216 265H32v150l184 26.7V265z" fill="currentColor"></path><path d="M480 32L232 67.4V249h248V32z" fill="currentColor"></path><path d="M216 69.7L32 96v153h184V69.7z" fill="currentColor"></path></svg>
|
||||
|
After Width: | Height: | Size: 377 B |
Loading…
x
Reference in New Issue
Block a user