no message
This commit is contained in:
parent
e5e7d2d052
commit
b24d1f79fa
@ -18,6 +18,14 @@ use Request;
|
||||
*/
|
||||
class ProjectController extends AbstractController
|
||||
{
|
||||
private $projectSelect = [
|
||||
'*',
|
||||
'projects.id AS id',
|
||||
'projects.userid AS userid',
|
||||
'projects.created_at AS created_at',
|
||||
'projects.updated_at AS updated_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* 项目列表
|
||||
*
|
||||
@ -33,7 +41,8 @@ class ProjectController extends AbstractController
|
||||
$user = User::IDE($user['data']);
|
||||
}
|
||||
//
|
||||
$list = Project::join('project_users', 'projects.id', '=', 'project_users.project_id')
|
||||
$list = Project::select($this->projectSelect)
|
||||
->join('project_users', 'projects.id', '=', 'project_users.project_id')
|
||||
->where('project_users.userid', $user->userid)
|
||||
->orderByDesc('projects.id')
|
||||
->paginate(Base::getPaginate(200, 100));
|
||||
@ -62,10 +71,15 @@ class ProjectController extends AbstractController
|
||||
$taskQuery->where('parent_id', 0);
|
||||
}]);
|
||||
}, 'projectUser'])
|
||||
->select($this->projectSelect)
|
||||
->join('project_users', 'projects.id', '=', 'project_users.project_id')
|
||||
->where('projects.id', $project_id)
|
||||
->where('project_users.userid', $user->userid)
|
||||
->first();
|
||||
if ($project) {
|
||||
$owner_user = $project->projectUser->where('owner', 1)->first();
|
||||
$project->owner_userid = $owner_user ? $owner_user->userid : 0;
|
||||
}
|
||||
//
|
||||
return Base::retSuccess('success', $project);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use App\Models\User;
|
||||
use App\Module\Base;
|
||||
use Cache;
|
||||
use Captcha;
|
||||
use Carbon\Carbon;
|
||||
use Request;
|
||||
|
||||
/**
|
||||
@ -87,11 +88,11 @@ class UsersController extends AbstractController
|
||||
}
|
||||
//
|
||||
$array = [
|
||||
'loginnum' => $user['loginnum'] + 1,
|
||||
'lastip' => Base::getIp(),
|
||||
'lastdate' => time(),
|
||||
'lineip' => Base::getIp(),
|
||||
'linedate' => time(),
|
||||
'login_num' => $user->login_num + 1,
|
||||
'last_ip' => Base::getIp(),
|
||||
'last_at' => Carbon::now(),
|
||||
'line_ip' => Base::getIp(),
|
||||
'line_at' => Carbon::now(),
|
||||
];
|
||||
foreach ($array as $key => $value) {
|
||||
$user->$key = $value;
|
||||
@ -159,14 +160,13 @@ class UsersController extends AbstractController
|
||||
"email": "admin@admin.com",
|
||||
"nickname": "admin",
|
||||
"userimg": "",
|
||||
"loginnum": 10,
|
||||
"login_num": 10,
|
||||
"changepass": 0,
|
||||
"lastip": "10.22.22.1",
|
||||
"lastdate": 1622468661,
|
||||
"lineip": "10.22.22.1",
|
||||
"linedate": 1622468661,
|
||||
"regip": "",
|
||||
"regdate": 0,
|
||||
"last_ip": "10.22.22.1",
|
||||
"last_at": "2021-06-01 12:00:00",
|
||||
"line_ip": "10.22.22.1",
|
||||
"line_at": "2021-06-01 12:00:00",
|
||||
"created_ip": "",
|
||||
}
|
||||
*/
|
||||
public function info()
|
||||
|
@ -5,6 +5,7 @@ namespace App\Models;
|
||||
|
||||
use App\Module\Base;
|
||||
use Cache;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* Class User
|
||||
@ -18,14 +19,13 @@ use Cache;
|
||||
* @property string|null $userimg 头像
|
||||
* @property string|null $encrypt
|
||||
* @property string|null $userpass 登录密码
|
||||
* @property int|null $loginnum 累计登录次数
|
||||
* @property int|null $login_num 累计登录次数
|
||||
* @property int|null $changepass 登录需要修改密码
|
||||
* @property string|null $lastip 最后登录IP
|
||||
* @property int|null $lastdate 最后登录时间
|
||||
* @property string|null $lineip 最后在线IP(接口)
|
||||
* @property int|null $linedate 最后在线时间(接口)
|
||||
* @property string|null $regip 注册IP
|
||||
* @property int|null $regdate 注册时间
|
||||
* @property string|null $last_ip 最后登录IP
|
||||
* @property \Illuminate\Support\Carbon|null $last_at 最后登录时间
|
||||
* @property string|null $line_ip 最后在线IP(接口)
|
||||
* @property \Illuminate\Support\Carbon|null $line_at 最后在线时间(接口)
|
||||
* @property string|null $created_ip 注册IP
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read string $usering
|
||||
@ -38,14 +38,13 @@ use Cache;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereEncrypt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereIdentity($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLastdate($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLastip($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLinedate($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLineip($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLoginnum($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLastAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLastIp($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLineAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLineIp($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLoginNum($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereNickname($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereRegdate($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereRegip($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedIp($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereUserid($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereUserimg($value)
|
||||
@ -59,7 +58,6 @@ class User extends AbstractModel
|
||||
protected $hidden = [
|
||||
'encrypt',
|
||||
'userpass',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
@ -80,7 +78,7 @@ class User extends AbstractModel
|
||||
*/
|
||||
public function getUserimgAttribute($value)
|
||||
{
|
||||
return self::userimg($value);
|
||||
return $value ? Base::fillUrl($value) : url('images/other/avatar.png');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,8 +127,7 @@ class User extends AbstractModel
|
||||
'encrypt' => $encrypt,
|
||||
'email' => $email,
|
||||
'userpass' => Base::md52($userpass, $encrypt),
|
||||
'regip' => Base::getIp(),
|
||||
'regdate' => time()
|
||||
'created_ip' => Base::getIp(),
|
||||
];
|
||||
if ($other) {
|
||||
$inArray = array_merge($inArray, $other);
|
||||
@ -228,11 +225,11 @@ class User extends AbstractModel
|
||||
$row = self::whereUserid($authInfo['userid'])->whereEmail($authInfo['email'])->whereEncrypt($authInfo['encrypt'])->first();
|
||||
if ($row) {
|
||||
$upArray = [];
|
||||
if (Base::getIp() && $row->lineip != Base::getIp()) {
|
||||
$upArray['lineip'] = Base::getIp();
|
||||
if (Base::getIp() && $row->line_ip != Base::getIp()) {
|
||||
$upArray['line_ip'] = Base::getIp();
|
||||
}
|
||||
if ($row->linedate + 30 < time()) {
|
||||
$upArray['linedate'] = time();
|
||||
if (Carbon::parse($row->line_at)->addSeconds(30)->lt(Carbon::now())) {
|
||||
$upArray['line_at'] = Carbon::now();
|
||||
}
|
||||
if ($upArray) {
|
||||
$row->updateInstance($upArray);
|
||||
@ -333,50 +330,14 @@ class User extends AbstractModel
|
||||
if (isset($_A["__static_userid2basic_" . $userid])) {
|
||||
return $_A["__static_userid2basic_" . $userid];
|
||||
}
|
||||
$fields = ['userid', 'email', 'nickname', 'userimg'];
|
||||
$fields = ['userid', 'email', 'nickname', 'userimg', 'line_at'];
|
||||
$userInfo = self::whereUserid($userid)->select($fields)->first();
|
||||
if ($userInfo) {
|
||||
$userInfo->line_at;
|
||||
}
|
||||
return $_A["__static_userid2basic_" . $userid] = ($userInfo ?: []);
|
||||
}
|
||||
|
||||
/**
|
||||
* email 获取 基本信息
|
||||
* @param string $email 邮箱地址
|
||||
* @return self
|
||||
*/
|
||||
public static function email2basic(string $email)
|
||||
{
|
||||
global $_A;
|
||||
if (empty($email)) {
|
||||
return null;
|
||||
}
|
||||
if (isset($_A["__static_email2basic_" . $email])) {
|
||||
return $_A["__static_email2basic_" . $email];
|
||||
}
|
||||
$fields = ['userid', 'email', 'nickname', 'userimg'];
|
||||
$userInfo = self::whereEmail($email)->select($fields)->first();
|
||||
return $_A["__static_email2basic_" . $email] = ($userInfo ?: []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户头像,不存在时返回默认
|
||||
* @param string $var 头像地址 或 会员邮箱
|
||||
* @return string
|
||||
*/
|
||||
public static function userimg(string $var)
|
||||
{
|
||||
if (!Base::strExists($var, '.')) {
|
||||
if (empty($var)) {
|
||||
$var = "";
|
||||
} else {
|
||||
$userInfo = self::email2basic($var);
|
||||
if ($userInfo) {
|
||||
$var = $userInfo->userimg;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $var ? Base::fillUrl($var) : url('images/other/avatar.png');
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新首字母
|
||||
* @param $userid
|
||||
|
3
resources/assets/js/app.js
vendored
3
resources/assets/js/app.js
vendored
@ -20,13 +20,14 @@ import Loading from './components/Loading.vue'
|
||||
import AutoTip from './components/AutoTip.vue'
|
||||
import TagInput from './components/TagInput.vue'
|
||||
import TableAction from './components/TableAction.vue'
|
||||
import UserAvatar from './components/UserAvatar.vue'
|
||||
|
||||
Vue.component('PageTitle', PageTitle);
|
||||
Vue.component('Loading', Loading);
|
||||
Vue.component('AutoTip', AutoTip);
|
||||
Vue.component('TagInput', TagInput)
|
||||
Vue.component('TableAction', TableAction);
|
||||
|
||||
Vue.component('UserAvatar', UserAvatar);
|
||||
|
||||
const originalPush = VueRouter.prototype.push
|
||||
VueRouter.prototype.push = function push(location) {
|
||||
|
76
resources/assets/js/components/UserAvatar.vue
Executable file
76
resources/assets/js/components/UserAvatar.vue
Executable file
@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<Tooltip v-if="user"
|
||||
:class="['common-avatar', user.online ? 'online' : '']"
|
||||
:delay="600"
|
||||
:transfer="transfer"
|
||||
:content="user.nickname">
|
||||
<Avatar v-if="showImg" :src="user.userimg" :size="size"/>
|
||||
<Avatar v-else :size="size" class="common-avatar-text">{{nickname}}</Avatar>
|
||||
</Tooltip>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UserAvatar',
|
||||
props: {
|
||||
userid: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: 'default'
|
||||
},
|
||||
transfer: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
user: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getData()
|
||||
},
|
||||
computed: {
|
||||
showImg() {
|
||||
const {userimg} = this.user
|
||||
if (!userimg) {
|
||||
return false;
|
||||
}
|
||||
return !$A.rightExists(userimg, '/avatar.png');
|
||||
},
|
||||
nickname() {
|
||||
const {nickname} = this.user;
|
||||
if (!nickname) {
|
||||
return "D";
|
||||
}
|
||||
let value = nickname.substring(0, 2);
|
||||
if (/^[\u4e00-\u9fa5]+$/.test(value)) {
|
||||
value = value.substring(0, 1);
|
||||
}
|
||||
return value || 'D';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
userid() {
|
||||
this.getData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
if (!this.userid) {
|
||||
return;
|
||||
}
|
||||
this.$store.commit('getUserBasic', {
|
||||
userid: this.userid,
|
||||
success: (user) => {
|
||||
this.user = user;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -2,13 +2,16 @@
|
||||
<div class="project-list">
|
||||
<div class="project-head">
|
||||
<div class="project-titbox">
|
||||
<div class="project-title">✔️ Daily Task</div>
|
||||
<div class="project-subtitle">Click + New To create new list and wait for project manager card Don't Create a card by yourself to manage a good colaboration.</div>
|
||||
<div class="project-title">
|
||||
<h1>{{projectDetail.name}}</h1>
|
||||
<div v-if="projectLoad > 0" class="project-load"><Loading/></div>
|
||||
</div>
|
||||
<div v-if="projectDetail.desc" class="project-subtitle">{{projectDetail.desc}}</div>
|
||||
</div>
|
||||
<div class="project-icobox">
|
||||
<ul class="project-icons">
|
||||
<li class="project-avatar online">
|
||||
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
|
||||
<li>
|
||||
<UserAvatar :userid="projectDetail.owner_userid" :size="36"/>
|
||||
</li>
|
||||
<li class="project-icon" @click="addShow=true">
|
||||
<Icon type="md-add" />
|
||||
@ -631,9 +634,22 @@
|
||||
flex: 1;
|
||||
margin-bottom: 16px;
|
||||
.project-title {
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> h1 {
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.project-load {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 18px;
|
||||
.common-loading {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.project-subtitle {
|
||||
color: #999999;
|
||||
@ -687,29 +703,6 @@
|
||||
background-color: #2d8cf0;
|
||||
}
|
||||
}
|
||||
&.project-avatar {
|
||||
.ivu-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
background-color: #ff0000;
|
||||
border: 1px solid #ffffff;
|
||||
z-index: 1;
|
||||
}
|
||||
&.online {
|
||||
&:before {
|
||||
background-color: #509E76;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.project-switch {
|
||||
@ -1015,6 +1008,7 @@
|
||||
<script>
|
||||
import TaskPriority from "./task-priority";
|
||||
import TaskAdd from "./task-add";
|
||||
import {mapState} from "vuex";
|
||||
export default {
|
||||
name: "ProjectList",
|
||||
components: {TaskAdd, TaskPriority},
|
||||
@ -1034,6 +1028,9 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['projectDetail', 'projectLoad']),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
13
resources/assets/js/store/mutations.js
vendored
13
resources/assets/js/store/mutations.js
vendored
@ -41,6 +41,13 @@ export default {
|
||||
if (state._isJson(state.cacheProject[project_id])) {
|
||||
state.projectDetail = state.cacheProject[project_id];
|
||||
}
|
||||
state.projectDetail.id = project_id;
|
||||
//
|
||||
if (state.cacheProject[project_id + "::load"]) {
|
||||
return;
|
||||
}
|
||||
state.cacheProject[project_id + "::load"] = true;
|
||||
//
|
||||
state.projectLoad++;
|
||||
$A.apiAjax({
|
||||
url: 'project/detail',
|
||||
@ -49,10 +56,14 @@ export default {
|
||||
},
|
||||
complete: () => {
|
||||
state.projectLoad--;
|
||||
state.cacheProject[project_id + "::load"] = false;
|
||||
},
|
||||
success: ({ret, data, msg}) => {
|
||||
if (ret === 1) {
|
||||
state.projectDetail = state.cacheProject[project_id] = data;
|
||||
state.cacheProject[project_id] = data;
|
||||
if (state.projectDetail.id == project_id) {
|
||||
state.projectDetail = data;
|
||||
}
|
||||
} else {
|
||||
$A.modalError(msg);
|
||||
}
|
||||
|
6
resources/assets/js/store/state.js
vendored
6
resources/assets/js/store/state.js
vendored
@ -174,7 +174,11 @@ export default Object.assign(stateCommon, {
|
||||
userToken,
|
||||
|
||||
projectLoad: 0,
|
||||
projectDetail: {},
|
||||
projectDetail: {
|
||||
id: 0,
|
||||
project_column: [],
|
||||
project_user: []
|
||||
},
|
||||
|
||||
cacheProject: {},
|
||||
cacheUserBasic: {},
|
||||
|
24
resources/assets/sass/main.scss
vendored
24
resources/assets/sass/main.scss
vendored
@ -412,6 +412,30 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.common-avatar {
|
||||
.common-avatar-text {
|
||||
background-color: #87d068;
|
||||
}
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
background-color: #ff0000;
|
||||
border: 1px solid #ffffff;
|
||||
z-index: 1;
|
||||
}
|
||||
&.online {
|
||||
&:before {
|
||||
background-color: #509E76;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.common-user-transfer {
|
||||
.user-input-option {
|
||||
display: flex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user