feat: 【工作报告】功能
This commit is contained in:
parent
3602acd187
commit
d48ed18102
379
app/Http/Controllers/Api/ReportController.php
Executable file
379
app/Http/Controllers/Api/ReportController.php
Executable file
@ -0,0 +1,379 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Exceptions\ApiException;
|
||||||
|
use App\Models\ProjectTask;
|
||||||
|
use App\Models\Report;
|
||||||
|
use App\Models\ReportReceive;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Module\Base;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Request;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @apiDefine report
|
||||||
|
*
|
||||||
|
* 汇报
|
||||||
|
*/
|
||||||
|
class ReportController extends AbstractController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @api {get} api/report/my 01. 我发送的汇报
|
||||||
|
*
|
||||||
|
* @apiVersion 1.0.0
|
||||||
|
* @apiGroup report
|
||||||
|
* @apiName my
|
||||||
|
*
|
||||||
|
* @apiParam {Number} [user] 会员ID
|
||||||
|
* @apiParam {String} [type] 汇报类型,weekly:周报,daily:日报
|
||||||
|
* @apiParam {Number} [page] 当前页,默认:1
|
||||||
|
* @apiParam {Number} [pagesize] 每页显示数量,默认:20,最大:50
|
||||||
|
*
|
||||||
|
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||||
|
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||||
|
* @apiSuccess {Object} data 返回数据
|
||||||
|
*/
|
||||||
|
public function my(): array
|
||||||
|
{
|
||||||
|
$user = User::auth();
|
||||||
|
// 搜索当前用户
|
||||||
|
$builder = Report::query()->whereUserid($user->userid);
|
||||||
|
$type = trim(Request::input('type'));
|
||||||
|
$createAt = Request::input('created_at');
|
||||||
|
in_array($type, [Report::WEEKLY, Report::DAILY]) && $builder->whereType($type);
|
||||||
|
$whereArray = [];
|
||||||
|
if (is_array($createAt)) {
|
||||||
|
if ($createAt[0] > 0) $whereArray[] = ['created_at', '>=', date('Y-m-d H:i:s', Base::dayTimeF($createAt[0]))];
|
||||||
|
if ($createAt[1] > 0) $whereArray[] = ['created_at', '<=', date('Y-m-d H:i:s', Base::dayTimeE($createAt[1]))];
|
||||||
|
}
|
||||||
|
$list = $builder->where($whereArray)->orderByDesc('created_at')->paginate(Base::getPaginate(50, 20));
|
||||||
|
if ($list->items()) {
|
||||||
|
foreach ($list->items() as $item) {
|
||||||
|
$item->receivesUser;
|
||||||
|
$item->receives = empty($item->receivesUser) ? [] : array_column($item->receivesUser->toArray(), "userid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Base::retSuccess('success', $list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我接收的汇报
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function receive(): array
|
||||||
|
{
|
||||||
|
$user = User::auth();
|
||||||
|
$builder = Report::query();
|
||||||
|
$builder->whereHas("receivesUser", function ($query) use ($user) {
|
||||||
|
$query->where("report_receives.userid", $user->userid);
|
||||||
|
});
|
||||||
|
$type = trim(Request::input('type'));
|
||||||
|
$createAt = Request::input('created_at');
|
||||||
|
$username = trim(Request::input('username', ''));
|
||||||
|
$builder->whereHas('sendUser', function ($query) use ($username) {
|
||||||
|
if (!empty($username)) {
|
||||||
|
$query->where('users.email', 'LIKE', '%' . $username . '%');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
in_array($type, [Report::WEEKLY, Report::DAILY]) && $builder->whereType($type);
|
||||||
|
$whereArray = [];
|
||||||
|
if (is_array($createAt)) {
|
||||||
|
if ($createAt[0] > 0) $whereArray[] = ['created_at', '>=', date('Y-m-d H:i:s', Base::dayTimeF($createAt[0]))];
|
||||||
|
if ($createAt[1] > 0) $whereArray[] = ['created_at', '<=', date('Y-m-d H:i:s', Base::dayTimeE($createAt[1]))];
|
||||||
|
}
|
||||||
|
$list = $builder->where($whereArray)->orderByDesc('created_at')->paginate(Base::getPaginate(50, 20));
|
||||||
|
if ($list->items()) {
|
||||||
|
foreach ($list->items() as $item) {
|
||||||
|
$item["receive_time"] = ReportReceive::query()->whereRid($item["id"])->whereUserid($user->userid)->value("receive_time");
|
||||||
|
$item->receivesUser;
|
||||||
|
$item->receives = empty($item->receivesUser) ? [] : array_column($item->receivesUser->toArray(), "userid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Base::retSuccess('success', $list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存并发送工作汇报
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function store(): array
|
||||||
|
{
|
||||||
|
$input = [
|
||||||
|
"id" => Base::getPostValue("id", 0),
|
||||||
|
"title" => Base::getPostValue("title"),
|
||||||
|
"type" => Base::getPostValue("type"),
|
||||||
|
"content" => Base::getPostValue("content"),
|
||||||
|
"receive" => Base::getPostValue("receive"),
|
||||||
|
// 以当前日期为基础的周期偏移量。例如选择了上一周那么就是 -1,上一天同理。
|
||||||
|
"offset" => Base::getPostValue("offset", 0),
|
||||||
|
];
|
||||||
|
$validator = Validator::make($input, [
|
||||||
|
'id' => 'numeric',
|
||||||
|
'title' => 'required',
|
||||||
|
'type' => ['required', Rule::in([Report::WEEKLY, Report::DAILY])],
|
||||||
|
'content' => 'required',
|
||||||
|
'receive' => 'required',
|
||||||
|
'offset' => ['numeric', 'max:0'],
|
||||||
|
], [
|
||||||
|
'id.numeric' => 'ID只能是数字',
|
||||||
|
'title.required' => '请填写标题',
|
||||||
|
'type.required' => '请选择汇报类型',
|
||||||
|
'type.in' => '汇报类型错误',
|
||||||
|
'content.required' => '请填写汇报内容',
|
||||||
|
'receive.required' => '请选择接收人',
|
||||||
|
'offset.numeric' => '工作汇报周期格式错误,只能是数字',
|
||||||
|
'offset.max' => '只能提交当天/本周或者之前的的工作汇报',
|
||||||
|
]);
|
||||||
|
if ($validator->fails())
|
||||||
|
return Base::retError($validator->errors()->first());
|
||||||
|
|
||||||
|
$user = User::auth();
|
||||||
|
// 接收人
|
||||||
|
if ( is_array($input["receive"]) ) {
|
||||||
|
// 删除当前登录人
|
||||||
|
$input["receive"] = array_diff($input["receive"], [$user->userid]);
|
||||||
|
|
||||||
|
// 查询用户是否存在
|
||||||
|
if ( count($input["receive"]) !== User::whereIn("userid", $input["receive"])->count() )
|
||||||
|
return Base::retError("用户不存在");
|
||||||
|
|
||||||
|
foreach ($input["receive"] as $userid) {
|
||||||
|
$input["receive_content"][] = [
|
||||||
|
"receive_time" => Carbon::now()->toDateTimeString(),
|
||||||
|
"userid" => $userid,
|
||||||
|
"read" => 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在事务中运行
|
||||||
|
Report::transaction( function () use ($input, $user) {
|
||||||
|
$id = $input["id"];
|
||||||
|
if ($id) {
|
||||||
|
// 编辑
|
||||||
|
$report = Report::getOne($id);
|
||||||
|
$report->updateInstance([
|
||||||
|
"title" => $input["title"],
|
||||||
|
"type" => $input["type"],
|
||||||
|
"content" => htmlspecialchars($input["content"]),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
// 生成唯一标识
|
||||||
|
$sign = Report::generateSign($input["type"], $input["offset"]);
|
||||||
|
// 检查唯一标识是否存在
|
||||||
|
if (empty($input["id"])) {
|
||||||
|
if (Report::query()->whereSign($sign)->count() > 0)
|
||||||
|
throw new ApiException("请勿重复提交工作汇报");
|
||||||
|
}
|
||||||
|
$report = Report::createInstance([
|
||||||
|
"title" => $input["title"],
|
||||||
|
"type" => $input["type"],
|
||||||
|
"content" => htmlspecialchars($input["content"]),
|
||||||
|
"userid" => $user->userid,
|
||||||
|
"sign" => $sign,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$report->save();
|
||||||
|
if (!empty($input["receive_content"])) {
|
||||||
|
// 删除关联
|
||||||
|
$report->Receives()->delete();
|
||||||
|
// 保存接收人
|
||||||
|
$report->Receives()->createMany($input["receive_content"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
return Base::retSuccess('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成汇报模板
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function template(): array
|
||||||
|
{
|
||||||
|
$user = User::auth();
|
||||||
|
$type = trim( Request::input("type") );
|
||||||
|
$offset = abs( intval( Request::input("offset", 0) ) );
|
||||||
|
$now_dt = trim( Request::input("date") ) ? Carbon::parse( Request::input("date") ) : Carbon::now();
|
||||||
|
// 获取开始时间
|
||||||
|
if ($type === Report::DAILY) {
|
||||||
|
$start_time = Carbon::today();
|
||||||
|
if ( $offset > 0 ) {
|
||||||
|
// 将当前时间调整为偏移量当天结束
|
||||||
|
$now_dt->subDays( $offset )->endOfDay();
|
||||||
|
// 开始时间偏移量计算
|
||||||
|
$start_time->subDays( $offset );
|
||||||
|
}
|
||||||
|
$end_time = Carbon::instance($start_time)->endOfDay();
|
||||||
|
} else {
|
||||||
|
$start_time = Carbon::now();
|
||||||
|
if ( $offset > 0 ) {
|
||||||
|
// 将当前时间调整为偏移量当周结束
|
||||||
|
$now_dt->subWeeks( $offset )->endOfDay();
|
||||||
|
// 开始时间偏移量计算
|
||||||
|
$start_time->subWeeks( $offset );
|
||||||
|
}
|
||||||
|
$start_time->startOfWeek();
|
||||||
|
$end_time = Carbon::instance($start_time)->endOfWeek();
|
||||||
|
}
|
||||||
|
// 生成唯一标识
|
||||||
|
$sign = Report::generateSign($type, 0, Carbon::instance($start_time));
|
||||||
|
$one = Report::query()->whereSign($sign)->first();
|
||||||
|
// 如果已经提交了相关汇报
|
||||||
|
if ($one) {
|
||||||
|
return Base::retSuccess('success', [
|
||||||
|
"content" => $one->content,
|
||||||
|
"title" => $one->title,
|
||||||
|
"id" => $one->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 已完成的任务
|
||||||
|
$completeContent = "";
|
||||||
|
$complete_task = ProjectTask::query()
|
||||||
|
->whereNotNull("complete_at")
|
||||||
|
->whereBetween("complete_at", [$start_time->toDateTimeString(), $end_time->toDateTimeString()])
|
||||||
|
->whereHas("taskUser", function ($query) use ($user) {
|
||||||
|
$query->where("userid", $user->userid);
|
||||||
|
})
|
||||||
|
->orderByDesc("id")
|
||||||
|
->get();
|
||||||
|
if ($complete_task->isNotEmpty()) {
|
||||||
|
foreach ($complete_task as $task) {
|
||||||
|
$complete_at = Carbon::parse($task->complete_at);
|
||||||
|
$pre = $type == Report::WEEKLY ? ('<span>[' . Base::Lang('周' . ['日', '一', '二', '三', '四', '五', '六'][$complete_at->dayOfWeek]) . ']</span> ') : '';
|
||||||
|
$completeContent .= '<li>' . $pre . $task->name . '</li>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$completeContent = '<li> </li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 未完成的任务
|
||||||
|
$unfinishedContent = "";
|
||||||
|
$unfinished_task = ProjectTask::query()
|
||||||
|
->whereNull("complete_at")
|
||||||
|
->whereNotNull("start_at")
|
||||||
|
->where("end_at", "<", $end_time->toDateTimeString())
|
||||||
|
->whereHas("taskUser", function ($query) use ($user) {
|
||||||
|
$query->where("userid", $user->userid);
|
||||||
|
})
|
||||||
|
->orderByDesc("id")
|
||||||
|
->get();
|
||||||
|
if ($unfinished_task->isNotEmpty()) {
|
||||||
|
foreach ($unfinished_task as $task) {
|
||||||
|
empty($task->end_at) || $end_at = Carbon::parse($task->end_at);
|
||||||
|
$pre = ( !empty( $end_at ) && $end_at->lt($now_dt) ) ? '<span style="color:#ff0000;">[' . Base::Lang('超期') . ']</span> ' : '';
|
||||||
|
$unfinishedContent .= '<li>' . $pre . $task->name . '</li>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$unfinishedContent = '<li> </li>';
|
||||||
|
}
|
||||||
|
// 生成标题
|
||||||
|
if ( $type === Report::WEEKLY ) {
|
||||||
|
$title = $user->nickname . "的周报[" . $start_time->format("m/d") . "-" . $end_time->format("m/d") . "]";
|
||||||
|
$title .= "[" . $start_time->month . "月第" . $start_time->weekOfMonth . "周]";
|
||||||
|
} else {
|
||||||
|
$title = $user->nickname . "的日报[" . $start_time->format("Y/m/d") . "]";
|
||||||
|
}
|
||||||
|
return Base::retSuccess('success', [
|
||||||
|
"time" => $start_time->toDateTimeString(),
|
||||||
|
"complete_task" => $complete_task,
|
||||||
|
"unfinished_task" => $unfinished_task,
|
||||||
|
"content" => '<h2>' . Base::Lang('已完成工作') . '</h2><ol>' .
|
||||||
|
$completeContent . '</ol><h2>' .
|
||||||
|
Base::Lang('未完成的工作') . '</h2><ol>' .
|
||||||
|
$unfinishedContent . '</ol>',
|
||||||
|
"title" => $title,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function detail(): array
|
||||||
|
{
|
||||||
|
$id = intval( trim( Request::input("id") ) );
|
||||||
|
if (empty( $id ))
|
||||||
|
return Base::retError("缺少ID参数");
|
||||||
|
|
||||||
|
$one = Report::getOne($id);
|
||||||
|
$one["type_val"] = $one->getRawOriginal("type");
|
||||||
|
|
||||||
|
$user = User::auth();
|
||||||
|
// 标记为已读
|
||||||
|
if ( !empty( $one->receivesUser ) ) {
|
||||||
|
foreach ($one->receivesUser as $item) {
|
||||||
|
if ($item->userid === $user->userid && $item->pivot->read === 0) {
|
||||||
|
$one->receivesUser()->updateExistingPivot($user->userid, [
|
||||||
|
"read" => 1,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Base::retSuccess("success", $one);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取最后一次提交的接收人
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function last_submitter(): array
|
||||||
|
{
|
||||||
|
$one = Report::getLastOne();
|
||||||
|
return Base::retSuccess("success", empty( $one["receives"] ) ? [] : $one["receives"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取未读
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function unread(): array
|
||||||
|
{
|
||||||
|
$userid = intval( trim( Request::input("userid") ) );
|
||||||
|
$user = empty($userid) ? User::auth() : User::find($userid);
|
||||||
|
|
||||||
|
$data = Report::whereHas("Receives", function (Builder $query) use ($user) {
|
||||||
|
$query->where("userid", $user->userid)->where("read", 0);
|
||||||
|
})->orderByDesc('created_at')->paginate(Base::getPaginate(50, 20));
|
||||||
|
return Base::retSuccess("success", $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记汇报已读,可批量
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function read(): array
|
||||||
|
{
|
||||||
|
$user = User::auth();
|
||||||
|
$ids = Request::input("ids");
|
||||||
|
if ( !is_array($ids) && !is_string($ids) ) {
|
||||||
|
return Base::retError("请传入正确的工作汇报Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_string($ids) ) {
|
||||||
|
$ids = explode(",", $ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = Report::with(["receivesUser" => function (BelongsToMany $query) use ($user) {
|
||||||
|
$query->where("report_receives.userid", $user->userid)->where("read", 0);
|
||||||
|
}])->whereIn("id", $ids)->get();
|
||||||
|
|
||||||
|
if ( $data->isNotEmpty() ) {
|
||||||
|
foreach ($data as $item) {
|
||||||
|
(!empty($item->receivesUser) && $item->receivesUser->isNotEmpty()) && $item->receivesUser()->updateExistingPivot($user->userid, [
|
||||||
|
"read" => 1,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Base::retSuccess("success", $data);
|
||||||
|
}
|
||||||
|
}
|
@ -44,5 +44,8 @@ class VerifyCsrfToken extends Middleware
|
|||||||
|
|
||||||
// 保存文件内容(上传)
|
// 保存文件内容(上传)
|
||||||
'api/file/content/upload/',
|
'api/file/content/upload/',
|
||||||
|
|
||||||
|
// 保存汇报
|
||||||
|
'api/report/store/',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
156
app/Models/Report.php
Normal file
156
app/Models/Report.php
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Exceptions\ApiException;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Carbon\Traits\Creator;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use JetBrains\PhpStorm\Pure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App\Models\Report
|
||||||
|
*
|
||||||
|
* @property int $id
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property string $title 标题
|
||||||
|
* @property string $type 汇报类型
|
||||||
|
* @property int $userid
|
||||||
|
* @property string|null $content
|
||||||
|
* @method static Builder|Report newModelQuery()
|
||||||
|
* @method static Builder|Report newQuery()
|
||||||
|
* @method static Builder|Report query()
|
||||||
|
* @method static Builder|Report whereContent($value)
|
||||||
|
* @method static Builder|Report whereCreatedAt($value)
|
||||||
|
* @method static Builder|Report whereId($value)
|
||||||
|
* @method static Builder|Report whereTitle($value)
|
||||||
|
* @method static Builder|Report whereType($value)
|
||||||
|
* @method static Builder|Report whereUpdatedAt($value)
|
||||||
|
* @method static Builder|Report whereUserid($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
* @property string $sign 汇报唯一标识
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ReportReceive[] $Receives
|
||||||
|
* @property-read int|null $receives_count
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\User[] $receivesUser
|
||||||
|
* @property-read int|null $receives_user_count
|
||||||
|
* @method static Builder|Report whereSign($value)
|
||||||
|
*/
|
||||||
|
class Report extends AbstractModel
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
const WEEKLY = "weekly";
|
||||||
|
const DAILY = "daily";
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
"title",
|
||||||
|
"type",
|
||||||
|
"userid",
|
||||||
|
"content",
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $appends = [
|
||||||
|
'receives',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function Receives(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ReportReceive::class, "rid");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function receivesUser(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(User::class, ReportReceive::class, "rid", "userid")
|
||||||
|
->withPivot("receive_time", "read");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendUser()
|
||||||
|
{
|
||||||
|
return $this->hasOne(User::class, "userid", "userid");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTypeAttribute($value): string
|
||||||
|
{
|
||||||
|
return match ($value) {
|
||||||
|
Report::WEEKLY => "周报",
|
||||||
|
Report::DAILY => "日报",
|
||||||
|
default => "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getContentAttribute($value): string
|
||||||
|
{
|
||||||
|
return htmlspecialchars_decode($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getReceivesAttribute()
|
||||||
|
{
|
||||||
|
if (!isset($this->appendattrs['receives'])) {
|
||||||
|
$this->appendattrs['receives'] = empty( $this->receivesUser ) ? [] : array_column($this->receivesUser->toArray(), "userid");
|
||||||
|
}
|
||||||
|
return $this->appendattrs['receives'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单条记录
|
||||||
|
* @param $id
|
||||||
|
* @param User|null $user
|
||||||
|
* @return Report|Builder|Model|object|null
|
||||||
|
* @throw ApiException
|
||||||
|
*/
|
||||||
|
public static function getOne($id, User $user = null)
|
||||||
|
{
|
||||||
|
$user === null && $user = User::auth();
|
||||||
|
$one = self::whereUserid($user->userid)->whereId($id)->first();
|
||||||
|
if ( empty($one) )
|
||||||
|
throw new ApiException("记录不存在");
|
||||||
|
return $one;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取最后一条提交记录
|
||||||
|
* @param User|null $user
|
||||||
|
* @return Builder|Model|\Illuminate\Database\Query\Builder|object
|
||||||
|
*/
|
||||||
|
public static function getLastOne(User $user = null)
|
||||||
|
{
|
||||||
|
$user === null && $user = User::auth();
|
||||||
|
$one = self::whereUserid($user->userid)->orderByDesc("created_at")->first();
|
||||||
|
if ( empty($one) )
|
||||||
|
throw new ApiException("记录不存在");
|
||||||
|
return $one;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成唯一标识
|
||||||
|
* @param $type
|
||||||
|
* @param $offset
|
||||||
|
* @param Carbon|null $time
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function generateSign($type, $offset, Carbon $time = null): string
|
||||||
|
{
|
||||||
|
$user = User::auth();
|
||||||
|
$now_dt = $time === null ? Carbon::now() : $time;
|
||||||
|
$time_s = match ($type) {
|
||||||
|
Report::WEEKLY => function() use ($now_dt, $offset) {
|
||||||
|
// 如果设置了周期偏移量
|
||||||
|
empty( $offset ) || $now_dt->subWeeks( abs( $offset ) );
|
||||||
|
$now_dt->startOfWeek(); // 设置为当周第一天
|
||||||
|
return $now_dt->year . $now_dt->weekOfYear . $now_dt->month . $now_dt->weekOfMonth;
|
||||||
|
},
|
||||||
|
Report::DAILY => function() use ($now_dt, $offset) {
|
||||||
|
// 如果设置了周期偏移量
|
||||||
|
empty( $offset ) || $now_dt->subDays( abs( $offset ) );
|
||||||
|
return $now_dt->year . $now_dt->dayOfYear . $now_dt->month . $now_dt->daysInMonth;
|
||||||
|
},
|
||||||
|
default => "",
|
||||||
|
};
|
||||||
|
return md5( $user->userid . ( is_callable($time_s) ? $time_s() : "" ) . $type );
|
||||||
|
}
|
||||||
|
}
|
39
app/Models/ReportReceive.php
Normal file
39
app/Models/ReportReceive.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App\Models\ReportReceive
|
||||||
|
*
|
||||||
|
* @property int $id
|
||||||
|
* @property int $rid
|
||||||
|
* @property string|null $receive_time 接收时间
|
||||||
|
* @property int $userid 接收人
|
||||||
|
* @property int $read 是否已读
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive whereRead($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive whereReceiveTime($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive whereRid($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|ReportReceive whereUserid($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class ReportReceive extends AbstractModel
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
// 关闭时间戳自动写入
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
"rid",
|
||||||
|
"receive_time",
|
||||||
|
"userid",
|
||||||
|
"read",
|
||||||
|
];
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateReportsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if ( Schema::hasTable('reports') )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Schema::create('reports', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
$table->string("title")->default("")->comment("标题");
|
||||||
|
$table->enum("type", ["weekly", "daily"])->default("daily")->comment("汇报类型");
|
||||||
|
$table->unsignedBigInteger("userid")->default(0);
|
||||||
|
$table->longText("content")->nullable();
|
||||||
|
$table->index(["userid", "created_at"], "default");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('reports');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateReportReceivesTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if ( Schema::hasTable('report_receives') )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Schema::create('report_receives', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements("id");
|
||||||
|
$table->unsignedInteger("rid")->default(0);
|
||||||
|
$table->timestamp("receive_time")->nullable()->comment("接收时间");
|
||||||
|
$table->unsignedBigInteger("userid")->default(0)->comment("接收人");
|
||||||
|
$table->unsignedTinyInteger("read")->default(0)->comment("是否已读");
|
||||||
|
$table->index(["userid", "receive_time"], "default");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('report_receives');
|
||||||
|
}
|
||||||
|
}
|
32
database/migrations/2022_01_04_111739_add_report_sign.php
Normal file
32
database/migrations/2022_01_04_111739_add_report_sign.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddReportSign extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('reports', function (Blueprint $table) {
|
||||||
|
$table->string("sign")->default("")->comment("汇报唯一标识");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('reports', function (Blueprint $table) {
|
||||||
|
$table->dropColumn("sign");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,10 @@
|
|||||||
v-for="(item, key) in menu"
|
v-for="(item, key) in menu"
|
||||||
:key="key"
|
:key="key"
|
||||||
:divided="!!item.divided"
|
:divided="!!item.divided"
|
||||||
:name="item.path">{{$L(item.name)}}</DropdownItem>
|
:name="item.path">
|
||||||
|
{{$L(item.name)}}
|
||||||
|
<Badge v-if="item.path === 'workReport'" :count="reportUnreadNumber"/>
|
||||||
|
</DropdownItem>
|
||||||
<Dropdown placement="right-start" @on-click="setLanguage">
|
<Dropdown placement="right-start" @on-click="setLanguage">
|
||||||
<DropdownItem divided>
|
<DropdownItem divided>
|
||||||
<div class="manage-menu-language">
|
<div class="manage-menu-language">
|
||||||
@ -160,6 +163,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<!--工作报告-->
|
||||||
|
<DrawerOverlay
|
||||||
|
v-model="workReportShow"
|
||||||
|
placement="right"
|
||||||
|
:size="900">
|
||||||
|
<Report v-if="workReportShow" @read="reportUnread" />
|
||||||
|
</DrawerOverlay>
|
||||||
|
|
||||||
<!--查看所有团队-->
|
<!--查看所有团队-->
|
||||||
<DrawerOverlay
|
<DrawerOverlay
|
||||||
v-model="allUserShow"
|
v-model="allUserShow"
|
||||||
@ -206,11 +217,13 @@ import ProjectManagement from "./manage/components/ProjectManagement";
|
|||||||
import DrawerOverlay from "../components/DrawerOverlay";
|
import DrawerOverlay from "../components/DrawerOverlay";
|
||||||
import DragBallComponent from "../components/DragBallComponent";
|
import DragBallComponent from "../components/DragBallComponent";
|
||||||
import TaskAdd from "./manage/components/TaskAdd";
|
import TaskAdd from "./manage/components/TaskAdd";
|
||||||
|
import Report from "./manage/components/Report";
|
||||||
import {Store} from "le5le-store";
|
import {Store} from "le5le-store";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
TaskAdd,
|
TaskAdd,
|
||||||
|
Report,
|
||||||
DragBallComponent, DrawerOverlay, ProjectManagement, TeamManagement, ProjectArchived, TaskDetail},
|
DragBallComponent, DrawerOverlay, ProjectManagement, TeamManagement, ProjectArchived, TaskDetail},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -242,6 +255,7 @@ export default {
|
|||||||
show768Menu: false,
|
show768Menu: false,
|
||||||
innerHeight: window.innerHeight,
|
innerHeight: window.innerHeight,
|
||||||
|
|
||||||
|
workReportShow: false,
|
||||||
allUserShow: false,
|
allUserShow: false,
|
||||||
allProjectShow: false,
|
allProjectShow: false,
|
||||||
archivedProjectShow: false,
|
archivedProjectShow: false,
|
||||||
@ -249,6 +263,7 @@ export default {
|
|||||||
natificationHidden: false,
|
natificationHidden: false,
|
||||||
natificationReady: false,
|
natificationReady: false,
|
||||||
notificationClass: null,
|
notificationClass: null,
|
||||||
|
reportUnreadNumber: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -273,6 +288,9 @@ export default {
|
|||||||
if (this.$Electron) {
|
if (this.$Electron) {
|
||||||
this.$Electron.ipcRenderer.send('setDockBadge', 0);
|
this.$Electron.ipcRenderer.send('setDockBadge', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 工作汇报未读标记
|
||||||
|
this.reportUnread();
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
@ -334,7 +352,8 @@ export default {
|
|||||||
{path: 'clearCache', name: '清除缓存'},
|
{path: 'clearCache', name: '清除缓存'},
|
||||||
{path: 'system', name: '系统设置', divided: true},
|
{path: 'system', name: '系统设置', divided: true},
|
||||||
{path: 'priority', name: '任务等级'},
|
{path: 'priority', name: '任务等级'},
|
||||||
{path: 'allUser', name: '团队管理', divided: true},
|
{path: 'workReport', name: '工作报告', divided: true},
|
||||||
|
{path: 'allUser', name: '团队管理'},
|
||||||
{path: 'allProject', name: '所有项目'},
|
{path: 'allProject', name: '所有项目'},
|
||||||
{path: 'archivedProject', name: '已归档的项目'}
|
{path: 'archivedProject', name: '已归档的项目'}
|
||||||
]
|
]
|
||||||
@ -343,7 +362,8 @@ export default {
|
|||||||
{path: 'personal', name: '个人设置'},
|
{path: 'personal', name: '个人设置'},
|
||||||
{path: 'password', name: '密码设置'},
|
{path: 'password', name: '密码设置'},
|
||||||
{path: 'clearCache', name: '清除缓存'},
|
{path: 'clearCache', name: '清除缓存'},
|
||||||
{path: 'archivedProject', name: '已归档的项目', divided: true}
|
{path: 'workReport', name: '工作报告', divided: true},
|
||||||
|
{path: 'archivedProject', name: '已归档的项目'}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -474,6 +494,9 @@ export default {
|
|||||||
case 'archivedProject':
|
case 'archivedProject':
|
||||||
this.archivedProjectShow = true;
|
this.archivedProjectShow = true;
|
||||||
return;
|
return;
|
||||||
|
case 'workReport':
|
||||||
|
this.workReportShow = true;
|
||||||
|
return;
|
||||||
case 'clearCache':
|
case 'clearCache':
|
||||||
this.$store.dispatch("handleClearCache", null).then(() => {
|
this.$store.dispatch("handleClearCache", null).then(() => {
|
||||||
$A.setStorage("clearCache", $A.randomString(6))
|
$A.setStorage("clearCache", $A.randomString(6))
|
||||||
@ -683,6 +706,17 @@ export default {
|
|||||||
this.natificationHidden = !!document[hiddenProperty]
|
this.natificationHidden = !!document[hiddenProperty]
|
||||||
}
|
}
|
||||||
document.addEventListener(visibilityChangeEvent, visibilityChangeListener);
|
document.addEventListener(visibilityChangeEvent, visibilityChangeListener);
|
||||||
|
},
|
||||||
|
|
||||||
|
reportUnread() {
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'report/unread',
|
||||||
|
method: 'get',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
// data 结果数据
|
||||||
|
this.reportUnreadNumber = data.total ? data.total : 0;
|
||||||
|
// msg 结果描述
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
resources/assets/js/pages/manage/components/Report.vue
Normal file
65
resources/assets/js/pages/manage/components/Report.vue
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<div class="report">
|
||||||
|
<Tabs v-model="reportTabs">
|
||||||
|
<TabPane label="填写" name="edit" icon="md-create">
|
||||||
|
<ReportEdit :id="reportId" @saveSuccess="saveSuccess">填写</ReportEdit>
|
||||||
|
</TabPane>
|
||||||
|
<TabPane label="我的汇报" name="my" icon="ios-paper-plane-outline">
|
||||||
|
<ReportMy v-if="reportTabs === 'my'" @detail="showDetail" @edit="editReport">我的汇报</ReportMy>
|
||||||
|
</TabPane>
|
||||||
|
<TabPane label="收到的汇报" name="receive" icon="ios-paper-outline">
|
||||||
|
<ReportReceive v-if="reportTabs === 'receive'" @detail="showDetail">收到的汇报</ReportReceive>
|
||||||
|
</TabPane>
|
||||||
|
</Tabs>
|
||||||
|
<Drawer v-model="showDetailDrawer" width="900px" :closable="false">
|
||||||
|
<ReportDetail :data="detailData" @closeDrawer="closeDrawer"/>
|
||||||
|
</Drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ReportEdit from "./ReportEdit"
|
||||||
|
import ReportMy from "./ReportMy"
|
||||||
|
import ReportReceive from "./ReportReceive"
|
||||||
|
import ReportDetail from "./ReportDetail"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Report",
|
||||||
|
components: {
|
||||||
|
ReportEdit, ReportMy, ReportReceive,ReportDetail
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
reportTabs: "my",
|
||||||
|
showDetailDrawer: false,
|
||||||
|
detailData: {},
|
||||||
|
reportId: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
closeDrawer(){
|
||||||
|
this.showDetailDrawer = false
|
||||||
|
},
|
||||||
|
showDetail(row) {
|
||||||
|
this.showDetailDrawer = true;
|
||||||
|
this.detailData = row;
|
||||||
|
//1.5秒后执行
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$emit("read");
|
||||||
|
}, 1500);
|
||||||
|
},
|
||||||
|
editReport(id) {
|
||||||
|
this.reportId = id;
|
||||||
|
this.reportTabs = "edit";
|
||||||
|
},
|
||||||
|
saveSuccess() {
|
||||||
|
this.reportId = 0;
|
||||||
|
this.reportTabs = "my";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
87
resources/assets/js/pages/manage/components/ReportDetail.vue
Normal file
87
resources/assets/js/pages/manage/components/ReportDetail.vue
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<div class="report-detail">
|
||||||
|
|
||||||
|
<p class="report-title"><Icon type="ios-arrow-back" class="report-title-icon" @click="closeDrawer"/> {{ data.title }}</p>
|
||||||
|
<Divider />
|
||||||
|
<div class="report-profile">
|
||||||
|
<Row>
|
||||||
|
<Col span="2">
|
||||||
|
<div class="report-submitter"><p>{{ $L('汇报人') }} </p></div>
|
||||||
|
</Col>
|
||||||
|
<Col span="6">
|
||||||
|
<div class="report-submitter">
|
||||||
|
<UserAvatar :userid="data.userid" :size="28"/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col span="2">
|
||||||
|
<div class="report-submitter"> <p>{{ $L('提交时间') }}</p></div>
|
||||||
|
</Col>
|
||||||
|
<Col span="6">
|
||||||
|
<div class="report-submitter">
|
||||||
|
<div>{{ data.created_at }}</div>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col span="2">
|
||||||
|
<div class="report-submitter"><p>{{ $L('汇报对象') }}</p></div>
|
||||||
|
</Col>
|
||||||
|
<Col span="6">
|
||||||
|
<div class="report-submitter">
|
||||||
|
<UserAvatar v-for="item in data.receives" :key="item" :userid="item" :size="28"/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
<Row class="report-main">
|
||||||
|
<Col span="2">
|
||||||
|
<div class="report-submitter"><p>{{ $L('汇报内容') }}</p></div>
|
||||||
|
</Col>
|
||||||
|
<Col span="22">
|
||||||
|
<div class="report-content" v-html="data.content">
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "ReportDetail",
|
||||||
|
props: {
|
||||||
|
data: {
|
||||||
|
default: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.data.id > 0) this.sendRead();
|
||||||
|
console.log(this.data)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
data() {
|
||||||
|
if (this.data.id > 0) this.sendRead();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
sendRead() {
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'report/read',
|
||||||
|
data: {ids: [this.data.id]},
|
||||||
|
method: 'get',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
// data 结果数据
|
||||||
|
// msg 结果描述
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
// msg 错误原因
|
||||||
|
});
|
||||||
|
},
|
||||||
|
closeDrawer(){
|
||||||
|
this.$emit('closeDrawer')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
236
resources/assets/js/pages/manage/components/ReportEdit.vue
Normal file
236
resources/assets/js/pages/manage/components/ReportEdit.vue
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
<template>
|
||||||
|
<Form class="report-box" label-position="top" @submit.native.prevent>
|
||||||
|
<Row class="report-row report-row-header" >
|
||||||
|
<Col span="2"><p class="report-titles">{{ $L("汇报类型") }}</p></Col>
|
||||||
|
<Col span="6">
|
||||||
|
<RadioGroup type="button" button-style="solid" v-model="reportData.type" @on-change="typeChange" class="report-radiogroup">
|
||||||
|
<Radio label="weekly">{{ $L("周报") }}</Radio>
|
||||||
|
<Radio label="daily">{{ $L("日报") }}</Radio>
|
||||||
|
</RadioGroup>
|
||||||
|
</Col>
|
||||||
|
<Col span="6">
|
||||||
|
<ButtonGroup class="report-buttongroup">
|
||||||
|
<Tooltip class="report-poptip" trigger="hover" :content="prevCycleText" placement="bottom">
|
||||||
|
<Button type="primary" @click="prevCycle">
|
||||||
|
<Icon type="ios-arrow-back" />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
<div class="report-buttongroup-shu"></div>
|
||||||
|
<Tooltip class="report-poptip" trigger="hover" :content="nextCycleText" placement="bottom">
|
||||||
|
<Button type="primary" @click="nextCycle" :disabled="reportData.offset >= 0">
|
||||||
|
<Icon type="ios-arrow-forward" />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</ButtonGroup>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row class="report-row report-row-header">
|
||||||
|
<Col span="2"><p class="report-titles">{{ $L("汇报名称") }}</p></Col>
|
||||||
|
<Col span="22">
|
||||||
|
<Input v-model="reportData.title" disabled placeholder=""></Input>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row class="report-row report-row-header">
|
||||||
|
<Col span="2"><p class="report-titles">{{ $L("汇报对象") }}</p></Col>
|
||||||
|
<Col span="16">
|
||||||
|
<UserInput
|
||||||
|
v-if="userInputShow"
|
||||||
|
v-model="reportData.receive"
|
||||||
|
:placeholder="$L('选择接收人')" />
|
||||||
|
</Col>
|
||||||
|
<Col span="6"><a class="report-row-a" href="javascript:void(0);" @click="getLastSubmitter"><Icon class="report-row-a-icon" type="ios-share-outline" />{{ $L("使用上一次提交的接收人") }}</a></Col>
|
||||||
|
</Row>
|
||||||
|
<Row class="report-row report-row-content">
|
||||||
|
<Col span="2"><p class="report-titles">{{ $L("汇报内容") }}</p></Col>
|
||||||
|
<Col span="22">
|
||||||
|
<FormItem>
|
||||||
|
<TEditor v-model="reportData.content" height="550px"/>
|
||||||
|
</FormItem>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row class="report-row report-row-foot">
|
||||||
|
<Col span="2"></Col>
|
||||||
|
<Col span="4">
|
||||||
|
<FormItem>
|
||||||
|
<Button type="primary" @click="handleSubmit" class="report-bottom">提交</Button>
|
||||||
|
<!-- <Button type="primary" @click="prevCycle">{{ prevCycleText }}</Button>-->
|
||||||
|
<!-- <Button type="primary" @click="nextCycle" :disabled="reportData.offset >= 0">{{ nextCycleText }}</Button>-->
|
||||||
|
</FormItem>
|
||||||
|
</Col>
|
||||||
|
<Col span="4">
|
||||||
|
<FormItem>
|
||||||
|
<Button type="primary" class="report-bottom-save">保存</Button>
|
||||||
|
<!-- <Button type="primary" @click="prevCycle">{{ prevCycleText }}</Button>-->
|
||||||
|
<!-- <Button type="primary" @click="nextCycle" :disabled="reportData.offset >= 0">{{ nextCycleText }}</Button>-->
|
||||||
|
</FormItem>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import UserInput from "../../../components/UserInput"
|
||||||
|
|
||||||
|
const TEditor = () => import('../../../components/TEditor');
|
||||||
|
export default {
|
||||||
|
name: "ReportEdit",
|
||||||
|
components: {
|
||||||
|
TEditor, UserInput
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
default: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
reportData: {
|
||||||
|
title: ""
|
||||||
|
, content: ""
|
||||||
|
, type: "weekly"
|
||||||
|
, receive: []
|
||||||
|
, id: 0
|
||||||
|
, offset: 0 // 以当前日期为基础的周期偏移量。例如选择了上一周那么就是 -1,上一天同理。
|
||||||
|
},
|
||||||
|
disabledType: false,
|
||||||
|
userInputShow: true,
|
||||||
|
prevCycleText: "",
|
||||||
|
nextCycleText: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
id(val) {
|
||||||
|
if (this.id > 0) this.getDetail(val);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getTemplate();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initLanguage () {
|
||||||
|
this.prevCycleText = this.$L("上一周");
|
||||||
|
this.nextCycleText = this.$L("下一周");
|
||||||
|
},
|
||||||
|
handleSubmit: function () {
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'report/store',
|
||||||
|
data: this.reportData,
|
||||||
|
method: 'post',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
// data 结果数据
|
||||||
|
this.reportData.content = "";
|
||||||
|
this.reportData.receive = [];
|
||||||
|
this.disabledType = false;
|
||||||
|
// msg 结果描述
|
||||||
|
$A.messageSuccess(msg);
|
||||||
|
this.$emit("saveSuccess");
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
// msg 错误原因
|
||||||
|
$A.messageError(msg);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getTemplate() {
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'report/template',
|
||||||
|
data: {
|
||||||
|
type: this.reportData.type,
|
||||||
|
offset: this.reportData.offset
|
||||||
|
},
|
||||||
|
method: 'get',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
// data 结果数据
|
||||||
|
if (data.id) {
|
||||||
|
this.getDetail(data.id);
|
||||||
|
} else {
|
||||||
|
this.reportData.title = data.title;
|
||||||
|
this.reportData.content = data.content;
|
||||||
|
}
|
||||||
|
// msg 结果描述
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
// msg 错误原因
|
||||||
|
$A.messageError(msg);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
typeChange(value) {
|
||||||
|
// 切换汇报类型后偏移量归零
|
||||||
|
this.reportData.offset = 0;
|
||||||
|
if ( value === "weekly" ) {
|
||||||
|
this.prevCycleText = this.$L("上一周");
|
||||||
|
this.nextCycleText = this.$L("下一周");
|
||||||
|
} else {
|
||||||
|
this.prevCycleText = this.$L("上一天");
|
||||||
|
this.nextCycleText = this.$L("下一天");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.id <= 0)
|
||||||
|
this.getTemplate();
|
||||||
|
},
|
||||||
|
getDetail(reportId) {
|
||||||
|
this.userInputShow = false;
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'report/detail',
|
||||||
|
data: {
|
||||||
|
id: reportId
|
||||||
|
},
|
||||||
|
method: 'get',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
// data 结果数据
|
||||||
|
this.reportData.title = data.title;
|
||||||
|
this.reportData.content = data.content;
|
||||||
|
this.reportData.receive = data.receives;
|
||||||
|
this.reportData.type = data.type_val;
|
||||||
|
this.reportData.id = reportId;
|
||||||
|
this.disabledType = true;
|
||||||
|
this.userInputShow = true;
|
||||||
|
// msg 结果描述
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
// msg 错误原因
|
||||||
|
$A.messageError(msg);
|
||||||
|
this.userInputShow = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
prevCycle() {
|
||||||
|
this.reportData.offset -= 1;
|
||||||
|
this.disabledType = false;
|
||||||
|
this.reReportData();
|
||||||
|
this.getTemplate();
|
||||||
|
},
|
||||||
|
nextCycle() {
|
||||||
|
// 周期偏移量不允许大于0
|
||||||
|
if ( this.reportData.offset < 0 ) {
|
||||||
|
this.reportData.offset += 1;
|
||||||
|
}
|
||||||
|
this.disabledType = false;
|
||||||
|
this.reReportData();
|
||||||
|
this.getTemplate();
|
||||||
|
},
|
||||||
|
// 获取上一次接收人
|
||||||
|
getLastSubmitter() {
|
||||||
|
this.userInputShow = false;
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'report/last_submitter',
|
||||||
|
method: 'get',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
// data 结果数据
|
||||||
|
this.reportData.receive = data;
|
||||||
|
this.userInputShow = true;
|
||||||
|
// msg 结果描述
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
// msg 错误原因
|
||||||
|
$A.messageError(msg);
|
||||||
|
this.userInputShow = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
reReportData() {
|
||||||
|
this.reportData.title = "";
|
||||||
|
this.reportData.content = "";
|
||||||
|
this.reportData.receive = [];
|
||||||
|
this.reportData.id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
172
resources/assets/js/pages/manage/components/ReportMy.vue
Normal file
172
resources/assets/js/pages/manage/components/ReportMy.vue
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
<template>
|
||||||
|
<div class="report-list-wrap">
|
||||||
|
<Row class="reportmy-row report-row-header">
|
||||||
|
<Col span="2"><p class="reportmy-titles">{{ $L("汇报类型") }}</p></Col>
|
||||||
|
<Col span="6">
|
||||||
|
<Select
|
||||||
|
v-model="reportType"
|
||||||
|
style="width:95%"
|
||||||
|
:placeholder="this.$L('全部')"
|
||||||
|
@on-change="typePick"
|
||||||
|
>
|
||||||
|
<Option v-for="item in reportTypeList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
<Col span="1"></Col>
|
||||||
|
<Col span="2"><p class="reportmy-titles">{{ $L("汇报时间") }}</p></Col>
|
||||||
|
<Col span="6">
|
||||||
|
<DatePicker
|
||||||
|
type="daterange"
|
||||||
|
split-panels
|
||||||
|
:placeholder="this.$L('请选择时间')"
|
||||||
|
style="width: 95%;"
|
||||||
|
@on-change="timePick"
|
||||||
|
></DatePicker>
|
||||||
|
</Col>
|
||||||
|
<Col span="1"></Col>
|
||||||
|
<Col span="4"><Button type="primary" icon="ios-search" @click="searchTab">{{ $L("搜索") }}</Button></Col>
|
||||||
|
</Row>
|
||||||
|
<Table class="tableFill report-row-content" ref="tableRef"
|
||||||
|
:columns="columns" :data="lists"
|
||||||
|
:loading="loadIng > 0"
|
||||||
|
:no-data-text="$L(noDataText)" stripe></Table>
|
||||||
|
<Page class="page-box report-row-foot" :total="listTotal" :current="listPage" :disabled="loadIng > 0"
|
||||||
|
@on-change="setPage" @on-page-size-change="setPageSize" :page-size-opts="[10,20,30,50,100]"
|
||||||
|
placement="top" show-elevator show-sizer show-total transfer />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "ReportMy",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loadIng: 0,
|
||||||
|
columns: [],
|
||||||
|
lists: [],
|
||||||
|
listPage: 1,
|
||||||
|
listTotal: 0,
|
||||||
|
listPageSize: 10,
|
||||||
|
noDataText: "",
|
||||||
|
createAt: [],
|
||||||
|
reportType:'',
|
||||||
|
reportTypeList:[
|
||||||
|
{value:"weekly",label:'周报' },
|
||||||
|
{value:"daily",label:'日报' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getLists();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initLanguage() {
|
||||||
|
this.noDataText = this.noDataText || "数据加载中.....";
|
||||||
|
this.columns = [{
|
||||||
|
"title": this.$L("名称"),
|
||||||
|
"key": 'title',
|
||||||
|
sortable: true,
|
||||||
|
"minWidth": 120,
|
||||||
|
}, {
|
||||||
|
"title": this.$L("类型"),
|
||||||
|
"key": 'type',
|
||||||
|
"align": 'center',
|
||||||
|
sortable: true,
|
||||||
|
"maxWidth": 80,
|
||||||
|
}, {
|
||||||
|
"title": this.$L("汇报时间"),
|
||||||
|
"key": 'created_at',
|
||||||
|
"align": 'center',
|
||||||
|
sortable: true,
|
||||||
|
"maxWidth": 180,
|
||||||
|
}, {
|
||||||
|
"title": "操作",
|
||||||
|
"key": 'action',
|
||||||
|
"align": 'right',
|
||||||
|
"width": 80,
|
||||||
|
render: (h, params) => {
|
||||||
|
if (!params.row.id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let arr = [
|
||||||
|
h('ETooltip', {
|
||||||
|
props: { content: this.$L('编辑'), transfer: true, delay: 600 }
|
||||||
|
}, [h('Icon', {
|
||||||
|
props: { type: 'md-create', size: 16 },
|
||||||
|
style: { margin: '0 3px', cursor: 'pointer' },
|
||||||
|
on: {
|
||||||
|
click: () => {
|
||||||
|
this.$emit("edit", params.row.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})]),
|
||||||
|
h('ETooltip', {
|
||||||
|
props: { content: this.$L('查看'), transfer: true, delay: 600 },
|
||||||
|
style: { position: 'relative' },
|
||||||
|
}, [h('Icon', {
|
||||||
|
props: { type: 'md-eye', size: 16 },
|
||||||
|
style: { margin: '0 3px', cursor: 'pointer' },
|
||||||
|
on: {
|
||||||
|
click: () => {
|
||||||
|
this.$emit("detail", params.row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})]),
|
||||||
|
];
|
||||||
|
return h('div', arr);
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
},
|
||||||
|
getLists() {
|
||||||
|
this.loadIng = 1;
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'report/my',
|
||||||
|
data: {
|
||||||
|
page: this.listPage,
|
||||||
|
created_at: this.createAt,
|
||||||
|
type: this.reportType
|
||||||
|
},
|
||||||
|
method: 'get',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
// data 结果数据
|
||||||
|
this.lists = data.data;
|
||||||
|
this.listTotal = data.total;
|
||||||
|
if ( this.lists.length <= 0 ) {
|
||||||
|
this.noDataText = this.$L("无数据");
|
||||||
|
}
|
||||||
|
// msg 结果描述
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
// msg 错误原因
|
||||||
|
$A.messageError(msg);
|
||||||
|
}).finally( () => {
|
||||||
|
this.loadIng = 0;
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
setPage(page) {
|
||||||
|
this.listPage = page;
|
||||||
|
this.getLists();
|
||||||
|
},
|
||||||
|
setPageSize(size) {
|
||||||
|
if (Math.max($A.runNum(this.listPageSize), 10) !== size) {
|
||||||
|
this.listPageSize = size;
|
||||||
|
this.getLists();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
timePick(e){
|
||||||
|
// console.log(e)
|
||||||
|
this.createAt = e;
|
||||||
|
},
|
||||||
|
typePick(e){
|
||||||
|
// console.log(e)
|
||||||
|
},
|
||||||
|
|
||||||
|
searchTab() {
|
||||||
|
this.getLists();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
194
resources/assets/js/pages/manage/components/ReportReceive.vue
Normal file
194
resources/assets/js/pages/manage/components/ReportReceive.vue
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
<template>
|
||||||
|
<div class="report-list-wrap">
|
||||||
|
<Row class="reportmy-row report-row-header">
|
||||||
|
<Col span="2"><p class="reportmy-titles">{{ $L("汇报人") }}</p></Col>
|
||||||
|
<Col span="4">
|
||||||
|
<Input style="width:100%" v-model="username" :placeholder="$L('请输入用户名')"/>
|
||||||
|
</Col>
|
||||||
|
<Col span="1"></Col>
|
||||||
|
<Col span="2"><p class="reportmy-titles">{{ $L("汇报类型") }}</p></Col>
|
||||||
|
<Col span="4">
|
||||||
|
<Select
|
||||||
|
v-model="reportType"
|
||||||
|
style="width:100%"
|
||||||
|
:placeholder="this.$L('全部')"
|
||||||
|
@on-change="typePick"
|
||||||
|
>
|
||||||
|
<Option v-for="item in reportTypeList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
<Col span="1"></Col>
|
||||||
|
<Col span="2"><p class="reportmy-titles">{{ $L("汇报时间") }}</p></Col>
|
||||||
|
<Col span='4'>
|
||||||
|
<DatePicker
|
||||||
|
type="daterange"
|
||||||
|
split-panels
|
||||||
|
:placeholder="this.$L('请选择时间')"
|
||||||
|
style="width: 100%;"
|
||||||
|
@on-change="timePick"
|
||||||
|
></DatePicker>
|
||||||
|
</Col>
|
||||||
|
<Col span="1"></Col>
|
||||||
|
<Col span="3"><Button type="primary" icon="ios-search" @click="searchTab">{{ $L("搜索") }}</Button></Col>
|
||||||
|
</Row>
|
||||||
|
<Table class="tableFill report-row-content" ref="tableRef"
|
||||||
|
:columns="columns" :data="lists"
|
||||||
|
:loading="loadIng > 0"
|
||||||
|
:no-data-text="$L(noDataText)" stripe></Table>
|
||||||
|
<Page class="page-box report-row-foot" :total="listTotal" :current="listPage" :disabled="loadIng > 0"
|
||||||
|
@on-change="setPage" @on-page-size-change="setPageSize" :page-size-opts="[10,20,30,50,100]"
|
||||||
|
placement="top" show-elevator show-sizer show-total transfer />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "ReportReceive",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loadIng: 0,
|
||||||
|
columns: [],
|
||||||
|
lists: [],
|
||||||
|
listPage: 1,
|
||||||
|
listTotal: 0,
|
||||||
|
listPageSize: 10,
|
||||||
|
noDataText: "",
|
||||||
|
|
||||||
|
username:'',
|
||||||
|
reportType:'',
|
||||||
|
createAt: [],
|
||||||
|
reportTypeList:[
|
||||||
|
{value:"weekly",label:'周报' },
|
||||||
|
{value:"daily",label:'日报' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getLists();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initLanguage() {
|
||||||
|
this.noDataText = this.noDataText || "数据加载中.....";
|
||||||
|
this.columns = [{
|
||||||
|
"title": this.$L("标题"),
|
||||||
|
"key": 'title',
|
||||||
|
"sortable": true,
|
||||||
|
"minWidth": 120,
|
||||||
|
render: (h, params) => {
|
||||||
|
let arr = []
|
||||||
|
if(params.row.receives_user[0].pivot.read==0){
|
||||||
|
arr.push(
|
||||||
|
h('Tag', {
|
||||||
|
props: { //传递参数
|
||||||
|
color: "orange",
|
||||||
|
}
|
||||||
|
}, this.$L("未读")),
|
||||||
|
h('span',params.row.title)
|
||||||
|
)
|
||||||
|
}else {
|
||||||
|
arr.push(
|
||||||
|
h('Tag', {
|
||||||
|
props: { //传递参数
|
||||||
|
color: "lime",
|
||||||
|
}
|
||||||
|
}, this.$L("已读")),
|
||||||
|
h('span',params.row.title)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return h('div',arr)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"title": this.$L("类型"),
|
||||||
|
"key": 'type',
|
||||||
|
"align": 'center',
|
||||||
|
"sortable": true,
|
||||||
|
"maxWidth": 80,
|
||||||
|
}, {
|
||||||
|
"title": this.$L("接收时间"),
|
||||||
|
"key": 'receive_time',
|
||||||
|
"align": 'center',
|
||||||
|
"sortable": true,
|
||||||
|
"maxWidth": 180,
|
||||||
|
}, {
|
||||||
|
"title": " ",
|
||||||
|
"key": 'action',
|
||||||
|
"align": 'right',
|
||||||
|
"width": 40,
|
||||||
|
render: (h, params) => {
|
||||||
|
if (!params.row.id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let arr = [
|
||||||
|
h('ETooltip', {
|
||||||
|
props: { content: this.$L('查看'), transfer: true, delay: 600 },
|
||||||
|
style: { position: 'relative' },
|
||||||
|
}, [h('Icon', {
|
||||||
|
props: { type: 'md-eye', size: 16 },
|
||||||
|
style: { margin: '0 3px', cursor: 'pointer' },
|
||||||
|
on: {
|
||||||
|
click: () => {
|
||||||
|
this.$emit("detail", params.row)
|
||||||
|
this.lists[params.index].receives_user[0].pivot.read = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})])
|
||||||
|
];
|
||||||
|
return h('div', arr);
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
},
|
||||||
|
|
||||||
|
getLists() {
|
||||||
|
this.loadIng = 1;
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'report/receive',
|
||||||
|
data: {
|
||||||
|
page: this.listPage,
|
||||||
|
username: this.username,
|
||||||
|
created_at: this.createAt,
|
||||||
|
type: this.reportType
|
||||||
|
},
|
||||||
|
method: 'get',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
// data 结果数据
|
||||||
|
this.lists = data.data;
|
||||||
|
this.listTotal = data.total;
|
||||||
|
if ( this.lists.length <= 0 ) {
|
||||||
|
this.noDataText = this.$L("无数据");
|
||||||
|
}
|
||||||
|
// msg 结果描述
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
// msg 错误原因
|
||||||
|
$A.messageError(msg);
|
||||||
|
}).finally( () => {
|
||||||
|
this.loadIng = 0;
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
setPage(page) {
|
||||||
|
this.listPage = page;
|
||||||
|
this.getLists();
|
||||||
|
},
|
||||||
|
setPageSize(size) {
|
||||||
|
if (Math.max($A.runNum(this.listPageSize), 10) !== size) {
|
||||||
|
this.listPageSize = size;
|
||||||
|
this.getLists();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
timePick(e){
|
||||||
|
this.createAt = e;
|
||||||
|
},
|
||||||
|
typePick(e){
|
||||||
|
// console.log(e)
|
||||||
|
},
|
||||||
|
searchTab() {
|
||||||
|
this.getLists();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
14
resources/assets/sass/_.scss
vendored
Normal file
14
resources/assets/sass/_.scss
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@import "app-down";
|
||||||
|
@import "auto-tip";
|
||||||
|
@import "circle";
|
||||||
|
@import "drawer-overlay";
|
||||||
|
@import "img-update";
|
||||||
|
@import "loading";
|
||||||
|
@import "scroller-y";
|
||||||
|
@import "spinner";
|
||||||
|
@import "t-editor";
|
||||||
|
@import "quick-edit";
|
||||||
|
@import "tag-input";
|
||||||
|
@import "user-avatar";
|
||||||
|
@import "user-input";
|
||||||
|
@import "report";
|
74
resources/assets/sass/app-down.scss
vendored
Normal file
74
resources/assets/sass/app-down.scss
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
.common-app-down {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 26px;
|
||||||
|
right: 26px;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: bottom 0.3s;
|
||||||
|
&.on-client {
|
||||||
|
&[data-route=login] {
|
||||||
|
bottom: 75px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.common-app-down-notification {
|
||||||
|
.notification-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.notification-title {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #17233d;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.notification-body {
|
||||||
|
max-height: 210px;
|
||||||
|
overflow: auto;
|
||||||
|
margin: 18px 0;
|
||||||
|
.markdown-preview {
|
||||||
|
margin: -20px -12px;
|
||||||
|
h2 {
|
||||||
|
font-size: 18px !important;
|
||||||
|
padding-top: 2px !important;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
li {
|
||||||
|
padding: 2px 0 2px 2px !important;
|
||||||
|
&:after {
|
||||||
|
top: 10px !important;
|
||||||
|
width: 6px !important;
|
||||||
|
height: 6px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.notification-link {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: right;
|
||||||
|
> button + button {
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.common-app-down-link {
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 32px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #8bcf70;
|
||||||
|
border-color: #8bcf70;
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
6
resources/assets/sass/auto-tip.scss
vendored
Normal file
6
resources/assets/sass/auto-tip.scss
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.common-auto-tip {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap
|
||||||
|
}
|
14
resources/assets/sass/circle.scss
vendored
Normal file
14
resources/assets/sass/circle.scss
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
.common-circle {
|
||||||
|
border-radius: 50%;
|
||||||
|
.common-circle-path {
|
||||||
|
fill: transparent;
|
||||||
|
}
|
||||||
|
.common-circle-g-path-ring {
|
||||||
|
stroke: $primary-color;
|
||||||
|
}
|
||||||
|
.common-circle-g-path-core {
|
||||||
|
fill: $primary-color;
|
||||||
|
transform: scale(0.56);
|
||||||
|
transform-origin: 50%;
|
||||||
|
}
|
||||||
|
}
|
1
resources/assets/sass/components/_.scss
vendored
1
resources/assets/sass/components/_.scss
vendored
@ -11,3 +11,4 @@
|
|||||||
@import "tag-input";
|
@import "tag-input";
|
||||||
@import "user-avatar";
|
@import "user-avatar";
|
||||||
@import "user-input";
|
@import "user-input";
|
||||||
|
@import "report";
|
||||||
|
218
resources/assets/sass/components/report.scss
vendored
Normal file
218
resources/assets/sass/components/report.scss
vendored
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
.report {
|
||||||
|
height: 100%;
|
||||||
|
padding: 10px 20px;
|
||||||
|
.report-list-wrap {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
top: 0;
|
||||||
|
padding-top: 53px;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
.report-row-header,.report-row-foot{
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
.report-row-content{
|
||||||
|
flex:1 1 auto;
|
||||||
|
.ivu-table{
|
||||||
|
.ivu-table-body{
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-box {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
.ivu-tabs{
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
.ivu-tabs-bar{
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.ivu-tabs-content{
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: -53px;
|
||||||
|
padding-top: 53px;
|
||||||
|
}
|
||||||
|
.ivu-tabs-tabpane{
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-detail {
|
||||||
|
.report-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding-top: 20px;
|
||||||
|
.report-title-icon{
|
||||||
|
font-size: 22px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-profile {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-submitter {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
height: 28px;
|
||||||
|
line-height: 28px;
|
||||||
|
p{
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
text-align: justify;
|
||||||
|
padding-right: 12px;
|
||||||
|
&:after{
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > div {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-col{
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-content {
|
||||||
|
margin-top: 12px;
|
||||||
|
width: 100%;
|
||||||
|
h2{
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
ol{
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-left: 18px;
|
||||||
|
li{
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-box{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
.report-row-header,.report-row-foot{
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
.report-row-content{
|
||||||
|
flex:1 1 auto;
|
||||||
|
}
|
||||||
|
.report-row-foot{
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-row{
|
||||||
|
margin-bottom: 20px;
|
||||||
|
.report-row-a{
|
||||||
|
float: right;
|
||||||
|
line-height: 32px;
|
||||||
|
.report-row-a-icon{
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
font-size: 16px;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-bottom{
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
.report-bottom-save{
|
||||||
|
width: 120px;
|
||||||
|
background: #F4F5F7 ;
|
||||||
|
color: #515A6E;
|
||||||
|
border-color: #F4F5F7 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-titles{
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
.report-radiogroup{
|
||||||
|
background: #F4F5F7 !important;
|
||||||
|
padding: 2px !important;
|
||||||
|
border-radius: 4px!important;
|
||||||
|
.ivu-radio-wrapper{
|
||||||
|
padding: 0 30px !important;
|
||||||
|
background: #F4F5F7 !important;
|
||||||
|
color: #515A6E !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none!important;
|
||||||
|
&:before{
|
||||||
|
width: 0!important;
|
||||||
|
}
|
||||||
|
&:after{
|
||||||
|
width: 0!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-radio-focus{
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none!important;
|
||||||
|
&:after{
|
||||||
|
background: none!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-radio-wrapper-checked:not(.ivu-radio-wrapper-disabled){
|
||||||
|
background: #fff !important;
|
||||||
|
color: #8BCF70 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none!important;
|
||||||
|
border-radius: 4px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.report-buttongroup{
|
||||||
|
margin-top: 2px;
|
||||||
|
background: #F4F5F7!important;
|
||||||
|
border-radius: 4px;
|
||||||
|
.report-buttongroup-shu{
|
||||||
|
position: absolute;
|
||||||
|
left: 47px;
|
||||||
|
width: 1px;
|
||||||
|
height: 23px;
|
||||||
|
background-color: #E5E5E5;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
.ivu-btn-primary{
|
||||||
|
background: #F4F5F7!important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none!important;
|
||||||
|
color: #8BCF70 !important;
|
||||||
|
&[disabled]{
|
||||||
|
color: #515A6E !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-poptip{
|
||||||
|
.ivu-tooltip-inner{
|
||||||
|
min-width: 60px !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.reportmy-row{
|
||||||
|
margin-bottom: 20px;
|
||||||
|
.reportmy-titles{
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-main{
|
||||||
|
.report-submitter{
|
||||||
|
padding-top: 13px;
|
||||||
|
}
|
||||||
|
}
|
136
resources/assets/sass/drawer-overlay.scss
vendored
Normal file
136
resources/assets/sass/drawer-overlay.scss
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
.drawer-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
box-sizing: border-box;
|
||||||
|
pointer-events: none;
|
||||||
|
background: rgba(0, 0, 0, 0.76);
|
||||||
|
outline: none;
|
||||||
|
opacity: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.overlay-mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.overlay-close {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: flex-end;
|
||||||
|
> a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
color: #dbdbde;
|
||||||
|
&:hover {
|
||||||
|
color: #fff
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-resize {
|
||||||
|
width: 100%;
|
||||||
|
height: 5px;
|
||||||
|
margin-bottom: -5px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-content {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 18px 18px 0 0;
|
||||||
|
transform: translate(0, 15%) scale(0.98);
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.overlay-visible {
|
||||||
|
pointer-events: auto;
|
||||||
|
opacity: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
.overlay-body {
|
||||||
|
.overlay-content {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate(0, 0) scale(1);
|
||||||
|
transition: opacity 0.2s ease, transform 0.3s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.overlay-hide {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
.overlay-body {
|
||||||
|
.overlay-content {
|
||||||
|
transform: translate(0, 15%) scale(0.98);
|
||||||
|
transition: opacity 0.2s ease, transform 0.2s ease
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
.overlay-body {
|
||||||
|
flex-direction: row;
|
||||||
|
.overlay-close {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.overlay-resize {
|
||||||
|
width: 5px;
|
||||||
|
height: 100%;
|
||||||
|
margin-right: -5px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.overlay-content {
|
||||||
|
transform: translate(15%, 0) scale(0.98);
|
||||||
|
border-radius: 18px 0 0 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.overlay-visible {
|
||||||
|
.overlay-body {
|
||||||
|
.overlay-content {
|
||||||
|
transform: translate(0, 0) scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.overlay-hide {
|
||||||
|
.overlay-body {
|
||||||
|
.overlay-content {
|
||||||
|
transform: translate(15%, 0) scale(0.98);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
255
resources/assets/sass/img-update.scss
vendored
Normal file
255
resources/assets/sass/img-update.scss
vendored
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
.img-upload-modal {
|
||||||
|
.ivu-modal-mask {
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-modal-no-mask {
|
||||||
|
background-color: rgba(55, 55, 55, .2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-modal-wrap {
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imgcomp-upload-list {
|
||||||
|
display: inline-block;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 60px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
|
||||||
|
margin-right: 4px;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
.imgcomp-upload-img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imgcomp-upload-list-cover {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(0, 0, 0, .6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.imgcomp-upload-list-cover i {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0;
|
||||||
|
transition: all .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imgcomp-upload-list-cover i:hover {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-progress {
|
||||||
|
height: 100%;
|
||||||
|
.ivu-progress-outer {
|
||||||
|
background-color: rgba(0, 0, 0, 0.68);
|
||||||
|
height: 100%;
|
||||||
|
.ivu-progress-inner {
|
||||||
|
width: 88%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imgcomp-upload-list:hover .imgcomp-upload-list-cover {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-upload-foot {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.img-upload-foot-input {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.img-upload-foot-httptitle {
|
||||||
|
cursor: pointer;
|
||||||
|
padding-left: 3px;
|
||||||
|
margin-right: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-box {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
display: inline-block;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px dashed #dddee1;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
.add-box-icon {
|
||||||
|
i {
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-box-upload {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
color: #ffffff;
|
||||||
|
padding-top: 9px;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
|
||||||
|
.add-box-item {
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.ivu-upload-drag, .ivu-upload-drag:hover {
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
transition: all .2s;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-box-item:hover {
|
||||||
|
span {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
em {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-box:hover {
|
||||||
|
border-color: rgba(0, 0, 0, .6);
|
||||||
|
|
||||||
|
.add-box-upload {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.callback-add-box {
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
height: 25px;
|
||||||
|
line-height: 25px;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
.add-box-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-box-upload {
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
background: transparent;
|
||||||
|
color: #333;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: inline-block;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.browse-load {
|
||||||
|
margin: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browse-list {
|
||||||
|
max-height: 540px;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.browse-item {
|
||||||
|
margin: 10px 15px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.browse-img {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKoAAABxCAAAAABg5GeyAAACW0lEQVR4Ae3XVRLjMBAE0L3/rSwKM3OcSNPyLVYOLvM6UD0Bd03LVe9XH+RlhlRSSSWVVFJJJZVUUkkllVRSSSWVVFJJJZVUUkl9WyqppJJKKqmkkgpURP17xngOAR5NxW5wlJ9MaLQh83F4NHWmd/gZtdVBaOldfDB1bq5UpJFbFOC6LKnYrkRO209PAw+hIuzWB8Ep5es8HvYo4z4tE1X8UeRwlMM2D5Bzkc7kj6Bi3VTKDDwEeUcrMxrUvGDXTnHa6kK69SDN9sgq1clxKSbNHqqnYmdri81Q9QHf1JPt1Frncaib2XbiTKL2GkHaurnY9LOulMV0O7G6Kw+g9sw2ohhm62KezVJaaufjWC1TnOkr1exilJ7Ji0vxCCqO9V4UwV4PYr9+apouhGYLKfnahdpqegjmeoXOpXgANe70pKT6Zhu19qkY2nC0PZS527lQOyInqr8Uvc5jqfUb1X+PGh5IhW90S2quh3FQC2XRcF66TUkTXPcLKm5FtdR9RJq+2hWII7UpFtmsQLEyzsdJtkxxpr6gLotbUSlV9yeT0Trmzk2XPdUThLYarUbWOY9j04xXQ2u+pMZLYSumGmNUH3HbM9qOAwSHodN2Pks25F2j3aI7+IxqNsB+YLWb16ukSjiW4xNB0gMoMfApBS/XZQgi3p9/5RsiKNKZEOwYFVIF5VyTyD19sbyjIJiNJRZxpNbx2S8sGKvGZNHJBniBu9Wy5WxjGuQFqIAcBHiRGyt4ua5gSCWVVFJJJZVUUkkllVRSSSWVVFJJJZVUUkkllVRSSSWVVFI/AgO0SXIVYHeGAAAAAElFTkSuQmCC);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browse-title {
|
||||||
|
display: block;
|
||||||
|
width: 64px;
|
||||||
|
margin-top: 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browse-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
font-size: 36px;
|
||||||
|
padding-top: 15px;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.browse-list-disabled {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browse-list-disabled:after {
|
||||||
|
position: absolute;
|
||||||
|
content: '';
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(255, 255, 255, 0.9);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
@ -180,6 +180,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.dialog-action {
|
||||||
|
align-self: flex-start;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
&.history {
|
&.history {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
11
resources/assets/sass/pages/page-login.scss
vendored
11
resources/assets/sass/pages/page-login.scss
vendored
@ -79,6 +79,17 @@
|
|||||||
.login-switch {
|
.login-switch {
|
||||||
color: #aaaaaa;
|
color: #aaaaaa;
|
||||||
}
|
}
|
||||||
|
.login-input-tips-box{
|
||||||
|
position: relative;
|
||||||
|
.login-input-tips{
|
||||||
|
font-size: 12px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: -20px;
|
||||||
|
color: #c7c7c7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.login-bottom {
|
.login-bottom {
|
||||||
|
58
resources/assets/sass/quick-edit.scss
vendored
Executable file
58
resources/assets/sass/quick-edit.scss
vendored
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
.quick-edit {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 100%;
|
||||||
|
.quick-input {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 100%;
|
||||||
|
position: relative;
|
||||||
|
.quick-loading {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 8px;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.common-loading {
|
||||||
|
margin: 0;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.quick-text {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
.quick-icon {
|
||||||
|
display: none;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
&.quick-always {
|
||||||
|
.quick-icon {
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 0.3;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.quick-icon {
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-table-row-hover {
|
||||||
|
.quick-edit {
|
||||||
|
.quick-icon {
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
218
resources/assets/sass/report.scss
vendored
Normal file
218
resources/assets/sass/report.scss
vendored
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
.report {
|
||||||
|
height: 100%;
|
||||||
|
padding: 10px 20px;
|
||||||
|
.report-list-wrap {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
top: 0;
|
||||||
|
padding-top: 53px;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
.report-row-header,.report-row-foot{
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
.report-row-content{
|
||||||
|
flex:1 1 auto;
|
||||||
|
.ivu-table{
|
||||||
|
.ivu-table-body{
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-box {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
.ivu-tabs{
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
.ivu-tabs-bar{
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.ivu-tabs-content{
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: -53px;
|
||||||
|
padding-top: 53px;
|
||||||
|
}
|
||||||
|
.ivu-tabs-tabpane{
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-detail {
|
||||||
|
.report-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding-top: 20px;
|
||||||
|
.report-title-icon{
|
||||||
|
font-size: 22px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-profile {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-submitter {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
height: 28px;
|
||||||
|
line-height: 28px;
|
||||||
|
p{
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
text-align: justify;
|
||||||
|
padding-right: 12px;
|
||||||
|
&:after{
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > div {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-col{
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-content {
|
||||||
|
margin-top: 12px;
|
||||||
|
width: 100%;
|
||||||
|
h2{
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
ol{
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-left: 18px;
|
||||||
|
li{
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-box{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
.report-row-header,.report-row-foot{
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
.report-row-content{
|
||||||
|
flex:1 1 auto;
|
||||||
|
}
|
||||||
|
.report-row-foot{
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-row{
|
||||||
|
margin-bottom: 20px;
|
||||||
|
.report-row-a{
|
||||||
|
float: right;
|
||||||
|
line-height: 32px;
|
||||||
|
.report-row-a-icon{
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
font-size: 16px;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-bottom{
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
.report-bottom-save{
|
||||||
|
width: 120px;
|
||||||
|
background: #F4F5F7 ;
|
||||||
|
color: #515A6E;
|
||||||
|
border-color: #F4F5F7 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-titles{
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
.report-radiogroup{
|
||||||
|
background: #F4F5F7 !important;
|
||||||
|
padding: 2px !important;
|
||||||
|
border-radius: 4px!important;
|
||||||
|
.ivu-radio-wrapper{
|
||||||
|
padding: 0 30px !important;
|
||||||
|
background: #F4F5F7 !important;
|
||||||
|
color: #515A6E !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none!important;
|
||||||
|
&:before{
|
||||||
|
width: 0!important;
|
||||||
|
}
|
||||||
|
&:after{
|
||||||
|
width: 0!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-radio-focus{
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none!important;
|
||||||
|
&:after{
|
||||||
|
background: none!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-radio-wrapper-checked:not(.ivu-radio-wrapper-disabled){
|
||||||
|
background: #fff !important;
|
||||||
|
color: #8BCF70 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none!important;
|
||||||
|
border-radius: 4px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.report-buttongroup{
|
||||||
|
margin-top: 2px;
|
||||||
|
background: #F4F5F7!important;
|
||||||
|
border-radius: 4px;
|
||||||
|
.report-buttongroup-shu{
|
||||||
|
position: absolute;
|
||||||
|
left: 47px;
|
||||||
|
width: 1px;
|
||||||
|
height: 23px;
|
||||||
|
background-color: #E5E5E5;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
.ivu-btn-primary{
|
||||||
|
background: #F4F5F7!important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none!important;
|
||||||
|
color: #8BCF70 !important;
|
||||||
|
&[disabled]{
|
||||||
|
color: #515A6E !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-poptip{
|
||||||
|
.ivu-tooltip-inner{
|
||||||
|
min-width: 60px !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.reportmy-row{
|
||||||
|
margin-bottom: 20px;
|
||||||
|
.reportmy-titles{
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.report-main{
|
||||||
|
.report-submitter{
|
||||||
|
padding-top: 13px;
|
||||||
|
}
|
||||||
|
}
|
19
resources/assets/sass/scroller-y.scss
vendored
Executable file
19
resources/assets/sass/scroller-y.scss
vendored
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
.app-scroller-y {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
.app-scroller-bottom {
|
||||||
|
height: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
&.static {
|
||||||
|
position: static;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
20
resources/assets/sass/spinner.scss
vendored
Normal file
20
resources/assets/sass/spinner.scss
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.common-spinner {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9999;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
|
||||||
|
.common-circular {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
118
resources/assets/sass/t-editor.scss
vendored
Executable file
118
resources/assets/sass/t-editor.scss
vendored
Executable file
@ -0,0 +1,118 @@
|
|||||||
|
.teditor-box,
|
||||||
|
.teditor-transfer {
|
||||||
|
.tox {
|
||||||
|
&.tox-silver-sink {
|
||||||
|
z-index: 13000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.teditor-box {
|
||||||
|
position: relative;
|
||||||
|
min-height: 22px;
|
||||||
|
|
||||||
|
.icon-inline {
|
||||||
|
color: #bbbbbb;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox-tinymce {
|
||||||
|
box-shadow: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-color: #dddee1;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.tox-statusbar {
|
||||||
|
span.tox-statusbar__branding {
|
||||||
|
a {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox-tbtn--bespoke {
|
||||||
|
.tox-tbtn__select-label {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.teditor-transfer {
|
||||||
|
background-color: #ffffff;
|
||||||
|
|
||||||
|
.tox-toolbar {
|
||||||
|
> div:last-child {
|
||||||
|
> button:last-child {
|
||||||
|
margin-right: 64px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-modal-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-modal-close {
|
||||||
|
top: 7px;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.teditor-transfer-body {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox-tinymce {
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
.tox-statusbar {
|
||||||
|
span.tox-statusbar__branding {
|
||||||
|
a {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.teditor-loadstyle {
|
||||||
|
width: 100%;
|
||||||
|
height: 180px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.teditor-loadedstyle {
|
||||||
|
width: 100%;
|
||||||
|
max-height: inherit;
|
||||||
|
overflow: inherit;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-control {
|
||||||
|
display: none;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tox-tinymce-inline {
|
||||||
|
z-index: 100000;
|
||||||
|
}
|
93
resources/assets/sass/tag-input.scss
vendored
Executable file
93
resources/assets/sass/tag-input.scss
vendored
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
.common-tag-input {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 2px 7px;
|
||||||
|
border: 1px solid #dddee1;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #495060;
|
||||||
|
background: #fff;
|
||||||
|
position: relative;
|
||||||
|
cursor: text;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: normal;
|
||||||
|
transition: all .2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #a2d98d;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.focus {
|
||||||
|
border-color: #a2d98d;
|
||||||
|
box-shadow: 0 0 0 2px rgba(139,207,112,.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-item, .tags-input {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
color: #495060;
|
||||||
|
background-color: #f1f8ff;
|
||||||
|
border-radius: 3px;
|
||||||
|
line-height: 22px;
|
||||||
|
margin: 2px 6px 2px 0;
|
||||||
|
padding: 0 20px 0 6px;
|
||||||
|
|
||||||
|
.tags-content {
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-del {
|
||||||
|
width: 20px;
|
||||||
|
height: 22px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
top: -1px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-input {
|
||||||
|
max-width: 80%;
|
||||||
|
padding: 0;
|
||||||
|
background-color: inherit;
|
||||||
|
border: none;
|
||||||
|
color: inherit;
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
outline: none;
|
||||||
|
resize: none;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-input::placeholder {
|
||||||
|
color: #bbbbbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags-placeholder {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: -1;
|
||||||
|
color: rgba(255, 255, 255, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.common-tag-input::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
.ivu-form-item-error {
|
||||||
|
.common-tag-input {
|
||||||
|
border-color: #ed4014;
|
||||||
|
&:hover {
|
||||||
|
border-color: #ed4014;
|
||||||
|
}
|
||||||
|
&.focus {
|
||||||
|
border-color: #ed4014;
|
||||||
|
box-shadow: 0 0 0 2px rgba(237,64,20,.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
resources/assets/sass/user-avatar.scss
vendored
Executable file
73
resources/assets/sass/user-avatar.scss
vendored
Executable file
@ -0,0 +1,73 @@
|
|||||||
|
.common-avatar {
|
||||||
|
position: relative;
|
||||||
|
&.avatar-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.avatar-box {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.avatar-default {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.avatar-text {
|
||||||
|
background-color: $primary-color;
|
||||||
|
> span {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> em {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ff9900;
|
||||||
|
border: 1px solid #ffffff;
|
||||||
|
transform-origin: right bottom;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
&.online {
|
||||||
|
> em {
|
||||||
|
background-color: $primary-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.avatar-name {
|
||||||
|
padding-left: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.common-avatar-transfer {
|
||||||
|
padding: 4px 2px;
|
||||||
|
line-height: 1.5;
|
||||||
|
> p {
|
||||||
|
padding: 1px 2px;
|
||||||
|
}
|
||||||
|
.avatar-icons {
|
||||||
|
margin-top: 12px;
|
||||||
|
border-top: 1px solid rgba(244, 244, 245, 0.5);
|
||||||
|
padding: 8px 0 2px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
> i {
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 22px;
|
||||||
|
margin-right: 12px;
|
||||||
|
color: #F4F4F5;
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
70
resources/assets/sass/user-input.scss
vendored
Executable file
70
resources/assets/sass/user-input.scss
vendored
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
.common-user {
|
||||||
|
position: relative;
|
||||||
|
white-space: normal;
|
||||||
|
.common-user-loading {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
bottom: 0;
|
||||||
|
right: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.common-loading {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.hidden-input {
|
||||||
|
.ivu-select-selection {
|
||||||
|
padding: 0 4px;
|
||||||
|
.ivu-select-input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.common-user-transfer {
|
||||||
|
.user-input-option {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.user-input-avatar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.avatar {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
line-height: 26px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.user-input-nickname {
|
||||||
|
margin-left: 10px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.user-input-userid {
|
||||||
|
margin-left: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #cccccc;
|
||||||
|
transition: margin 0.1s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ivu-select-item {
|
||||||
|
&.ivu-select-item-selected {
|
||||||
|
&:after {
|
||||||
|
top: 8px;
|
||||||
|
}
|
||||||
|
.user-input-option {
|
||||||
|
.user-input-userid {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.user-drop-prepend {
|
||||||
|
text-align: center;
|
||||||
|
color: #c5c8ce;
|
||||||
|
line-height: 20px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-bottom: 1px solid #f1f1f1;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
use App\Http\Controllers\Api\DialogController;
|
use App\Http\Controllers\Api\DialogController;
|
||||||
use App\Http\Controllers\Api\FileController;
|
use App\Http\Controllers\Api\FileController;
|
||||||
use App\Http\Controllers\Api\ProjectController;
|
use App\Http\Controllers\Api\ProjectController;
|
||||||
|
use App\Http\Controllers\Api\ReportController;
|
||||||
use App\Http\Controllers\Api\SystemController;
|
use App\Http\Controllers\Api\SystemController;
|
||||||
use App\Http\Controllers\Api\UsersController;
|
use App\Http\Controllers\Api\UsersController;
|
||||||
use App\Http\Controllers\IndexController;
|
use App\Http\Controllers\IndexController;
|
||||||
@ -39,6 +40,9 @@ Route::prefix('api')->middleware(['webapi'])->group(function () {
|
|||||||
// 文件
|
// 文件
|
||||||
Route::any('file/{method}', FileController::class);
|
Route::any('file/{method}', FileController::class);
|
||||||
Route::any('file/{method}/{action}', FileController::class);
|
Route::any('file/{method}/{action}', FileController::class);
|
||||||
|
// 报告
|
||||||
|
Route::any('report/{method}', ReportController::class);
|
||||||
|
Route::any('report/{method}/{action}', ReportController::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user