no message

This commit is contained in:
kuaifan 2021-06-02 19:40:33 +08:00
parent e5e7d2d052
commit b24d1f79fa
9 changed files with 197 additions and 109 deletions

View File

@ -18,6 +18,14 @@ use Request;
*/ */
class ProjectController extends AbstractController 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']); $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) ->where('project_users.userid', $user->userid)
->orderByDesc('projects.id') ->orderByDesc('projects.id')
->paginate(Base::getPaginate(200, 100)); ->paginate(Base::getPaginate(200, 100));
@ -62,10 +71,15 @@ class ProjectController extends AbstractController
$taskQuery->where('parent_id', 0); $taskQuery->where('parent_id', 0);
}]); }]);
}, 'projectUser']) }, 'projectUser'])
->select($this->projectSelect)
->join('project_users', 'projects.id', '=', 'project_users.project_id') ->join('project_users', 'projects.id', '=', 'project_users.project_id')
->where('projects.id', $project_id) ->where('projects.id', $project_id)
->where('project_users.userid', $user->userid) ->where('project_users.userid', $user->userid)
->first(); ->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); return Base::retSuccess('success', $project);
} }

View File

@ -6,6 +6,7 @@ use App\Models\User;
use App\Module\Base; use App\Module\Base;
use Cache; use Cache;
use Captcha; use Captcha;
use Carbon\Carbon;
use Request; use Request;
/** /**
@ -87,11 +88,11 @@ class UsersController extends AbstractController
} }
// //
$array = [ $array = [
'loginnum' => $user['loginnum'] + 1, 'login_num' => $user->login_num + 1,
'lastip' => Base::getIp(), 'last_ip' => Base::getIp(),
'lastdate' => time(), 'last_at' => Carbon::now(),
'lineip' => Base::getIp(), 'line_ip' => Base::getIp(),
'linedate' => time(), 'line_at' => Carbon::now(),
]; ];
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
$user->$key = $value; $user->$key = $value;
@ -159,14 +160,13 @@ class UsersController extends AbstractController
"email": "admin@admin.com", "email": "admin@admin.com",
"nickname": "admin", "nickname": "admin",
"userimg": "", "userimg": "",
"loginnum": 10, "login_num": 10,
"changepass": 0, "changepass": 0,
"lastip": "10.22.22.1", "last_ip": "10.22.22.1",
"lastdate": 1622468661, "last_at": "2021-06-01 12:00:00",
"lineip": "10.22.22.1", "line_ip": "10.22.22.1",
"linedate": 1622468661, "line_at": "2021-06-01 12:00:00",
"regip": "", "created_ip": "",
"regdate": 0,
} }
*/ */
public function info() public function info()

View File

@ -5,6 +5,7 @@ namespace App\Models;
use App\Module\Base; use App\Module\Base;
use Cache; use Cache;
use Carbon\Carbon;
/** /**
* Class User * Class User
@ -18,14 +19,13 @@ use Cache;
* @property string|null $userimg 头像 * @property string|null $userimg 头像
* @property string|null $encrypt * @property string|null $encrypt
* @property string|null $userpass 登录密码 * @property string|null $userpass 登录密码
* @property int|null $loginnum 累计登录次数 * @property int|null $login_num 累计登录次数
* @property int|null $changepass 登录需要修改密码 * @property int|null $changepass 登录需要修改密码
* @property string|null $lastip 最后登录IP * @property string|null $last_ip 最后登录IP
* @property int|null $lastdate 最后登录时间 * @property \Illuminate\Support\Carbon|null $last_at 最后登录时间
* @property string|null $lineip 最后在线IP接口 * @property string|null $line_ip 最后在线IP接口
* @property int|null $linedate 最后在线时间(接口) * @property \Illuminate\Support\Carbon|null $line_at 最后在线时间(接口)
* @property string|null $regip 注册IP * @property string|null $created_ip 注册IP
* @property int|null $regdate 注册时间
* @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at * @property \Illuminate\Support\Carbon|null $updated_at
* @property-read string $usering * @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 whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereEncrypt($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 whereIdentity($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereLastdate($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 whereLastIp($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereLinedate($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 whereLineIp($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereLoginnum($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 whereNickname($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereRegdate($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedIp($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereRegip($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($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 whereUserid($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereUserimg($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereUserimg($value)
@ -59,7 +58,6 @@ class User extends AbstractModel
protected $hidden = [ protected $hidden = [
'encrypt', 'encrypt',
'userpass', 'userpass',
'created_at',
'updated_at', 'updated_at',
]; ];
@ -80,7 +78,7 @@ class User extends AbstractModel
*/ */
public function getUserimgAttribute($value) 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, 'encrypt' => $encrypt,
'email' => $email, 'email' => $email,
'userpass' => Base::md52($userpass, $encrypt), 'userpass' => Base::md52($userpass, $encrypt),
'regip' => Base::getIp(), 'created_ip' => Base::getIp(),
'regdate' => time()
]; ];
if ($other) { if ($other) {
$inArray = array_merge($inArray, $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(); $row = self::whereUserid($authInfo['userid'])->whereEmail($authInfo['email'])->whereEncrypt($authInfo['encrypt'])->first();
if ($row) { if ($row) {
$upArray = []; $upArray = [];
if (Base::getIp() && $row->lineip != Base::getIp()) { if (Base::getIp() && $row->line_ip != Base::getIp()) {
$upArray['lineip'] = Base::getIp(); $upArray['line_ip'] = Base::getIp();
} }
if ($row->linedate + 30 < time()) { if (Carbon::parse($row->line_at)->addSeconds(30)->lt(Carbon::now())) {
$upArray['linedate'] = time(); $upArray['line_at'] = Carbon::now();
} }
if ($upArray) { if ($upArray) {
$row->updateInstance($upArray); $row->updateInstance($upArray);
@ -333,48 +330,12 @@ class User extends AbstractModel
if (isset($_A["__static_userid2basic_" . $userid])) { if (isset($_A["__static_userid2basic_" . $userid])) {
return $_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(); $userInfo = self::whereUserid($userid)->select($fields)->first();
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) { if ($userInfo) {
$var = $userInfo->userimg; $userInfo->line_at;
} }
} return $_A["__static_userid2basic_" . $userid] = ($userInfo ?: []);
}
return $var ? Base::fillUrl($var) : url('images/other/avatar.png');
} }
/** /**

View File

@ -20,13 +20,14 @@ import Loading from './components/Loading.vue'
import AutoTip from './components/AutoTip.vue' import AutoTip from './components/AutoTip.vue'
import TagInput from './components/TagInput.vue' import TagInput from './components/TagInput.vue'
import TableAction from './components/TableAction.vue' import TableAction from './components/TableAction.vue'
import UserAvatar from './components/UserAvatar.vue'
Vue.component('PageTitle', PageTitle); Vue.component('PageTitle', PageTitle);
Vue.component('Loading', Loading); Vue.component('Loading', Loading);
Vue.component('AutoTip', AutoTip); Vue.component('AutoTip', AutoTip);
Vue.component('TagInput', TagInput) Vue.component('TagInput', TagInput)
Vue.component('TableAction', TableAction); Vue.component('TableAction', TableAction);
Vue.component('UserAvatar', UserAvatar);
const originalPush = VueRouter.prototype.push const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) { VueRouter.prototype.push = function push(location) {

View 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>

View File

@ -2,13 +2,16 @@
<div class="project-list"> <div class="project-list">
<div class="project-head"> <div class="project-head">
<div class="project-titbox"> <div class="project-titbox">
<div class="project-title"> Daily Task</div> <div class="project-title">
<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> <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>
<div class="project-icobox"> <div class="project-icobox">
<ul class="project-icons"> <ul class="project-icons">
<li class="project-avatar online"> <li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /> <UserAvatar :userid="projectDetail.owner_userid" :size="36"/>
</li> </li>
<li class="project-icon" @click="addShow=true"> <li class="project-icon" @click="addShow=true">
<Icon type="md-add" /> <Icon type="md-add" />
@ -631,10 +634,23 @@
flex: 1; flex: 1;
margin-bottom: 16px; margin-bottom: 16px;
.project-title { .project-title {
display: flex;
align-items: center;
> h1 {
color: #333333; color: #333333;
font-size: 28px; font-size: 28px;
font-weight: 600; font-weight: 600;
} }
.project-load {
display: flex;
align-items: center;
margin-left: 18px;
.common-loading {
width: 22px;
height: 22px;
}
}
}
.project-subtitle { .project-subtitle {
color: #999999; color: #999999;
margin-top: 18px; margin-top: 18px;
@ -687,29 +703,6 @@
background-color: #2d8cf0; 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 { .project-switch {
@ -1015,6 +1008,7 @@
<script> <script>
import TaskPriority from "./task-priority"; import TaskPriority from "./task-priority";
import TaskAdd from "./task-add"; import TaskAdd from "./task-add";
import {mapState} from "vuex";
export default { export default {
name: "ProjectList", name: "ProjectList",
components: {TaskAdd, TaskPriority}, components: {TaskAdd, TaskPriority},
@ -1034,6 +1028,9 @@ export default {
}, },
mounted() { mounted() {
} },
computed: {
...mapState(['projectDetail', 'projectLoad']),
},
} }
</script> </script>

View File

@ -41,6 +41,13 @@ export default {
if (state._isJson(state.cacheProject[project_id])) { if (state._isJson(state.cacheProject[project_id])) {
state.projectDetail = 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++; state.projectLoad++;
$A.apiAjax({ $A.apiAjax({
url: 'project/detail', url: 'project/detail',
@ -49,10 +56,14 @@ export default {
}, },
complete: () => { complete: () => {
state.projectLoad--; state.projectLoad--;
state.cacheProject[project_id + "::load"] = false;
}, },
success: ({ret, data, msg}) => { success: ({ret, data, msg}) => {
if (ret === 1) { 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 { } else {
$A.modalError(msg); $A.modalError(msg);
} }

View File

@ -174,7 +174,11 @@ export default Object.assign(stateCommon, {
userToken, userToken,
projectLoad: 0, projectLoad: 0,
projectDetail: {}, projectDetail: {
id: 0,
project_column: [],
project_user: []
},
cacheProject: {}, cacheProject: {},
cacheUserBasic: {}, cacheUserBasic: {},

View File

@ -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 { .common-user-transfer {
.user-input-option { .user-input-option {
display: flex; display: flex;